Merge branch 'master' of https://github.com/highfidelity/hifi into domain-tunnel

This commit is contained in:
Stephen Birarda 2014-10-10 14:30:43 -07:00
commit 21114d5f56
14 changed files with 590 additions and 143 deletions

View file

@ -152,7 +152,6 @@ $(document).ready(function(){
})
$('#settings-form').on('change', 'select', function(){
console.log("Changed" + $(this))
$("input[name='" + $(this).attr('data-hidden-input') + "']").val($(this).val()).change()
})

280
examples/gamepad.js Normal file
View file

@ -0,0 +1,280 @@
//
// controller.js
// examples
//
// Created by Ryan Huffman on 10/9/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// TODO Update to work with any controller that is plugged in.
var CONTROLLER_NAMES = [
"Wireless 360 Controller",
"Controller (XBOX 360 For Windows)",
"Controller", // Wired 360 controller
]
for (var i = 0; i < CONTROLLER_NAMES.length; i++) {
gamepad = Joysticks.joystickWithName(CONTROLLER_NAMES[i]);
if (gamepad) {
print("Found controller: " + CONTROLLER_NAMES[i]);
break;
}
}
if (!gamepad) {
print("No gamepad found.");
}
// Controller axis/button mappings
var GAMEPAD = {
AXES: {
LEFT_JOYSTICK_X: 0,
LEFT_JOYSTICK_Y: 1,
RIGHT_JOYSTICK_X: 2,
RIGHT_JOYSTICK_Y: 3,
LEFT_TRIGGER: 4,
RIGHT_TRIGGER: 5,
},
BUTTONS: {
DPAD_UP: 0,
DPAD_DOWN: 1,
DPAD_LEFT: 2,
DPAD_RIGHT: 3,
LEFT_JOYSTICK: 6,
RIGHT_JOYSTICK: 7,
LEFT_BUMPER: 8,
RIGHT_BUMPER: 9,
// Face buttons, ABXY on an XBOX controller
FACE_BOTTOM: 11,
FACE_RIGHT: 12,
FACE_LEFT: 13,
FACE_TOP: 14,
}
}
// Button/axis mappings
var AXIS_STRAFE = GAMEPAD.AXES.LEFT_JOYSTICK_X;
var AXIS_FORWARD = GAMEPAD.AXES.LEFT_JOYSTICK_Y;
var AXIS_ROTATE = GAMEPAD.AXES.RIGHT_JOYSTICK_X;
var BUTTON_TURN_AROUND = GAMEPAD.BUTTONS.RIGHT_JOYSTICK;
var BUTTON_FLY_UP = GAMEPAD.BUTTONS.RIGHT_BUMPER;
var BUTTON_FLY_DOWN = GAMEPAD.BUTTONS.LEFT_BUMPER
var BUTTON_WARP = GAMEPAD.BUTTONS.FACE_BOTTOM;
var BUTTON_WARP_FORWARD = GAMEPAD.BUTTONS.DPAD_UP;
var BUTTON_WARP_BACKWARD = GAMEPAD.BUTTONS.DPAD_DOWN;
var BUTTON_WARP_LEFT = GAMEPAD.BUTTONS.DPAD_LEFT;
var BUTTON_WARP_RIGHT = GAMEPAD.BUTTONS.DPAD_RIGHT;
// Distance in meters to warp via BUTTON_WARP_*
var WARP_DISTANCE = 1;
// Walk speed in m/s
var MOVE_SPEED = 2;
// Amount to rotate in radians
var ROTATE_INCREMENT = Math.PI / 8;
// Pick from above where we want to warp
var WARP_PICK_OFFSET = { x: 0, y: 10, z: 0 };
// When warping, the warp position will snap to a target below the current warp position.
// This is the max distance it will snap to.
var WARP_PICK_MAX_DISTANCE = 100;
var flyDownButtonState = false;
var flyUpButtonState = false;
// Current move direction, axis aligned - that is, looking down and moving forward
// will not move you into the ground, but instead will keep you on the horizontal plane.
var moveDirection = { x: 0, y: 0, z: 0 };
var warpActive = false;
var warpPosition = { x: 0, y: 0, z: 0 };
var WARP_SPHERE_SIZE = 1;
var warpSphere = Overlays.addOverlay("sphere", {
position: { x: 0, y: 0, z: 0 },
size: WARP_SPHERE_SIZE,
color: { red: 0, green: 255, blue: 0 },
alpha: 1.0,
solid: true,
visible: false,
});
var WARP_LINE_HEIGHT = 10;
var warpLine = Overlays.addOverlay("line3d", {
position: { x: 0, y: 0, z:0 },
end: { x: 0, y: 0, z: 0 },
color: { red: 0, green: 255, blue: 255},
alpha: 1,
lineWidth: 5,
visible: false,
});
function copyVec3(vec) {
return { x: vec.x, y: vec.y, z: vec.z };
}
function activateWarp() {
if (warpActive) return;
warpActive = true;
updateWarp();
}
function updateWarp() {
if (!warpActive) return;
var look = Quat.getFront(Camera.getOrientation());
var pitch = Math.asin(look.y);
// Get relative to looking straight down
pitch += Math.PI / 2;
// Scale up
pitch *= 2;
var distance = pitch * pitch * pitch;
var warpDirection = Vec3.normalize({ x: look.x, y: 0, z: look.z });
warpPosition = Vec3.multiply(warpDirection, distance);
warpPosition = Vec3.sum(MyAvatar.position, warpPosition);
var pickRay = {
origin: Vec3.sum(warpPosition, WARP_PICK_OFFSET),
direction: { x: 0, y: -1, z: 0 }
};
var intersection = Voxels.findRayIntersection(pickRay);
if (intersection.intersects && intersection.distance < WARP_PICK_MAX_DISTANCE) {
// Warp 1 meter above the object - this is an approximation
// TODO Get the actual offset to the Avatar's feet and plant them to
// the object.
warpPosition = Vec3.sum(intersection.intersection, { x: 0, y: 1, z:0 });
}
// Adjust overlays to match warp position
Overlays.editOverlay(warpSphere, {
position: warpPosition,
visible: true,
});
Overlays.editOverlay(warpLine, {
position: warpPosition,
end: Vec3.sum(warpPosition, { x: 0, y: WARP_LINE_HEIGHT, z: 0 }),
visible: true,
});
}
function finishWarp() {
if (!warpActive) return;
warpActive = false;
Overlays.editOverlay(warpSphere, {
visible: false,
});
Overlays.editOverlay(warpLine, {
visible: false,
});
MyAvatar.position = warpPosition;
}
function reportAxisValue(axis, newValue, oldValue) {
if (Math.abs(oldValue) < 0.2) oldValue = 0;
if (Math.abs(newValue) < 0.2) newValue = 0;
if (axis == AXIS_FORWARD) {
moveDirection.z = newValue;
} else if (axis == AXIS_STRAFE) {
moveDirection.x = newValue;
} else if (axis == AXIS_ROTATE) {
if (oldValue == 0 && newValue != 0) {
var rotateRadians = newValue > 0 ? -ROTATE_INCREMENT : ROTATE_INCREMENT;
var orientation = MyAvatar.orientation;
orientation = Quat.multiply(Quat.fromPitchYawRollRadians(0, rotateRadians, 0), orientation) ;
MyAvatar.orientation = orientation;
}
}
}
function reportButtonValue(button, newValue, oldValue) {
if (button == BUTTON_FLY_DOWN) {
flyDownButtonState = newValue;
} else if (button == BUTTON_FLY_UP) {
flyUpButtonState = newValue;
} else if (button == BUTTON_WARP) {
if (newValue) {
activateWarp();
} else {
finishWarp();
}
} else if (button == BUTTON_TURN_AROUND) {
if (newValue) {
MyAvatar.orientation = Quat.multiply(
Quat.fromPitchYawRollRadians(0, Math.PI, 0), MyAvatar.orientation);
}
} else if (newValue) {
var direction = null;
if (button == BUTTON_WARP_FORWARD) {
direction = Quat.getFront(Camera.getOrientation());
} else if (button == BUTTON_WARP_BACKWARD) {
direction = Quat.getFront(Camera.getOrientation());
direction = Vec3.multiply(-1, direction);
} else if (button == BUTTON_WARP_LEFT) {
direction = Quat.getRight(Camera.getOrientation());
direction = Vec3.multiply(-1, direction);
} else if (button == BUTTON_WARP_RIGHT) {
direction = Quat.getRight(Camera.getOrientation());
}
if (direction) {
direction.y = 0;
direction = Vec3.multiply(Vec3.normalize(direction), WARP_DISTANCE);
MyAvatar.position = Vec3.sum(MyAvatar.position, direction);
}
}
if (flyUpButtonState && !flyDownButtonState) {
moveDirection.y = 1;
} else if (!flyUpButtonState && flyDownButtonState) {
moveDirection.y = -1;
} else {
moveDirection.y = 0;
}
}
function update(dt) {
var velocity = { x: 0, y: 0, z: 0 };
var move = copyVec3(moveDirection);
move.y = 0;
if (Vec3.length(move) > 0) {
velocity = Vec3.multiplyQbyV(Camera.getOrientation(), move);
velocity.y = 0;
velocity = Vec3.multiply(Vec3.normalize(velocity), MOVE_SPEED);
}
if (moveDirection.y != 0) {
velocity.y = moveDirection.y * MOVE_SPEED;
}
MyAvatar.setVelocity(velocity);
updateWarp();
}
if (gamepad) {
gamepad.axisValueChanged.connect(reportAxisValue);
gamepad.buttonStateChanged.connect(reportButtonValue);
Script.update.connect(update);
}

View file

@ -454,22 +454,28 @@ SelectionDisplay = (function () {
var rotateHandleOffset = 0.05;
var grabberMoveUpOffset = 0.1;
var left = properties.position.x - halfDimensions.x;
var right = properties.position.x + halfDimensions.x;
var bottom = properties.position.y - halfDimensions.y;
var top = properties.position.y + halfDimensions.y;
var near = properties.position.z - halfDimensions.z;
var far = properties.position.z + halfDimensions.z;
var center = { x: properties.position.x, y: properties.position.y, z: properties.position.z };
var top, far, left, bottom, near, right, boundsCenter, objectCenter, BLN, BRN, BLF, TLN, TRN, TLF, TRF;
var BLN = { x: left, y: bottom, z: near };
var BRN = { x: right, y: bottom, z: near };
var BLF = { x: left, y: bottom, z: far };
var BRF = { x: right, y: bottom, z: far };
var TLN = { x: left, y: top, z: near };
var TRN = { x: right, y: top, z: near };
var TLF = { x: left, y: top, z: far };
var TRF = { x: right, y: top, z: far };
objectCenter = { x: properties.position.x, y: properties.position.y, z: properties.position.z };
top = properties.boundingBox.tfl.y;
far = properties.boundingBox.tfl.z;
left = properties.boundingBox.tfl.x;
bottom = properties.boundingBox.brn.y;
right = properties.boundingBox.brn.x;
near = properties.boundingBox.brn.z;
boundsCenter = { x: properties.boundingBox.center.x, y: properties.boundingBox.center.y, z: properties.boundingBox.center.z };
BLN = { x: left, y: bottom, z: near };
BRN = { x: right, y: bottom, z: near };
BLF = { x: left, y: bottom, z: far };
BRF = { x: right, y: bottom, z: far };
TLN = { x: left, y: top, z: near };
TRN = { x: right, y: top, z: near };
TLF = { x: left, y: top, z: far };
TRF = { x: right, y: top, z: far };
var yawCorner;
var pitchCorner;
@ -488,9 +494,10 @@ SelectionDisplay = (function () {
------------------------------*/
if (MyAvatar.position.x > center.x) {
if (MyAvatar.position.x > objectCenter.x) {
// must be BRF or BRN
if (MyAvatar.position.z < center.z) {
if (MyAvatar.position.z < objectCenter.z) {
yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 90, z: 0 });
pitchHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 90, z: 0 });
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 0 });
@ -499,21 +506,21 @@ SelectionDisplay = (function () {
pitchNormal = { x: 1, y: 0, z: 0 };
rollNormal = { x: 0, y: 0, z: 1 };
yawCorner = { x: right + rotateHandleOffset,
yawCorner = { x: left + rotateHandleOffset,
y: bottom - rotateHandleOffset,
z: near - rotateHandleOffset };
pitchCorner = { x: left - rotateHandleOffset,
pitchCorner = { x: right - rotateHandleOffset,
y: top + rotateHandleOffset,
z: near - rotateHandleOffset};
rollCorner = { x: right + rotateHandleOffset,
rollCorner = { x: left + rotateHandleOffset,
y: top + rotateHandleOffset,
z: far + rotateHandleOffset };
yawCenter = { x: center.x, y: bottom, z: center.z };
pitchCenter = { x: left, y: center.y, z: center.z};
rollCenter = { x: center.x, y: center.y, z: far };
yawCenter = { x: boundsCenter.x, y: bottom, z: boundsCenter.z };
pitchCenter = { x: right, y: boundsCenter.y, z: boundsCenter.z};
rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: far };
Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-south.png" });
@ -521,6 +528,7 @@ SelectionDisplay = (function () {
} else {
yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 0, z: 0 });
pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 });
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 90 });
@ -530,29 +538,31 @@ SelectionDisplay = (function () {
rollNormal = { x: 0, y: 0, z: 1 };
yawCorner = { x: right + rotateHandleOffset,
yawCorner = { x: left + rotateHandleOffset,
y: bottom - rotateHandleOffset,
z: far + rotateHandleOffset };
pitchCorner = { x: left - rotateHandleOffset,
pitchCorner = { x: right - rotateHandleOffset,
y: top + rotateHandleOffset,
z: far + rotateHandleOffset };
rollCorner = { x: right + rotateHandleOffset,
rollCorner = { x: left + rotateHandleOffset,
y: top + rotateHandleOffset,
z: near - rotateHandleOffset};
yawCenter = { x: center.x, y: bottom, z: center.z };
pitchCenter = { x: left, y: center.y, z: center.z };
rollCenter = { x: center.x, y: center.y, z: near};
yawCenter = { x: boundsCenter.x, y: bottom, z: boundsCenter.z };
pitchCenter = { x: right, y: boundsCenter.y, z: boundsCenter.z };
rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: near};
Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
}
} else {
// must be BLF or BLN
if (MyAvatar.position.z < center.z) {
if (MyAvatar.position.z < objectCenter.z) {
yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 180, z: 0 });
pitchHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 0, z: 90 });
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 });
@ -561,26 +571,27 @@ SelectionDisplay = (function () {
pitchNormal = { x: 1, y: 0, z: 0 };
rollNormal = { x: 0, y: 0, z: 1 };
yawCorner = { x: left - rotateHandleOffset,
yawCorner = { x: right - rotateHandleOffset,
y: bottom - rotateHandleOffset,
z: near - rotateHandleOffset };
pitchCorner = { x: right + rotateHandleOffset,
pitchCorner = { x: left + rotateHandleOffset,
y: top + rotateHandleOffset,
z: near - rotateHandleOffset };
rollCorner = { x: left - rotateHandleOffset,
rollCorner = { x: right - rotateHandleOffset,
y: top + rotateHandleOffset,
z: far + rotateHandleOffset};
yawCenter = { x: center.x, y: bottom, z: center.z };
pitchCenter = { x: right, y: center.y, z: center.z };
rollCenter = { x: center.x, y: center.y, z: far};
yawCenter = { x: boundsCenter.x, y: bottom, z: boundsCenter.z };
pitchCenter = { x: left, y: boundsCenter.y, z: boundsCenter.z };
rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: far};
Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
} else {
yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 270, z: 0 });
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 });
pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 });
@ -589,21 +600,21 @@ SelectionDisplay = (function () {
rollNormal = { x: 0, y: 0, z: 1 };
pitchNormal = { x: 1, y: 0, z: 0 };
yawCorner = { x: left - rotateHandleOffset,
yawCorner = { x: right - rotateHandleOffset,
y: bottom - rotateHandleOffset,
z: far + rotateHandleOffset };
rollCorner = { x: left - rotateHandleOffset,
rollCorner = { x: right - rotateHandleOffset,
y: top + rotateHandleOffset,
z: near - rotateHandleOffset };
pitchCorner = { x: right + rotateHandleOffset,
pitchCorner = { x: left + rotateHandleOffset,
y: top + rotateHandleOffset,
z: far + rotateHandleOffset};
yawCenter = { x: center.x, y: bottom, z: center.z };
rollCenter = { x: center.x, y: center.y, z: near };
pitchCenter = { x: right, y: center.y, z: center.z};
yawCenter = { x: boundsCenter.x, y: bottom, z: boundsCenter.z };
rollCenter = { x: boundsCenter.x, y: boundsCenter.y, z: near };
pitchCenter = { x: left, y: boundsCenter.y, z: boundsCenter.z};
Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
@ -611,7 +622,6 @@ SelectionDisplay = (function () {
}
}
var rotateHandlesVisible = true;
var translateHandlesVisible = true;
var stretchHandlesVisible = true;
@ -632,17 +642,11 @@ SelectionDisplay = (function () {
Overlays.editOverlay(highlightBox, { visible: false });
print("selectionBoxVisible:" + selectionBoxVisible);
Overlays.editOverlay(selectionBox,
{
visible: selectionBoxVisible,
position: center,
dimensions: properties.dimensions,
rotation: properties.rotation,
});
Overlays.editOverlay(selectionBox, { visible: selectionBoxVisible, position: objectCenter, dimensions: properties.dimensions,
rotation: properties.rotation,});
Overlays.editOverlay(grabberMoveUp, { visible: translateHandlesVisible, position: { x: center.x, y: top + grabberMoveUpOffset, z: center.z } });
Overlays.editOverlay(grabberMoveUp, { visible: translateHandlesVisible, position: { x: boundsCenter.x, y: top + grabberMoveUpOffset, z: boundsCenter.z } });
Overlays.editOverlay(grabberLBN, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: near } });
Overlays.editOverlay(grabberRBN, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: near } });
@ -654,25 +658,25 @@ SelectionDisplay = (function () {
Overlays.editOverlay(grabberRTF, { visible: stretchHandlesVisible, position: { x: right, y: top, z: far } });
Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: center.z } });
Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: center.z } });
Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: center.z } });
Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: center.z } });
Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, position: { x: center.x, y: center.y, z: near } });
Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, position: { x: center.x, y: center.y, z: far } });
Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: boundsCenter.z } });
Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: boundsCenter.z } });
Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: boundsCenter.z } });
Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: boundsCenter.z } });
Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: boundsCenter.y, z: near } });
Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: boundsCenter.y, z: far } });
Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, position: { x: right, y: top, z: center.z } });
Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, position: { x: left, y: top, z: center.z } });
Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: far } });
Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: near } });
Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: center.z } });
Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: center.z } });
Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: far } });
Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: near } });
Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: near } });
Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: near } });
Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: far } });
Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: far } });
Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, position: { x: right, y: top, z: boundsCenter.z } });
Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, position: { x: left, y: top, z: boundsCenter.z } });
Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: far } });
Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: near } });
Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: boundsCenter.z } });
Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: boundsCenter.z } });
Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: far } });
Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: near } });
Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: near } });
Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: near } });
Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: far } });
Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: far } });
Overlays.editOverlay(baseOfEntityProjectionOverlay,

View file

@ -1,19 +0,0 @@
//
// xbox.js
// examples
//
// Created by Stephen Birarda on September 23, 2014
//
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
gamepad = Joysticks.joystickWithName("Wireless 360 Controller");
function reportAxisValue(axis, newValue, oldValue) {
print("The value for axis " + axis + " has changed to " + newValue + ". It was " + oldValue);
}
gamepad.axisValueChanged.connect(reportAxisValue);

View file

@ -1084,6 +1084,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_Equal:
_myAvatar->resetSize();
break;
case Qt::Key_Escape:
OculusManager::abandonCalibration();
break;
default:
event->ignore();
break;
@ -1476,6 +1479,9 @@ void Application::setEnableVRMode(bool enableVRMode) {
OculusManager::disconnect();
OculusManager::connect();
}
OculusManager::recalibrate();
} else {
OculusManager::abandonCalibration();
}
resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());

View file

@ -365,6 +365,8 @@ public slots:
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
void resetSensors();
private slots:
void timer();
void idle();
@ -381,7 +383,6 @@ private slots:
void closeMirrorView();
void restoreMirrorView();
void shrinkMirrorView();
void resetSensors();
void parseVersionXml();

View file

@ -55,6 +55,20 @@ bool OculusManager::_programInitialized = false;
Camera* OculusManager::_camera = NULL;
int OculusManager::_activeEyeIndex = -1;
float OculusManager::CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f;
float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.f * RADIANS_PER_DEGREE;
float OculusManager::CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f;
float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE;
quint64 OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec
float OculusManager::CALIBRATION_MESSAGE_DISTANCE = 2.5f;
OculusManager::CalibrationState OculusManager::_calibrationState;
glm::vec3 OculusManager::_calibrationPosition;
glm::quat OculusManager::_calibrationOrientation;
quint64 OculusManager::_calibrationStartTime;
int OculusManager::_calibrationMessage = NULL;
QString OculusManager::CALIBRATION_BILLBOARD_URL = "http://hifi-public.s3.amazonaws.com/images/hold-to-calibrate.svg";
float OculusManager::CALIBRATION_BILLBOARD_SCALE = 2.f;
#endif
glm::vec3 OculusManager::_leftEyePosition = glm::vec3();
@ -62,6 +76,8 @@ glm::vec3 OculusManager::_rightEyePosition = glm::vec3();
void OculusManager::connect() {
#ifdef HAVE_LIBOVR
_calibrationState = UNCALIBRATED;
ovr_Initialize();
_ovrHmd = ovrHmd_Create(0);
@ -172,6 +188,121 @@ void OculusManager::disconnect() {
#endif
}
#ifdef HAVE_LIBOVR
void OculusManager::positionCalibrationBillboard(BillboardOverlay* billboard) {
glm::quat headOrientation = Application::getInstance()->getAvatar()->getHeadOrientation();
headOrientation.x = 0;
headOrientation.z = 0;
glm::normalize(headOrientation);
billboard->setPosition(Application::getInstance()->getAvatar()->getHeadPosition()
+ headOrientation * glm::vec3(0.f, 0.f, -CALIBRATION_MESSAGE_DISTANCE));
billboard->setRotation(headOrientation);
}
#endif
#ifdef HAVE_LIBOVR
void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) {
static QString progressMessage;
static BillboardOverlay* billboard;
switch (_calibrationState) {
case UNCALIBRATED:
if (position != glm::vec3() && orientation != glm::quat()) { // Handle zero values at start-up.
_calibrationPosition = position;
_calibrationOrientation = orientation;
_calibrationState = WAITING_FOR_DELTA;
}
break;
case WAITING_FOR_DELTA:
if (glm::length(position - _calibrationPosition) > CALIBRATION_DELTA_MINIMUM_LENGTH
|| glm::angle(orientation * glm::inverse(_calibrationOrientation)) > CALIBRATION_DELTA_MINIMUM_ANGLE) {
_calibrationPosition = position;
_calibrationOrientation = orientation;
_calibrationState = WAITING_FOR_ZERO;
}
break;
case WAITING_FOR_ZERO:
if (glm::length(position - _calibrationPosition) < CALIBRATION_ZERO_MAXIMUM_LENGTH
&& glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) {
_calibrationStartTime = usecTimestampNow();
_calibrationState = WAITING_FOR_ZERO_HELD;
if (!_calibrationMessage) {
qDebug() << "Hold still to calibrate HMD";
billboard = new BillboardOverlay();
billboard->setURL(CALIBRATION_BILLBOARD_URL);
billboard->setScale(CALIBRATION_BILLBOARD_SCALE);
billboard->setIsFacingAvatar(false);
positionCalibrationBillboard(billboard);
_calibrationMessage = Application::getInstance()->getOverlays().addOverlay(billboard);
}
progressMessage = "";
} else {
_calibrationPosition = position;
_calibrationOrientation = orientation;
}
break;
case WAITING_FOR_ZERO_HELD:
if (glm::length(position - _calibrationPosition) < CALIBRATION_ZERO_MAXIMUM_LENGTH
&& glm::angle(orientation * glm::inverse(_calibrationOrientation)) < CALIBRATION_ZERO_MAXIMUM_ANGLE) {
if ((usecTimestampNow() - _calibrationStartTime) > CALIBRATION_ZERO_HOLD_TIME) {
_calibrationState = CALIBRATED;
qDebug() << "HMD calibrated";
Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage);
_calibrationMessage = NULL;
Application::getInstance()->resetSensors();
} else {
quint64 quarterSeconds = (usecTimestampNow() - _calibrationStartTime) / 250000;
if (quarterSeconds + 1 > progressMessage.length()) {
// 3...2...1...
if (quarterSeconds == 4 * (quarterSeconds / 4)) {
quint64 wholeSeconds = CALIBRATION_ZERO_HOLD_TIME / 1000000 - quarterSeconds / 4;
if (wholeSeconds == 3) {
positionCalibrationBillboard(billboard);
}
progressMessage += QString::number(wholeSeconds);
} else {
progressMessage += ".";
}
//qDebug() << progressMessage; // Progress message ready for 3D text overlays.
}
}
} else {
_calibrationPosition = position;
_calibrationOrientation = orientation;
_calibrationState = WAITING_FOR_ZERO;
}
break;
}
}
#endif
void OculusManager::recalibrate() {
#ifdef HAVE_LIBOVR
_calibrationState = UNCALIBRATED;
#endif
}
void OculusManager::abandonCalibration() {
#ifdef HAVE_LIBOVR
_calibrationState = CALIBRATED;
if (_calibrationMessage) {
qDebug() << "Abandoned HMD calibration";
Application::getInstance()->getOverlays().deleteOverlay(_calibrationMessage);
_calibrationMessage = NULL;
}
#endif
}
#ifdef HAVE_LIBOVR
void OculusManager::generateDistortionMesh() {
@ -325,6 +456,13 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
ovrVector3f ovrHeadPosition = ts.HeadPose.ThePose.Position;
trackerPosition = glm::vec3(ovrHeadPosition.x, ovrHeadPosition.y, ovrHeadPosition.z);
if (_calibrationState != CALIBRATED) {
ovrQuatf ovrHeadOrientation = ts.HeadPose.ThePose.Orientation;
orientation = glm::quat(ovrHeadOrientation.w, ovrHeadOrientation.x, ovrHeadOrientation.y, ovrHeadOrientation.z);
calibrate(trackerPosition, orientation);
}
trackerPosition = bodyOrientation * trackerPosition;
#endif

View file

@ -18,6 +18,7 @@
#endif
#include "renderer/ProgramObject.h"
#include "ui/overlays/BillboardOverlay.h"
const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f;
@ -30,6 +31,8 @@ public:
static void connect();
static void disconnect();
static bool isConnected();
static void recalibrate();
static void abandonCalibration();
static void beginFrameTiming();
static void endFrameTiming();
static void configureCamera(Camera& camera, int screenWidth, int screenHeight);
@ -99,6 +102,30 @@ private:
static bool _programInitialized;
static Camera* _camera;
static int _activeEyeIndex;
static void calibrate(const glm::vec3 position, const glm::quat orientation);
enum CalibrationState {
UNCALIBRATED,
WAITING_FOR_DELTA,
WAITING_FOR_ZERO,
WAITING_FOR_ZERO_HELD,
CALIBRATED
};
static void positionCalibrationBillboard(BillboardOverlay* billboard);
static float CALIBRATION_DELTA_MINIMUM_LENGTH;
static float CALIBRATION_DELTA_MINIMUM_ANGLE;
static float CALIBRATION_ZERO_MAXIMUM_LENGTH;
static float CALIBRATION_ZERO_MAXIMUM_ANGLE;
static quint64 CALIBRATION_ZERO_HOLD_TIME;
static float CALIBRATION_MESSAGE_DISTANCE;
static CalibrationState _calibrationState;
static glm::vec3 _calibrationPosition;
static glm::quat _calibrationOrientation;
static quint64 _calibrationStartTime;
static int _calibrationMessage;
static QString CALIBRATION_BILLBOARD_URL;
static float CALIBRATION_BILLBOARD_SCALE;
#endif
static glm::vec3 _leftEyePosition;

View file

@ -156,9 +156,14 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
}
}
void BillboardOverlay::setURL(const QString& url) {
setBillboardURL(url);
}
void BillboardOverlay::setBillboardURL(const QString& url) {
_url = url;
QUrl actualURL = url;
_isLoaded = false;
// clear the billboard if previously set

View file

@ -24,6 +24,12 @@ public:
BillboardOverlay();
virtual void render();
// setters
void setURL(const QString& url);
void setScale(float scale) { _scale = scale; }
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
virtual void setProperties(const QScriptValue& properties);
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }

View file

@ -124,90 +124,59 @@ void Overlays::render3D() {
unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) {
unsigned int thisID = 0;
bool created = false;
bool is3D = false;
Overlay* thisOverlay = NULL;
bool created = true;
if (type == "image") {
thisOverlay = new ImageOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
} else if (type == "text") {
thisOverlay = new TextOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
} else if (type == "cube") {
thisOverlay = new Cube3DOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else if (type == "sphere") {
thisOverlay = new Sphere3DOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else if (type == "circle3d") {
thisOverlay = new Circle3DOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else if (type == "rectangle3d") {
thisOverlay = new Rectangle3DOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else if (type == "line3d") {
thisOverlay = new Line3DOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else if (type == "localvoxels") {
thisOverlay = new LocalVoxelsOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else if (type == "localmodels") {
thisOverlay = new LocalModelsOverlay(Application::getInstance()->getEntityClipboardRenderer());
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else if (type == "model") {
thisOverlay = new ModelOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else if (type == "billboard") {
thisOverlay = new BillboardOverlay();
thisOverlay->init(_parent);
thisOverlay->setProperties(properties);
created = true;
is3D = true;
} else {
created = false;
}
if (created) {
QWriteLocker lock(&_lock);
thisID = _nextOverlayID;
_nextOverlayID++;
if (is3D) {
_overlays3D[thisID] = thisOverlay;
} else {
_overlays2D[thisID] = thisOverlay;
}
thisOverlay->setProperties(properties);
thisID = addOverlay(thisOverlay);
}
return thisID;
}
unsigned int Overlays::addOverlay(Overlay* overlay) {
overlay->init(_parent);
QWriteLocker lock(&_lock);
unsigned int thisID = _nextOverlayID;
_nextOverlayID++;
bool is3D = typeid(*overlay) != typeid(ImageOverlay) && typeid(*overlay) != typeid(TextOverlay);
if (is3D) {
_overlays3D[thisID] = overlay;
} else {
_overlays2D[thisID] = overlay;
}
return thisID;
}
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
Overlay* thisOverlay = NULL;
QWriteLocker lock(&_lock);

View file

@ -44,6 +44,9 @@ public slots:
/// adds an overlay with the specific properties
unsigned int addOverlay(const QString& type, const QScriptValue& properties);
/// adds an overlay that's already been created
unsigned int addOverlay(Overlay* overlay);
/// edits an overlay updating only the included properties, will return the identified OverlayID in case of
/// successful edit, if the input id is for an unknown overlay this function will have no effect
bool editOverlay(unsigned int id, const QScriptValue& properties);

View file

@ -174,6 +174,16 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
sittingPoints.setProperty("length", _sittingPoints.size());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable
AABox aaBox = getAABoxInMeters();
QScriptValue boundingBox = engine->newObject();
QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner());
QScriptValue topFarLeft = vec3toScriptValue(engine, aaBox.calcTopFarLeft());
QScriptValue center = vec3toScriptValue(engine, aaBox.calcCenter());
boundingBox.setProperty("brn", bottomRightNear);
boundingBox.setProperty("tfl", topFarLeft);
boundingBox.setProperty("center", center);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(boundingBox, boundingBox); // gettable, but not settable
return properties;
}
@ -643,3 +653,20 @@ AACube EntityItemProperties::getMaximumAACubeInMeters() const {
return AACube(minimumCorner, diameter);
}
// The minimum bounding box for the entity.
AABox EntityItemProperties::getAABoxInMeters() const {
// _position represents the position of the registration point.
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint;
glm::vec3 unrotatedMinRelativeToEntity = glm::vec3(0.0f, 0.0f, 0.0f) - (_dimensions * _registrationPoint);
glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder;
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation());
// shift the extents to be relative to the position/registration point
rotatedExtentsRelativeToRegistrationPoint.shiftBy(_position);
return AABox(rotatedExtentsRelativeToRegistrationPoint);
}

View file

@ -101,6 +101,7 @@ public:
AACube getMaximumAACubeInTreeUnits() const;
AACube getMaximumAACubeInMeters() const;
AABox getAABoxInMeters() const;
void debugDump() const;