mirror of
https://github.com/overte-org/overte.git
synced 2025-06-27 20:29:38 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels
This commit is contained in:
commit
c8c09a1e7b
27 changed files with 1560 additions and 202 deletions
|
@ -152,7 +152,6 @@ $(document).ready(function(){
|
||||||
})
|
})
|
||||||
|
|
||||||
$('#settings-form').on('change', 'select', function(){
|
$('#settings-form').on('change', 'select', function(){
|
||||||
console.log("Changed" + $(this))
|
|
||||||
$("input[name='" + $(this).attr('data-hidden-input') + "']").val($(this).val()).change()
|
$("input[name='" + $(this).attr('data-hidden-input') + "']").val($(this).val()).change()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -474,8 +473,10 @@ function deleteTableRow(delete_glyphicon) {
|
||||||
if (!isArray) {
|
if (!isArray) {
|
||||||
// this is a hash row, so we empty it but leave the hidden input blank so it is cleared when we save
|
// this is a hash row, so we empty it but leave the hidden input blank so it is cleared when we save
|
||||||
row.empty()
|
row.empty()
|
||||||
row.html("<input type='hidden' class='form-control' name='" + table.attr("name") + "' data-changed='true' value=''>");
|
row.html("<input type='hidden' class='form-control' name='"
|
||||||
} else if (table.find('.' + Settings.DATA_ROW_CLASS).length > 1) {
|
+ row.attr('name') + "' data-changed='true' value=''>");
|
||||||
|
} else {
|
||||||
|
if (table.find('.' + Settings.DATA_ROW_CLASS).length) {
|
||||||
updateDataChangedForSiblingRows(row)
|
updateDataChangedForSiblingRows(row)
|
||||||
|
|
||||||
// this isn't the last row - we can just remove it
|
// this isn't the last row - we can just remove it
|
||||||
|
@ -490,6 +491,7 @@ function deleteTableRow(delete_glyphicon) {
|
||||||
row.html("<input type='hidden' class='form-control' name='" + table.attr("name").replace('[]', '')
|
row.html("<input type='hidden' class='form-control' name='" + table.attr("name").replace('[]', '')
|
||||||
+ "' data-changed='true' value=''>");
|
+ "' data-changed='true' value=''>");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// we need to fire a change event on one of the remaining inputs so that the sidebar badge is updated
|
// we need to fire a change event on one of the remaining inputs so that the sidebar badge is updated
|
||||||
badgeSidebarForDifferences($(table))
|
badgeSidebarForDifferences($(table))
|
||||||
|
|
280
examples/gamepad.js
Normal file
280
examples/gamepad.js
Normal 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);
|
||||||
|
}
|
|
@ -244,7 +244,7 @@ EntityPropertyDialogBox = (function () {
|
||||||
properties.color.blue = array[index++].value;
|
properties.color.blue = array[index++].value;
|
||||||
}
|
}
|
||||||
Entities.editEntity(editModelID, properties);
|
Entities.editEntity(editModelID, properties);
|
||||||
selectionDisplay.highlightSelectable(editModelID, propeties);
|
selectionDisplay.select(editModelID, false);
|
||||||
}
|
}
|
||||||
modelSelected = false;
|
modelSelected = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,10 +31,33 @@ SelectionDisplay = (function () {
|
||||||
var handleHoverColor = { red: 224, green: 67, blue: 36 };
|
var handleHoverColor = { red: 224, green: 67, blue: 36 };
|
||||||
var handleHoverAlpha = 1.0;
|
var handleHoverAlpha = 1.0;
|
||||||
|
|
||||||
|
var rotateOverlayTargetSize = 10000; // really big target
|
||||||
|
var innerSnapAngle = 22.5; // the angle which we snap to on the inner rotation tool
|
||||||
|
var innerRadius;
|
||||||
|
var outerRadius;
|
||||||
|
var yawHandleRotation;
|
||||||
|
var pitchHandleRotation;
|
||||||
|
var rollHandleRotation;
|
||||||
|
var yawCenter;
|
||||||
|
var pitchCenter;
|
||||||
|
var rollCenter;
|
||||||
|
var yawZero;
|
||||||
|
var pitchZero;
|
||||||
|
var rollZero;
|
||||||
|
var yawNormal;
|
||||||
|
var pitchNormal;
|
||||||
|
var rollNormal;
|
||||||
|
var rotationNormal;
|
||||||
|
|
||||||
|
var originalRotation;
|
||||||
|
var originalPitch;
|
||||||
|
var originalYaw;
|
||||||
|
var originalRoll;
|
||||||
|
|
||||||
|
|
||||||
var rotateHandleColor = { red: 0, green: 0, blue: 0 };
|
var rotateHandleColor = { red: 0, green: 0, blue: 0 };
|
||||||
var rotateHandleAlpha = 0.7;
|
var rotateHandleAlpha = 0.7;
|
||||||
|
|
||||||
|
|
||||||
var grabberSizeCorner = 0.025;
|
var grabberSizeCorner = 0.025;
|
||||||
var grabberSizeEdge = 0.015;
|
var grabberSizeEdge = 0.015;
|
||||||
var grabberSizeFace = 0.025;
|
var grabberSizeFace = 0.025;
|
||||||
|
@ -151,7 +174,8 @@ SelectionDisplay = (function () {
|
||||||
alpha: 0.5,
|
alpha: 0.5,
|
||||||
solid: true,
|
solid: true,
|
||||||
visible: false,
|
visible: false,
|
||||||
rotation: baseOverlayRotation
|
rotation: baseOverlayRotation,
|
||||||
|
ignoreRayIntersection: true, // always ignore this
|
||||||
});
|
});
|
||||||
|
|
||||||
var yawOverlayAngles = { x: 90, y: 0, z: 0 };
|
var yawOverlayAngles = { x: 90, y: 0, z: 0 };
|
||||||
|
@ -161,6 +185,34 @@ SelectionDisplay = (function () {
|
||||||
var rollOverlayAngles = { x: 0, y: 180, z: 0 };
|
var rollOverlayAngles = { x: 0, y: 180, z: 0 };
|
||||||
var rollOverlayRotation = Quat.fromVec3Degrees(rollOverlayAngles);
|
var rollOverlayRotation = Quat.fromVec3Degrees(rollOverlayAngles);
|
||||||
|
|
||||||
|
var rotateZeroOverlay = Overlays.addOverlay("line3d", {
|
||||||
|
visible: false,
|
||||||
|
lineWidth: 2.0,
|
||||||
|
start: { x: 0, y: 0, z: 0 },
|
||||||
|
end: { x: 0, y: 0, z: 0 },
|
||||||
|
color: { red: 255, green: 0, blue: 0 },
|
||||||
|
ignoreRayIntersection: true, // always ignore this
|
||||||
|
});
|
||||||
|
|
||||||
|
var rotateCurrentOverlay = Overlays.addOverlay("line3d", {
|
||||||
|
visible: false,
|
||||||
|
lineWidth: 2.0,
|
||||||
|
start: { x: 0, y: 0, z: 0 },
|
||||||
|
end: { x: 0, y: 0, z: 0 },
|
||||||
|
color: { red: 0, green: 0, blue: 255 },
|
||||||
|
ignoreRayIntersection: true, // always ignore this
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var rotateOverlayTarget = Overlays.addOverlay("circle3d", {
|
||||||
|
position: { x:0, y: 0, z: 0},
|
||||||
|
size: rotateOverlayTargetSize,
|
||||||
|
color: { red: 0, green: 0, blue: 0 },
|
||||||
|
alpha: 0.0,
|
||||||
|
solid: true,
|
||||||
|
visible: false,
|
||||||
|
rotation: yawOverlayRotation,
|
||||||
|
});
|
||||||
|
|
||||||
var rotateOverlayInner = Overlays.addOverlay("circle3d", {
|
var rotateOverlayInner = Overlays.addOverlay("circle3d", {
|
||||||
position: { x:0, y: 0, z: 0},
|
position: { x:0, y: 0, z: 0},
|
||||||
|
@ -171,12 +223,13 @@ SelectionDisplay = (function () {
|
||||||
visible: false,
|
visible: false,
|
||||||
rotation: yawOverlayRotation,
|
rotation: yawOverlayRotation,
|
||||||
hasTickMarks: true,
|
hasTickMarks: true,
|
||||||
majorTickMarksAngle: 12.5,
|
majorTickMarksAngle: innerSnapAngle,
|
||||||
minorTickMarksAngle: 0,
|
minorTickMarksAngle: 0,
|
||||||
majorTickMarksLength: -0.25,
|
majorTickMarksLength: -0.25,
|
||||||
minorTickMarksLength: 0,
|
minorTickMarksLength: 0,
|
||||||
majorTickMarksColor: { red: 0, green: 0, blue: 0 },
|
majorTickMarksColor: { red: 0, green: 0, blue: 0 },
|
||||||
minorTickMarksColor: { red: 0, green: 0, blue: 0 },
|
minorTickMarksColor: { red: 0, green: 0, blue: 0 },
|
||||||
|
ignoreRayIntersection: true, // always ignore this
|
||||||
});
|
});
|
||||||
|
|
||||||
var rotateOverlayOuter = Overlays.addOverlay("circle3d", {
|
var rotateOverlayOuter = Overlays.addOverlay("circle3d", {
|
||||||
|
@ -195,6 +248,7 @@ SelectionDisplay = (function () {
|
||||||
minorTickMarksLength: 0.1,
|
minorTickMarksLength: 0.1,
|
||||||
majorTickMarksColor: { red: 0, green: 0, blue: 0 },
|
majorTickMarksColor: { red: 0, green: 0, blue: 0 },
|
||||||
minorTickMarksColor: { red: 0, green: 0, blue: 0 },
|
minorTickMarksColor: { red: 0, green: 0, blue: 0 },
|
||||||
|
ignoreRayIntersection: true, // always ignore this
|
||||||
});
|
});
|
||||||
|
|
||||||
var rotateOverlayCurrent = Overlays.addOverlay("circle3d", {
|
var rotateOverlayCurrent = Overlays.addOverlay("circle3d", {
|
||||||
|
@ -205,10 +259,11 @@ SelectionDisplay = (function () {
|
||||||
solid: true,
|
solid: true,
|
||||||
visible: false,
|
visible: false,
|
||||||
rotation: yawOverlayRotation,
|
rotation: yawOverlayRotation,
|
||||||
|
ignoreRayIntersection: true, // always ignore this
|
||||||
});
|
});
|
||||||
|
|
||||||
var yawHandle = Overlays.addOverlay("billboard", {
|
var yawHandle = Overlays.addOverlay("billboard", {
|
||||||
url: "https://s3.amazonaws.com/uploads.hipchat.com/33953/231323/HRRhkMk8ueLk8ku/rotate-arrow.png",
|
url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png",
|
||||||
position: { x:0, y: 0, z: 0},
|
position: { x:0, y: 0, z: 0},
|
||||||
color: rotateHandleColor,
|
color: rotateHandleColor,
|
||||||
alpha: rotateHandleAlpha,
|
alpha: rotateHandleAlpha,
|
||||||
|
@ -220,7 +275,7 @@ SelectionDisplay = (function () {
|
||||||
|
|
||||||
|
|
||||||
var pitchHandle = Overlays.addOverlay("billboard", {
|
var pitchHandle = Overlays.addOverlay("billboard", {
|
||||||
url: "https://s3.amazonaws.com/uploads.hipchat.com/33953/231323/HRRhkMk8ueLk8ku/rotate-arrow.png",
|
url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png",
|
||||||
position: { x:0, y: 0, z: 0},
|
position: { x:0, y: 0, z: 0},
|
||||||
color: rotateHandleColor,
|
color: rotateHandleColor,
|
||||||
alpha: rotateHandleAlpha,
|
alpha: rotateHandleAlpha,
|
||||||
|
@ -232,7 +287,7 @@ SelectionDisplay = (function () {
|
||||||
|
|
||||||
|
|
||||||
var rollHandle = Overlays.addOverlay("billboard", {
|
var rollHandle = Overlays.addOverlay("billboard", {
|
||||||
url: "https://s3.amazonaws.com/uploads.hipchat.com/33953/231323/HRRhkMk8ueLk8ku/rotate-arrow.png",
|
url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png",
|
||||||
position: { x:0, y: 0, z: 0},
|
position: { x:0, y: 0, z: 0},
|
||||||
color: rotateHandleColor,
|
color: rotateHandleColor,
|
||||||
alpha: rotateHandleAlpha,
|
alpha: rotateHandleAlpha,
|
||||||
|
@ -279,10 +334,13 @@ SelectionDisplay = (function () {
|
||||||
overlayNames[pitchHandle] = "pitchHandle";
|
overlayNames[pitchHandle] = "pitchHandle";
|
||||||
overlayNames[rollHandle] = "rollHandle";
|
overlayNames[rollHandle] = "rollHandle";
|
||||||
|
|
||||||
|
overlayNames[rotateOverlayTarget] = "rotateOverlayTarget";
|
||||||
overlayNames[rotateOverlayInner] = "rotateOverlayInner";
|
overlayNames[rotateOverlayInner] = "rotateOverlayInner";
|
||||||
overlayNames[rotateOverlayOuter] = "rotateOverlayOuter";
|
overlayNames[rotateOverlayOuter] = "rotateOverlayOuter";
|
||||||
overlayNames[rotateOverlayCurrent] = "rotateOverlayCurrent";
|
overlayNames[rotateOverlayCurrent] = "rotateOverlayCurrent";
|
||||||
|
|
||||||
|
overlayNames[rotateZeroOverlay] = "rotateZeroOverlay";
|
||||||
|
overlayNames[rotateCurrentOverlay] = "rotateCurrentOverlay";
|
||||||
|
|
||||||
that.cleanup = function () {
|
that.cleanup = function () {
|
||||||
Overlays.deleteOverlay(highlightBox);
|
Overlays.deleteOverlay(highlightBox);
|
||||||
|
@ -322,10 +380,15 @@ SelectionDisplay = (function () {
|
||||||
Overlays.deleteOverlay(pitchHandle);
|
Overlays.deleteOverlay(pitchHandle);
|
||||||
Overlays.deleteOverlay(rollHandle);
|
Overlays.deleteOverlay(rollHandle);
|
||||||
|
|
||||||
|
Overlays.deleteOverlay(rotateOverlayTarget);
|
||||||
Overlays.deleteOverlay(rotateOverlayInner);
|
Overlays.deleteOverlay(rotateOverlayInner);
|
||||||
Overlays.deleteOverlay(rotateOverlayOuter);
|
Overlays.deleteOverlay(rotateOverlayOuter);
|
||||||
Overlays.deleteOverlay(rotateOverlayCurrent);
|
Overlays.deleteOverlay(rotateOverlayCurrent);
|
||||||
|
|
||||||
|
Overlays.deleteOverlay(rotateZeroOverlay);
|
||||||
|
Overlays.deleteOverlay(rotateCurrentOverlay);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
that.highlightSelectable = function(entityID) {
|
that.highlightSelectable = function(entityID) {
|
||||||
|
@ -377,8 +440,8 @@ SelectionDisplay = (function () {
|
||||||
|
|
||||||
var diagonal = (Vec3.length(properties.dimensions) / 2) * 1.1;
|
var diagonal = (Vec3.length(properties.dimensions) / 2) * 1.1;
|
||||||
var halfDimensions = Vec3.multiply(properties.dimensions, 0.5);
|
var halfDimensions = Vec3.multiply(properties.dimensions, 0.5);
|
||||||
var innerRadius = diagonal;
|
innerRadius = diagonal;
|
||||||
var outerRadius = diagonal * 1.15;
|
outerRadius = diagonal * 1.15;
|
||||||
var innerActive = false;
|
var innerActive = false;
|
||||||
var innerAlpha = 0.2;
|
var innerAlpha = 0.2;
|
||||||
var outerAlpha = 0.2;
|
var outerAlpha = 0.2;
|
||||||
|
@ -391,31 +454,33 @@ SelectionDisplay = (function () {
|
||||||
var rotateHandleOffset = 0.05;
|
var rotateHandleOffset = 0.05;
|
||||||
var grabberMoveUpOffset = 0.1;
|
var grabberMoveUpOffset = 0.1;
|
||||||
|
|
||||||
var left = properties.position.x - halfDimensions.x;
|
var top, far, left, bottom, near, right, boundsCenter, objectCenter, BLN, BRN, BLF, TLN, TRN, TLF, TRF;
|
||||||
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 BLN = { x: left, y: bottom, z: near };
|
objectCenter = { x: properties.position.x, y: properties.position.y, z: properties.position.z };
|
||||||
var BRN = { x: right, y: bottom, z: near };
|
|
||||||
var BLF = { x: left, y: bottom, z: far };
|
top = properties.boundingBox.tfl.y;
|
||||||
var BRF = { x: right, y: bottom, z: far };
|
far = properties.boundingBox.tfl.z;
|
||||||
var TLN = { x: left, y: top, z: near };
|
left = properties.boundingBox.tfl.x;
|
||||||
var TRN = { x: right, y: top, z: near };
|
|
||||||
var TLF = { x: left, y: top, z: far };
|
bottom = properties.boundingBox.brn.y;
|
||||||
var TRF = { x: right, y: top, z: far };
|
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 yawCorner;
|
||||||
var pitchCorner;
|
var pitchCorner;
|
||||||
var rollCorner;
|
var rollCorner;
|
||||||
|
|
||||||
var yawHandleRotation;
|
|
||||||
var pitchHandleRotation;
|
|
||||||
var rollHandleRotation;
|
|
||||||
|
|
||||||
// determine which bottom corner we are closest to
|
// determine which bottom corner we are closest to
|
||||||
/*------------------------------
|
/*------------------------------
|
||||||
example:
|
example:
|
||||||
|
@ -429,124 +494,189 @@ SelectionDisplay = (function () {
|
||||||
|
|
||||||
------------------------------*/
|
------------------------------*/
|
||||||
|
|
||||||
if (MyAvatar.position.x > center.x) {
|
if (MyAvatar.position.x > objectCenter.x) {
|
||||||
// must be BRF or BRN
|
// must be BRF or BRN
|
||||||
if (MyAvatar.position.z < center.z) {
|
if (MyAvatar.position.z < objectCenter.z) {
|
||||||
yawHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 0, z: 0 });
|
|
||||||
pitchHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 180, z: 180 });
|
|
||||||
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 90, z: 180 });
|
|
||||||
|
|
||||||
yawCorner = { x: right + rotateHandleOffset,
|
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 });
|
||||||
|
|
||||||
|
yawNormal = { x: 0, y: 1, z: 0 };
|
||||||
|
pitchNormal = { x: 1, y: 0, z: 0 };
|
||||||
|
rollNormal = { x: 0, y: 0, z: 1 };
|
||||||
|
|
||||||
|
yawCorner = { x: left + rotateHandleOffset,
|
||||||
y: bottom - rotateHandleOffset,
|
y: bottom - rotateHandleOffset,
|
||||||
z: near - rotateHandleOffset };
|
z: near - rotateHandleOffset };
|
||||||
|
|
||||||
pitchCorner = { x: right + rotateHandleOffset,
|
pitchCorner = { x: right - rotateHandleOffset,
|
||||||
y: top + rotateHandleOffset,
|
|
||||||
z: far + rotateHandleOffset };
|
|
||||||
|
|
||||||
rollCorner = { x: left - rotateHandleOffset,
|
|
||||||
y: top + rotateHandleOffset,
|
y: top + rotateHandleOffset,
|
||||||
z: near - rotateHandleOffset};
|
z: near - rotateHandleOffset};
|
||||||
|
|
||||||
|
rollCorner = { x: left + rotateHandleOffset,
|
||||||
|
y: top + rotateHandleOffset,
|
||||||
|
z: far + rotateHandleOffset };
|
||||||
|
|
||||||
|
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" });
|
||||||
|
Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-south.png" });
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
yawHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 270, z: 0 });
|
|
||||||
|
yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 0, z: 0 });
|
||||||
pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 });
|
pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 });
|
||||||
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 90 });
|
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 90 });
|
||||||
|
|
||||||
yawCorner = { x: right + rotateHandleOffset,
|
yawNormal = { x: 0, y: 1, z: 0 };
|
||||||
|
pitchNormal = { x: 1, y: 0, z: 0 };
|
||||||
|
rollNormal = { x: 0, y: 0, z: 1 };
|
||||||
|
|
||||||
|
|
||||||
|
yawCorner = { x: left + rotateHandleOffset,
|
||||||
y: bottom - rotateHandleOffset,
|
y: bottom - rotateHandleOffset,
|
||||||
z: far + rotateHandleOffset };
|
z: far + rotateHandleOffset };
|
||||||
|
|
||||||
pitchCorner = { x: left - rotateHandleOffset,
|
pitchCorner = { x: right - rotateHandleOffset,
|
||||||
y: top + rotateHandleOffset,
|
y: top + rotateHandleOffset,
|
||||||
z: far + rotateHandleOffset };
|
z: far + rotateHandleOffset };
|
||||||
|
|
||||||
rollCorner = { x: right + rotateHandleOffset,
|
rollCorner = { x: left + rotateHandleOffset,
|
||||||
y: top + rotateHandleOffset,
|
y: top + rotateHandleOffset,
|
||||||
z: near - rotateHandleOffset};
|
z: near - rotateHandleOffset};
|
||||||
|
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
|
|
||||||
// must be BLF or BLN
|
// must be BLF or BLN
|
||||||
if (MyAvatar.position.z < center.z) {
|
if (MyAvatar.position.z < objectCenter.z) {
|
||||||
yawHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 90, z: 0 });
|
|
||||||
|
yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 180, z: 0 });
|
||||||
pitchHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 0, z: 90 });
|
pitchHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 0, z: 90 });
|
||||||
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 });
|
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 });
|
||||||
|
|
||||||
yawCorner = { x: left - rotateHandleOffset,
|
yawNormal = { x: 0, y: 1, z: 0 };
|
||||||
|
pitchNormal = { x: 1, y: 0, z: 0 };
|
||||||
|
rollNormal = { x: 0, y: 0, z: 1 };
|
||||||
|
|
||||||
|
yawCorner = { x: right - rotateHandleOffset,
|
||||||
y: bottom - rotateHandleOffset,
|
y: bottom - rotateHandleOffset,
|
||||||
z: near - rotateHandleOffset };
|
z: near - rotateHandleOffset };
|
||||||
|
|
||||||
pitchCorner = { x: right + rotateHandleOffset,
|
pitchCorner = { x: left + rotateHandleOffset,
|
||||||
y: top + rotateHandleOffset,
|
y: top + rotateHandleOffset,
|
||||||
z: near - rotateHandleOffset };
|
z: near - rotateHandleOffset };
|
||||||
|
|
||||||
rollCorner = { x: left - rotateHandleOffset,
|
rollCorner = { x: right - rotateHandleOffset,
|
||||||
y: top + rotateHandleOffset,
|
y: top + rotateHandleOffset,
|
||||||
z: far + rotateHandleOffset};
|
z: far + rotateHandleOffset};
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
yawHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 180, z: 0 });
|
|
||||||
pitchHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 });
|
|
||||||
rollHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 });
|
|
||||||
|
|
||||||
yawCorner = { x: left - rotateHandleOffset,
|
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 });
|
||||||
|
|
||||||
|
yawNormal = { x: 0, y: 1, z: 0 };
|
||||||
|
rollNormal = { x: 0, y: 0, z: 1 };
|
||||||
|
pitchNormal = { x: 1, y: 0, z: 0 };
|
||||||
|
|
||||||
|
yawCorner = { x: right - rotateHandleOffset,
|
||||||
y: bottom - rotateHandleOffset,
|
y: bottom - rotateHandleOffset,
|
||||||
z: far + rotateHandleOffset };
|
z: far + rotateHandleOffset };
|
||||||
|
|
||||||
pitchCorner = { x: left - rotateHandleOffset,
|
rollCorner = { x: right - rotateHandleOffset,
|
||||||
y: top + rotateHandleOffset,
|
y: top + rotateHandleOffset,
|
||||||
z: near - rotateHandleOffset };
|
z: near - rotateHandleOffset };
|
||||||
|
|
||||||
rollCorner = { x: right + rotateHandleOffset,
|
pitchCorner = { x: left + rotateHandleOffset,
|
||||||
y: top + rotateHandleOffset,
|
y: top + rotateHandleOffset,
|
||||||
z: far + rotateHandleOffset};
|
z: far + rotateHandleOffset};
|
||||||
|
|
||||||
|
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" });
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rotateHandlesVisible = true;
|
||||||
|
var translateHandlesVisible = true;
|
||||||
|
var stretchHandlesVisible = true;
|
||||||
|
var selectionBoxVisible = true;
|
||||||
|
if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL" || mode == "TRANSLATE_XZ") {
|
||||||
|
rotateHandlesVisible = false;
|
||||||
|
translateHandlesVisible = false;
|
||||||
|
stretchHandlesVisible = false;
|
||||||
|
selectionBoxVisible = false;
|
||||||
|
} else if (mode == "TRANSLATE_UP_DOWN") {
|
||||||
|
rotateHandlesVisible = false;
|
||||||
|
stretchHandlesVisible = false;
|
||||||
|
} else if (mode != "UNKNOWN") {
|
||||||
|
// every other mode is a stretch mode...
|
||||||
|
rotateHandlesVisible = false;
|
||||||
|
translateHandlesVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
Overlays.editOverlay(highlightBox, { visible: false });
|
Overlays.editOverlay(highlightBox, { visible: false });
|
||||||
|
|
||||||
Overlays.editOverlay(selectionBox,
|
Overlays.editOverlay(selectionBox, { visible: selectionBoxVisible, position: objectCenter, dimensions: properties.dimensions,
|
||||||
{
|
rotation: properties.rotation,});
|
||||||
visible: true,
|
|
||||||
position: center,
|
|
||||||
dimensions: properties.dimensions,
|
|
||||||
rotation: properties.rotation,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Overlays.editOverlay(grabberMoveUp, { visible: true, 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: true, position: { x: left, y: bottom, z: near } });
|
Overlays.editOverlay(grabberLBN, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: near } });
|
||||||
Overlays.editOverlay(grabberRBN, { visible: true, position: { x: right, y: bottom, z: near } });
|
Overlays.editOverlay(grabberRBN, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: near } });
|
||||||
Overlays.editOverlay(grabberLBF, { visible: true, position: { x: left, y: bottom, z: far } });
|
Overlays.editOverlay(grabberLBF, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: far } });
|
||||||
Overlays.editOverlay(grabberRBF, { visible: true, position: { x: right, y: bottom, z: far } });
|
Overlays.editOverlay(grabberRBF, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: far } });
|
||||||
Overlays.editOverlay(grabberLTN, { visible: true, position: { x: left, y: top, z: near } });
|
Overlays.editOverlay(grabberLTN, { visible: stretchHandlesVisible, position: { x: left, y: top, z: near } });
|
||||||
Overlays.editOverlay(grabberRTN, { visible: true, position: { x: right, y: top, z: near } });
|
Overlays.editOverlay(grabberRTN, { visible: stretchHandlesVisible, position: { x: right, y: top, z: near } });
|
||||||
Overlays.editOverlay(grabberLTF, { visible: true, position: { x: left, y: top, z: far } });
|
Overlays.editOverlay(grabberLTF, { visible: stretchHandlesVisible, position: { x: left, y: top, z: far } });
|
||||||
Overlays.editOverlay(grabberRTF, { visible: true, position: { x: right, y: top, z: far } });
|
Overlays.editOverlay(grabberRTF, { visible: stretchHandlesVisible, position: { x: right, y: top, z: far } });
|
||||||
|
|
||||||
|
|
||||||
Overlays.editOverlay(grabberTOP, { visible: true, position: { x: center.x, y: top, z: center.z } });
|
Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: boundsCenter.z } });
|
||||||
Overlays.editOverlay(grabberBOTTOM, { visible: true, position: { x: center.x, y: bottom, z: center.z } });
|
Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: boundsCenter.z } });
|
||||||
Overlays.editOverlay(grabberLEFT, { visible: true, position: { x: left, y: center.y, z: center.z } });
|
Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: boundsCenter.z } });
|
||||||
Overlays.editOverlay(grabberRIGHT, { visible: true, position: { x: right, y: center.y, z: center.z } });
|
Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: boundsCenter.z } });
|
||||||
Overlays.editOverlay(grabberNEAR, { visible: true, position: { x: center.x, y: center.y, z: near } });
|
Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: boundsCenter.y, z: near } });
|
||||||
Overlays.editOverlay(grabberFAR, { visible: true, position: { x: center.x, y: center.y, z: far } });
|
Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: boundsCenter.y, z: far } });
|
||||||
|
|
||||||
Overlays.editOverlay(grabberEdgeTR, { visible: true, position: { x: right, y: top, z: center.z } });
|
Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, position: { x: right, y: top, z: boundsCenter.z } });
|
||||||
Overlays.editOverlay(grabberEdgeTL, { visible: true, position: { x: left, y: top, z: center.z } });
|
Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, position: { x: left, y: top, z: boundsCenter.z } });
|
||||||
Overlays.editOverlay(grabberEdgeTF, { visible: true, position: { x: center.x, y: top, z: far } });
|
Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: far } });
|
||||||
Overlays.editOverlay(grabberEdgeTN, { visible: true, position: { x: center.x, y: top, z: near } });
|
Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: near } });
|
||||||
Overlays.editOverlay(grabberEdgeBR, { visible: true, position: { x: right, y: bottom, z: center.z } });
|
Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: boundsCenter.z } });
|
||||||
Overlays.editOverlay(grabberEdgeBL, { visible: true, position: { x: left, y: bottom, z: center.z } });
|
Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: boundsCenter.z } });
|
||||||
Overlays.editOverlay(grabberEdgeBF, { visible: true, position: { x: center.x, y: bottom, z: far } });
|
Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: far } });
|
||||||
Overlays.editOverlay(grabberEdgeBN, { visible: true, position: { x: center.x, y: bottom, z: near } });
|
Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: near } });
|
||||||
Overlays.editOverlay(grabberEdgeNR, { visible: true, position: { x: right, y: center.y, z: near } });
|
Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: near } });
|
||||||
Overlays.editOverlay(grabberEdgeNL, { visible: true, position: { x: left, y: center.y, z: near } });
|
Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: near } });
|
||||||
Overlays.editOverlay(grabberEdgeFR, { visible: true, position: { x: right, y: center.y, z: far } });
|
Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: far } });
|
||||||
Overlays.editOverlay(grabberEdgeFL, { visible: true, position: { x: left, y: center.y, z: far } });
|
Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: far } });
|
||||||
|
|
||||||
|
|
||||||
Overlays.editOverlay(baseOfEntityProjectionOverlay,
|
Overlays.editOverlay(baseOfEntityProjectionOverlay,
|
||||||
|
@ -563,13 +693,11 @@ SelectionDisplay = (function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Overlays.editOverlay(rotateOverlayTarget, { visible: false });
|
||||||
|
|
||||||
Overlays.editOverlay(rotateOverlayInner,
|
Overlays.editOverlay(rotateOverlayInner,
|
||||||
{
|
{
|
||||||
visible: false,
|
visible: false,
|
||||||
position: { x: properties.position.x,
|
|
||||||
y: properties.position.y - (properties.dimensions.y / 2),
|
|
||||||
z: properties.position.z},
|
|
||||||
|
|
||||||
size: innerRadius,
|
size: innerRadius,
|
||||||
innerRadius: 0.9,
|
innerRadius: 0.9,
|
||||||
alpha: innerAlpha
|
alpha: innerAlpha
|
||||||
|
@ -578,10 +706,6 @@ SelectionDisplay = (function () {
|
||||||
Overlays.editOverlay(rotateOverlayOuter,
|
Overlays.editOverlay(rotateOverlayOuter,
|
||||||
{
|
{
|
||||||
visible: false,
|
visible: false,
|
||||||
position: { x: properties.position.x,
|
|
||||||
y: properties.position.y - (properties.dimensions.y / 2),
|
|
||||||
z: properties.position.z},
|
|
||||||
|
|
||||||
size: outerRadius,
|
size: outerRadius,
|
||||||
innerRadius: 0.9,
|
innerRadius: 0.9,
|
||||||
startAt: 0,
|
startAt: 0,
|
||||||
|
@ -592,20 +716,19 @@ SelectionDisplay = (function () {
|
||||||
Overlays.editOverlay(rotateOverlayCurrent,
|
Overlays.editOverlay(rotateOverlayCurrent,
|
||||||
{
|
{
|
||||||
visible: false,
|
visible: false,
|
||||||
position: { x: properties.position.x,
|
|
||||||
y: properties.position.y - (properties.dimensions.y / 2),
|
|
||||||
z: properties.position.z},
|
|
||||||
|
|
||||||
size: outerRadius,
|
size: outerRadius,
|
||||||
startAt: 0,
|
startAt: 0,
|
||||||
endAt: 0,
|
endAt: 0,
|
||||||
innerRadius: 0.9,
|
innerRadius: 0.9,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Overlays.editOverlay(rotateZeroOverlay, { visible: false });
|
||||||
|
Overlays.editOverlay(rotateCurrentOverlay, { visible: false });
|
||||||
|
|
||||||
// TODO: we have not implemented the rotating handle/controls yet... so for now, these handles are hidden
|
// TODO: we have not implemented the rotating handle/controls yet... so for now, these handles are hidden
|
||||||
Overlays.editOverlay(yawHandle, { visible: false, position: yawCorner, rotation: yawHandleRotation});
|
Overlays.editOverlay(yawHandle, { visible: rotateHandlesVisible, position: yawCorner, rotation: yawHandleRotation});
|
||||||
Overlays.editOverlay(pitchHandle, { visible: false, position: pitchCorner, rotation: pitchHandleRotation});
|
Overlays.editOverlay(pitchHandle, { visible: rotateHandlesVisible, position: pitchCorner, rotation: pitchHandleRotation});
|
||||||
Overlays.editOverlay(rollHandle, { visible: false, position: rollCorner, rotation: rollHandleRotation});
|
Overlays.editOverlay(rollHandle, { visible: rotateHandlesVisible, position: rollCorner, rotation: rollHandleRotation});
|
||||||
|
|
||||||
Entities.editEntity(entityID, { localRenderAlpha: 0.1 });
|
Entities.editEntity(entityID, { localRenderAlpha: 0.1 });
|
||||||
};
|
};
|
||||||
|
@ -655,10 +778,14 @@ SelectionDisplay = (function () {
|
||||||
Overlays.editOverlay(pitchHandle, { visible: false });
|
Overlays.editOverlay(pitchHandle, { visible: false });
|
||||||
Overlays.editOverlay(rollHandle, { visible: false });
|
Overlays.editOverlay(rollHandle, { visible: false });
|
||||||
|
|
||||||
|
Overlays.editOverlay(rotateOverlayTarget, { visible: false });
|
||||||
Overlays.editOverlay(rotateOverlayInner, { visible: false });
|
Overlays.editOverlay(rotateOverlayInner, { visible: false });
|
||||||
Overlays.editOverlay(rotateOverlayOuter, { visible: false });
|
Overlays.editOverlay(rotateOverlayOuter, { visible: false });
|
||||||
Overlays.editOverlay(rotateOverlayCurrent, { visible: false });
|
Overlays.editOverlay(rotateOverlayCurrent, { visible: false });
|
||||||
|
|
||||||
|
Overlays.editOverlay(rotateZeroOverlay, { visible: false });
|
||||||
|
Overlays.editOverlay(rotateCurrentOverlay, { visible: false });
|
||||||
|
|
||||||
Entities.editEntity(entityID, { localRenderAlpha: 1.0 });
|
Entities.editEntity(entityID, { localRenderAlpha: 1.0 });
|
||||||
|
|
||||||
currentSelection = { id: -1, isKnownID: false };
|
currentSelection = { id: -1, isKnownID: false };
|
||||||
|
@ -1442,6 +1569,184 @@ SelectionDisplay = (function () {
|
||||||
that.select(currentSelection, false); // TODO: this should be more than highlighted
|
that.select(currentSelection, false); // TODO: this should be more than highlighted
|
||||||
};
|
};
|
||||||
|
|
||||||
|
that.rotateYaw = function(event) {
|
||||||
|
if (!entitySelected || mode !== "ROTATE_YAW") {
|
||||||
|
return; // not allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false});
|
||||||
|
Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true });
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true });
|
||||||
|
|
||||||
|
var result = Overlays.findRayIntersection(pickRay);
|
||||||
|
if (result.intersects) {
|
||||||
|
var properties = Entities.getEntityProperties(currentSelection);
|
||||||
|
var center = yawCenter;
|
||||||
|
var zero = yawZero;
|
||||||
|
var centerToZero = Vec3.subtract(center, zero);
|
||||||
|
var centerToIntersect = Vec3.subtract(center, result.intersection);
|
||||||
|
var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);
|
||||||
|
|
||||||
|
var distanceFromCenter = Vec3.distance(center, result.intersection);
|
||||||
|
var snapToInner = false;
|
||||||
|
if (distanceFromCenter < innerRadius) {
|
||||||
|
angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle;
|
||||||
|
snapToInner = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for debugging
|
||||||
|
//Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection });
|
||||||
|
|
||||||
|
var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 });
|
||||||
|
var newRotation = Quat.multiply(yawChange, originalRotation);
|
||||||
|
|
||||||
|
Entities.editEntity(currentSelection, { rotation: newRotation });
|
||||||
|
|
||||||
|
// update the rotation display accordingly...
|
||||||
|
var startAtCurrent = 0;
|
||||||
|
var endAtCurrent = angleFromZero;
|
||||||
|
var startAtRemainder = angleFromZero;
|
||||||
|
var endAtRemainder = 360;
|
||||||
|
if (angleFromZero < 0) {
|
||||||
|
startAtCurrent = 360 + angleFromZero;
|
||||||
|
endAtCurrent = 360;
|
||||||
|
startAtRemainder = 0;
|
||||||
|
endAtRemainder = startAtCurrent;
|
||||||
|
}
|
||||||
|
if (snapToInner) {
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius });
|
||||||
|
} else {
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
that.rotatePitch = function(event) {
|
||||||
|
if (!entitySelected || mode !== "ROTATE_PITCH") {
|
||||||
|
return; // not allowed
|
||||||
|
}
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false});
|
||||||
|
Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true });
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true });
|
||||||
|
var result = Overlays.findRayIntersection(pickRay);
|
||||||
|
|
||||||
|
if (result.intersects) {
|
||||||
|
var properties = Entities.getEntityProperties(currentSelection);
|
||||||
|
var center = pitchCenter;
|
||||||
|
var zero = pitchZero;
|
||||||
|
var centerToZero = Vec3.subtract(center, zero);
|
||||||
|
var centerToIntersect = Vec3.subtract(center, result.intersection);
|
||||||
|
var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);
|
||||||
|
|
||||||
|
var distanceFromCenter = Vec3.distance(center, result.intersection);
|
||||||
|
var snapToInner = false;
|
||||||
|
if (distanceFromCenter < innerRadius) {
|
||||||
|
angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle;
|
||||||
|
snapToInner = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for debugging
|
||||||
|
//Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection });
|
||||||
|
|
||||||
|
var pitchChange = Quat.fromVec3Degrees({ x: angleFromZero, y: 0, z: 0 });
|
||||||
|
var newRotation = Quat.multiply(pitchChange, originalRotation);
|
||||||
|
|
||||||
|
Entities.editEntity(currentSelection, { rotation: newRotation });
|
||||||
|
|
||||||
|
// update the rotation display accordingly...
|
||||||
|
var startAtCurrent = 0;
|
||||||
|
var endAtCurrent = angleFromZero;
|
||||||
|
var startAtRemainder = angleFromZero;
|
||||||
|
var endAtRemainder = 360;
|
||||||
|
if (angleFromZero < 0) {
|
||||||
|
startAtCurrent = 360 + angleFromZero;
|
||||||
|
endAtCurrent = 360;
|
||||||
|
startAtRemainder = 0;
|
||||||
|
endAtRemainder = startAtCurrent;
|
||||||
|
}
|
||||||
|
if (snapToInner) {
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius });
|
||||||
|
} else {
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
that.rotateRoll = function(event) {
|
||||||
|
if (!entitySelected || mode !== "ROTATE_ROLL") {
|
||||||
|
return; // not allowed
|
||||||
|
}
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false});
|
||||||
|
Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true });
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true });
|
||||||
|
var result = Overlays.findRayIntersection(pickRay);
|
||||||
|
if (result.intersects) {
|
||||||
|
var properties = Entities.getEntityProperties(currentSelection);
|
||||||
|
var center = rollCenter;
|
||||||
|
var zero = rollZero;
|
||||||
|
var centerToZero = Vec3.subtract(center, zero);
|
||||||
|
var centerToIntersect = Vec3.subtract(center, result.intersection);
|
||||||
|
var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);
|
||||||
|
|
||||||
|
var distanceFromCenter = Vec3.distance(center, result.intersection);
|
||||||
|
var snapToInner = false;
|
||||||
|
if (distanceFromCenter < innerRadius) {
|
||||||
|
angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle;
|
||||||
|
snapToInner = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for debugging
|
||||||
|
//Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection });
|
||||||
|
|
||||||
|
var rollChange = Quat.fromVec3Degrees({ x: 0, y: 0, z: angleFromZero });
|
||||||
|
var newRotation = Quat.multiply(rollChange, originalRotation);
|
||||||
|
|
||||||
|
Entities.editEntity(currentSelection, { rotation: newRotation });
|
||||||
|
|
||||||
|
// update the rotation display accordingly...
|
||||||
|
var startAtCurrent = 0;
|
||||||
|
var endAtCurrent = angleFromZero;
|
||||||
|
var startAtRemainder = angleFromZero;
|
||||||
|
var endAtRemainder = 360;
|
||||||
|
if (angleFromZero < 0) {
|
||||||
|
startAtCurrent = 360 + angleFromZero;
|
||||||
|
endAtCurrent = 360;
|
||||||
|
startAtRemainder = 0;
|
||||||
|
endAtRemainder = startAtCurrent;
|
||||||
|
}
|
||||||
|
if (snapToInner) {
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 });
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius });
|
||||||
|
} else {
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 });
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
that.checkMove = function() {
|
that.checkMove = function() {
|
||||||
if (currentSelection.isKnownID &&
|
if (currentSelection.isKnownID &&
|
||||||
(!Vec3.equal(MyAvatar.position, lastAvatarPosition) || !Quat.equal(MyAvatar.orientation, lastAvatarOrientation))){
|
(!Vec3.equal(MyAvatar.position, lastAvatarPosition) || !Quat.equal(MyAvatar.orientation, lastAvatarOrientation))){
|
||||||
|
@ -1477,6 +1782,36 @@ SelectionDisplay = (function () {
|
||||||
case grabberMoveUp:
|
case grabberMoveUp:
|
||||||
mode = "TRANSLATE_UP_DOWN";
|
mode = "TRANSLATE_UP_DOWN";
|
||||||
somethingClicked = true;
|
somethingClicked = true;
|
||||||
|
|
||||||
|
// in translate mode, we hide our stretch handles...
|
||||||
|
Overlays.editOverlay(grabberLBN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLBF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRBN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRBF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLTN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLTF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRTN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRTF, { visible: false });
|
||||||
|
|
||||||
|
Overlays.editOverlay(grabberTOP, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberBOTTOM, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLEFT, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRIGHT, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberNEAR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberFAR, { visible: false });
|
||||||
|
|
||||||
|
Overlays.editOverlay(grabberEdgeTR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeTL, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeTF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeTN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeBR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeBL, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeBF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeBN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeNR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeNL, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeFR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeFL, { visible: false });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case grabberRBN:
|
case grabberRBN:
|
||||||
|
@ -1559,20 +1894,131 @@ SelectionDisplay = (function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if one of the items above was clicked, then we know we are in translate or stretch mode, and we
|
||||||
|
// should hide our rotate handles...
|
||||||
|
if (somethingClicked) {
|
||||||
|
Overlays.editOverlay(yawHandle, { visible: false });
|
||||||
|
Overlays.editOverlay(pitchHandle, { visible: false });
|
||||||
|
Overlays.editOverlay(rollHandle, { visible: false });
|
||||||
|
|
||||||
|
if (mode != "TRANSLATE_UP_DOWN") {
|
||||||
|
Overlays.editOverlay(grabberMoveUp, { visible: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!somethingClicked) {
|
if (!somethingClicked) {
|
||||||
|
|
||||||
|
print("rotate handle case...");
|
||||||
|
|
||||||
// After testing our stretch handles, then check out rotate handles
|
// After testing our stretch handles, then check out rotate handles
|
||||||
Overlays.editOverlay(yawHandle, { ignoreRayIntersection: false });
|
Overlays.editOverlay(yawHandle, { ignoreRayIntersection: false });
|
||||||
Overlays.editOverlay(pitchHandle, { ignoreRayIntersection: false });
|
Overlays.editOverlay(pitchHandle, { ignoreRayIntersection: false });
|
||||||
Overlays.editOverlay(rollHandle, { ignoreRayIntersection: false });
|
Overlays.editOverlay(rollHandle, { ignoreRayIntersection: false });
|
||||||
var result = Overlays.findRayIntersection(pickRay);
|
var result = Overlays.findRayIntersection(pickRay);
|
||||||
|
|
||||||
|
var overlayOrientation;
|
||||||
|
var overlayCenter;
|
||||||
|
|
||||||
|
var properties = Entities.getEntityProperties(currentSelection);
|
||||||
|
var angles = Quat.safeEulerAngles(properties.rotation);
|
||||||
|
var pitch = angles.x;
|
||||||
|
var yaw = angles.y;
|
||||||
|
var roll = angles.z;
|
||||||
|
|
||||||
|
originalRotation = properties.rotation;
|
||||||
|
originalPitch = pitch;
|
||||||
|
originalYaw = yaw;
|
||||||
|
originalRoll = roll;
|
||||||
|
|
||||||
if (result.intersects) {
|
if (result.intersects) {
|
||||||
switch(result.overlayID) {
|
switch(result.overlayID) {
|
||||||
|
case yawHandle:
|
||||||
|
mode = "ROTATE_YAW";
|
||||||
|
somethingClicked = true;
|
||||||
|
overlayOrientation = yawHandleRotation;
|
||||||
|
overlayCenter = yawCenter;
|
||||||
|
yawZero = result.intersection;
|
||||||
|
rotationNormal = yawNormal;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pitchHandle:
|
||||||
|
mode = "ROTATE_PITCH";
|
||||||
|
somethingClicked = true;
|
||||||
|
overlayOrientation = pitchHandleRotation;
|
||||||
|
overlayCenter = pitchCenter;
|
||||||
|
pitchZero = result.intersection;
|
||||||
|
rotationNormal = pitchNormal;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case rollHandle:
|
||||||
|
mode = "ROTATE_ROLL";
|
||||||
|
somethingClicked = true;
|
||||||
|
overlayOrientation = rollHandleRotation;
|
||||||
|
overlayCenter = rollCenter;
|
||||||
|
rollZero = result.intersection;
|
||||||
|
rotationNormal = rollNormal;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print("mousePressEvent()...... " + overlayNames[result.overlayID]);
|
print("mousePressEvent()...... " + overlayNames[result.overlayID]);
|
||||||
mode = "UNKNOWN";
|
mode = "UNKNOWN";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print(" somethingClicked:" + somethingClicked);
|
||||||
|
print(" mode:" + mode);
|
||||||
|
|
||||||
|
|
||||||
|
if (somethingClicked) {
|
||||||
|
|
||||||
|
Overlays.editOverlay(rotateOverlayTarget, { visible: true, rotation: overlayOrientation, position: overlayCenter });
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { visible: true, rotation: overlayOrientation, position: overlayCenter });
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { visible: true, rotation: overlayOrientation, position: overlayCenter, startAt: 0, endAt: 360 });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { visible: true, rotation: overlayOrientation, position: overlayCenter, startAt: 0, endAt: 0 });
|
||||||
|
|
||||||
|
// for debugging
|
||||||
|
//Overlays.editOverlay(rotateZeroOverlay, { visible: true, start: overlayCenter, end: result.intersection });
|
||||||
|
//Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: overlayCenter, end: result.intersection });
|
||||||
|
|
||||||
|
Overlays.editOverlay(yawHandle, { visible: false });
|
||||||
|
Overlays.editOverlay(pitchHandle, { visible: false });
|
||||||
|
Overlays.editOverlay(rollHandle, { visible: false });
|
||||||
|
|
||||||
|
|
||||||
|
Overlays.editOverlay(yawHandle, { visible: false });
|
||||||
|
Overlays.editOverlay(pitchHandle, { visible: false });
|
||||||
|
Overlays.editOverlay(rollHandle, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberMoveUp, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLBN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLBF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRBN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRBF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLTN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLTF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRTN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRTF, { visible: false });
|
||||||
|
|
||||||
|
Overlays.editOverlay(grabberTOP, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberBOTTOM, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberLEFT, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberRIGHT, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberNEAR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberFAR, { visible: false });
|
||||||
|
|
||||||
|
Overlays.editOverlay(grabberEdgeTR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeTL, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeTF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeTN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeBR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeBL, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeBF, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeBN, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeNR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeNL, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeFR, { visible: false });
|
||||||
|
Overlays.editOverlay(grabberEdgeFL, { visible: false });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!somethingClicked) {
|
if (!somethingClicked) {
|
||||||
|
@ -1614,6 +2060,15 @@ SelectionDisplay = (function () {
|
||||||
that.mouseMoveEvent = function(event) {
|
that.mouseMoveEvent = function(event) {
|
||||||
//print("mouseMoveEvent()... mode:" + mode);
|
//print("mouseMoveEvent()... mode:" + mode);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
case "ROTATE_YAW":
|
||||||
|
that.rotateYaw(event);
|
||||||
|
break;
|
||||||
|
case "ROTATE_PITCH":
|
||||||
|
that.rotatePitch(event);
|
||||||
|
break;
|
||||||
|
case "ROTATE_ROLL":
|
||||||
|
that.rotateRoll(event);
|
||||||
|
break;
|
||||||
case "TRANSLATE_UP_DOWN":
|
case "TRANSLATE_UP_DOWN":
|
||||||
that.translateUpDown(event);
|
that.translateUpDown(event);
|
||||||
break;
|
break;
|
||||||
|
@ -1671,14 +2126,34 @@ SelectionDisplay = (function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
that.mouseReleaseEvent = function(event) {
|
that.mouseReleaseEvent = function(event) {
|
||||||
|
var showHandles = false;
|
||||||
|
// hide our rotation overlays..., and show our handles
|
||||||
|
if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL") {
|
||||||
|
Overlays.editOverlay(rotateOverlayTarget, { visible: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayInner, { visible: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayOuter, { visible: false });
|
||||||
|
Overlays.editOverlay(rotateOverlayCurrent, { visible: false });
|
||||||
|
showHandles = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode != "UNKNOWN") {
|
||||||
|
showHandles = true;
|
||||||
|
}
|
||||||
|
|
||||||
mode = "UNKNOWN";
|
mode = "UNKNOWN";
|
||||||
|
|
||||||
// if something is selected, then reset the "original" properties for any potential next click+move operation
|
// if something is selected, then reset the "original" properties for any potential next click+move operation
|
||||||
if (entitySelected) {
|
if (entitySelected) {
|
||||||
|
|
||||||
|
if (showHandles) {
|
||||||
|
that.select(currentSelection, event);
|
||||||
|
}
|
||||||
|
|
||||||
selectedEntityProperties = Entities.getEntityProperties(currentSelection);
|
selectedEntityProperties = Entities.getEntityProperties(currentSelection);
|
||||||
selectedEntityPropertiesOriginalPosition = properties.position;
|
selectedEntityPropertiesOriginalPosition = properties.position;
|
||||||
selectedEntityPropertiesOriginalDimensions = properties.dimensions;
|
selectedEntityPropertiesOriginalDimensions = properties.dimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Controller.mousePressEvent.connect(that.mousePressEvent);
|
Controller.mousePressEvent.connect(that.mousePressEvent);
|
||||||
|
|
|
@ -570,6 +570,19 @@ function handeMenuEvent(menuItem) {
|
||||||
}
|
}
|
||||||
} else if (menuItem == "Edit Properties...") {
|
} else if (menuItem == "Edit Properties...") {
|
||||||
// good place to put the properties dialog
|
// good place to put the properties dialog
|
||||||
|
|
||||||
|
editModelID = -1;
|
||||||
|
if (entitySelected) {
|
||||||
|
print(" Edit Properties.... selectedEntityID="+ selectedEntityID);
|
||||||
|
editModelID = selectedEntityID;
|
||||||
|
} else {
|
||||||
|
print(" Edit Properties.... not holding...");
|
||||||
|
}
|
||||||
|
if (editModelID != -1) {
|
||||||
|
print(" Edit Properties.... about to edit properties...");
|
||||||
|
entityPropertyDialogBox.openDialog(editModelID);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (menuItem == "Paste Models") {
|
} else if (menuItem == "Paste Models") {
|
||||||
modelImporter.paste();
|
modelImporter.paste();
|
||||||
} else if (menuItem == "Export Models") {
|
} else if (menuItem == "Export Models") {
|
||||||
|
|
|
@ -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);
|
|
|
@ -41,7 +41,7 @@ configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVe
|
||||||
|
|
||||||
# grab the implementation and header files from src dirs
|
# grab the implementation and header files from src dirs
|
||||||
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
|
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
|
||||||
foreach(SUBDIR avatar devices renderer ui starfield location scripting voxels particles entities)
|
foreach(SUBDIR avatar devices renderer ui starfield location scripting voxels particles entities gpu)
|
||||||
file(GLOB_RECURSE SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
|
file(GLOB_RECURSE SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
|
||||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
|
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
|
||||||
endforeach(SUBDIR)
|
endforeach(SUBDIR)
|
||||||
|
|
|
@ -605,10 +605,14 @@ void Application::paintGL() {
|
||||||
|
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||||
if (!OculusManager::isConnected()) {
|
if (!OculusManager::isConnected()) {
|
||||||
|
// If there isn't an HMD, match exactly to avatar's head
|
||||||
_myCamera.setPosition(_myAvatar->getHead()->getEyePosition());
|
_myCamera.setPosition(_myAvatar->getHead()->getEyePosition());
|
||||||
_myCamera.setRotation(_myAvatar->getHead()->getCameraOrientation());
|
_myCamera.setRotation(_myAvatar->getHead()->getCameraOrientation());
|
||||||
|
} else {
|
||||||
|
// For an HMD, set the base position and orientation to that of the avatar body
|
||||||
|
_myCamera.setPosition(_myAvatar->getDefaultEyePosition());
|
||||||
|
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation());
|
||||||
}
|
}
|
||||||
// OculusManager::display() updates camera position and rotation a bit further on.
|
|
||||||
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f;
|
static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f;
|
||||||
|
@ -664,7 +668,6 @@ void Application::paintGL() {
|
||||||
|
|
||||||
_viewFrustumOffsetCamera.setRotation(_myCamera.getRotation() * frustumRotation);
|
_viewFrustumOffsetCamera.setRotation(_myCamera.getRotation() * frustumRotation);
|
||||||
|
|
||||||
_viewFrustumOffsetCamera.initialize(); // force immediate snap to ideal position and orientation
|
|
||||||
_viewFrustumOffsetCamera.update(1.f/_fps);
|
_viewFrustumOffsetCamera.update(1.f/_fps);
|
||||||
whichCamera = &_viewFrustumOffsetCamera;
|
whichCamera = &_viewFrustumOffsetCamera;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,16 @@
|
||||||
|
|
||||||
|
|
||||||
Camera::Camera() :
|
Camera::Camera() :
|
||||||
_needsToInitialize(true),
|
|
||||||
_mode(CAMERA_MODE_THIRD_PERSON),
|
_mode(CAMERA_MODE_THIRD_PERSON),
|
||||||
_position(0.0f, 0.0f, 0.0f),
|
_position(0.0f, 0.0f, 0.0f),
|
||||||
_fieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES),
|
_fieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES),
|
||||||
_aspectRatio(16.0f/9.0f),
|
_aspectRatio(16.0f/9.0f),
|
||||||
_nearClip(DEFAULT_NEAR_CLIP), // default
|
_nearClip(DEFAULT_NEAR_CLIP), // default
|
||||||
_farClip(DEFAULT_FAR_CLIP), // default
|
_farClip(DEFAULT_FAR_CLIP), // default
|
||||||
|
_hmdPosition(),
|
||||||
|
_hmdRotation(),
|
||||||
|
_targetPosition(),
|
||||||
|
_targetRotation(),
|
||||||
_scale(1.0f)
|
_scale(1.0f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -64,26 +67,6 @@ void Camera::setFarClip(float f) {
|
||||||
_farClip = f;
|
_farClip = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setEyeOffsetPosition(const glm::vec3& p) {
|
|
||||||
_eyeOffsetPosition = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::setEyeOffsetOrientation(const glm::quat& o) {
|
|
||||||
_eyeOffsetOrientation = o;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::setScale(float s) {
|
|
||||||
_scale = s;
|
|
||||||
_needsToInitialize = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::initialize() {
|
|
||||||
_needsToInitialize = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CameraScriptableObject::CameraScriptableObject(Camera* camera, ViewFrustum* viewFrustum) :
|
CameraScriptableObject::CameraScriptableObject(Camera* camera, ViewFrustum* viewFrustum) :
|
||||||
_camera(camera), _viewFrustum(viewFrustum)
|
_camera(camera), _viewFrustum(viewFrustum)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,17 +38,23 @@ public:
|
||||||
|
|
||||||
void setPosition(const glm::vec3& p) { _position = p; }
|
void setPosition(const glm::vec3& p) { _position = p; }
|
||||||
void setRotation(const glm::quat& rotation) { _rotation = rotation; };
|
void setRotation(const glm::quat& rotation) { _rotation = rotation; };
|
||||||
|
void setHmdPosition(const glm::vec3& hmdPosition) { _hmdPosition = hmdPosition; }
|
||||||
|
void setHmdRotation(const glm::quat& hmdRotation) { _hmdRotation = hmdRotation; };
|
||||||
|
|
||||||
void setMode(CameraMode m);
|
void setMode(CameraMode m);
|
||||||
void setFieldOfView(float f);
|
void setFieldOfView(float f);
|
||||||
void setAspectRatio(float a);
|
void setAspectRatio(float a);
|
||||||
void setNearClip(float n);
|
void setNearClip(float n);
|
||||||
void setFarClip(float f);
|
void setFarClip(float f);
|
||||||
void setEyeOffsetPosition(const glm::vec3& p);
|
void setEyeOffsetPosition(const glm::vec3& p) { _eyeOffsetPosition = p; }
|
||||||
void setEyeOffsetOrientation(const glm::quat& o);
|
void setEyeOffsetOrientation(const glm::quat& o) { _eyeOffsetOrientation = o; }
|
||||||
void setScale(const float s);
|
void setScale(const float s) { _scale = s; }
|
||||||
|
|
||||||
|
glm::vec3 getPosition() const { return _position + _hmdPosition; }
|
||||||
|
glm::quat getRotation() const { return _rotation * _hmdRotation; }
|
||||||
|
const glm::vec3& getHmdPosition() const { return _hmdPosition; }
|
||||||
|
const glm::quat& getHmdRotation() const { return _hmdRotation; }
|
||||||
|
|
||||||
const glm::vec3& getPosition() const { return _position; }
|
|
||||||
const glm::quat& getRotation() const { return _rotation; }
|
|
||||||
CameraMode getMode() const { return _mode; }
|
CameraMode getMode() const { return _mode; }
|
||||||
float getFieldOfView() const { return _fieldOfView; }
|
float getFieldOfView() const { return _fieldOfView; }
|
||||||
float getAspectRatio() const { return _aspectRatio; }
|
float getAspectRatio() const { return _aspectRatio; }
|
||||||
|
@ -60,7 +66,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool _needsToInitialize;
|
|
||||||
CameraMode _mode;
|
CameraMode _mode;
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
float _fieldOfView; // degrees
|
float _fieldOfView; // degrees
|
||||||
|
@ -70,7 +75,10 @@ private:
|
||||||
glm::vec3 _eyeOffsetPosition;
|
glm::vec3 _eyeOffsetPosition;
|
||||||
glm::quat _eyeOffsetOrientation;
|
glm::quat _eyeOffsetOrientation;
|
||||||
glm::quat _rotation;
|
glm::quat _rotation;
|
||||||
|
glm::vec3 _hmdPosition;
|
||||||
|
glm::quat _hmdRotation;
|
||||||
|
glm::vec3 _targetPosition;
|
||||||
|
glm::quat _targetRotation;
|
||||||
float _scale;
|
float _scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1151,7 +1151,7 @@ const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
|
||||||
|
|
||||||
bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {
|
bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {
|
||||||
const Head* head = getHead();
|
const Head* head = getHead();
|
||||||
return (renderMode != NORMAL_RENDER_MODE) ||
|
return (renderMode != NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) ||
|
||||||
(glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
(glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -337,15 +337,20 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
|
||||||
#else
|
#else
|
||||||
ovrEyeType eye = _ovrHmdDesc.EyeRenderOrder[eyeIndex];
|
ovrEyeType eye = _ovrHmdDesc.EyeRenderOrder[eyeIndex];
|
||||||
#endif
|
#endif
|
||||||
//Set the camera rotation for this eye
|
// Set the camera rotation for this eye
|
||||||
eyeRenderPose[eye] = ovrHmd_GetEyePose(_ovrHmd, eye);
|
eyeRenderPose[eye] = ovrHmd_GetEyePose(_ovrHmd, eye);
|
||||||
orientation.x = eyeRenderPose[eye].Orientation.x;
|
orientation.x = eyeRenderPose[eye].Orientation.x;
|
||||||
orientation.y = eyeRenderPose[eye].Orientation.y;
|
orientation.y = eyeRenderPose[eye].Orientation.y;
|
||||||
orientation.z = eyeRenderPose[eye].Orientation.z;
|
orientation.z = eyeRenderPose[eye].Orientation.z;
|
||||||
orientation.w = eyeRenderPose[eye].Orientation.w;
|
orientation.w = eyeRenderPose[eye].Orientation.w;
|
||||||
|
|
||||||
_camera->setRotation(bodyOrientation * orientation);
|
// Update the application camera with the latest HMD position
|
||||||
_camera->setPosition(position + trackerPosition);
|
whichCamera.setHmdPosition(trackerPosition);
|
||||||
|
whichCamera.setHmdRotation(orientation);
|
||||||
|
|
||||||
|
// Update our camera to what the application camera is doing
|
||||||
|
_camera->setRotation(whichCamera.getRotation());
|
||||||
|
_camera->setPosition(whichCamera.getPosition());
|
||||||
|
|
||||||
// Store the latest left and right eye render locations for things that need to know
|
// Store the latest left and right eye render locations for things that need to know
|
||||||
glm::vec3 thisEyePosition = position + trackerPosition +
|
glm::vec3 thisEyePosition = position + trackerPosition +
|
||||||
|
@ -408,9 +413,6 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
// Update camera for use by rest of Interface.
|
|
||||||
whichCamera.setPosition((_leftEyePosition + _rightEyePosition) / 2.f);
|
|
||||||
whichCamera.setRotation(_camera->getRotation());
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
220
interface/src/gpu/Resource.cpp
Normal file
220
interface/src/gpu/Resource.cpp
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
//
|
||||||
|
// Resource.cpp
|
||||||
|
// interface/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 10/8/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
|
||||||
|
//
|
||||||
|
#include "Resource.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
using namespace gpu;
|
||||||
|
|
||||||
|
Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size) {
|
||||||
|
if ( !dataAllocated ) {
|
||||||
|
qWarning() << "Buffer::Sysmem::allocateMemory() : Must have a valid dataAllocated pointer.";
|
||||||
|
return NOT_ALLOCATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to allocate if needed
|
||||||
|
Size newSize = 0;
|
||||||
|
if (size > 0) {
|
||||||
|
// Try allocating as much as the required size + one block of memory
|
||||||
|
newSize = size;
|
||||||
|
(*dataAllocated) = new Byte[newSize];
|
||||||
|
// Failed?
|
||||||
|
if (!(*dataAllocated)) {
|
||||||
|
qWarning() << "Buffer::Sysmem::allocate() : Can't allocate a system memory buffer of " << newSize << "bytes. Fails to create the buffer Sysmem.";
|
||||||
|
return NOT_ALLOCATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return what's actually allocated
|
||||||
|
return newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resource::Sysmem::deallocateMemory(Byte* dataAllocated, Size size) {
|
||||||
|
if (dataAllocated) {
|
||||||
|
delete[] dataAllocated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Sysmem::Sysmem() :
|
||||||
|
_data(NULL),
|
||||||
|
_size(0),
|
||||||
|
_stamp(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Sysmem::Sysmem(Size size, const Byte* bytes) :
|
||||||
|
_data(NULL),
|
||||||
|
_size(0),
|
||||||
|
_stamp(0)
|
||||||
|
{
|
||||||
|
if (size > 0) {
|
||||||
|
_size = allocateMemory(&_data, size);
|
||||||
|
if (_size >= size) {
|
||||||
|
if (bytes) {
|
||||||
|
memcpy(_data, bytes, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Sysmem::~Sysmem() {
|
||||||
|
deallocateMemory( _data, _size );
|
||||||
|
_data = NULL;
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Size Resource::Sysmem::allocate(Size size) {
|
||||||
|
if (size != _size) {
|
||||||
|
Byte* newData = 0;
|
||||||
|
Size newSize = 0;
|
||||||
|
if (size > 0) {
|
||||||
|
Size allocated = allocateMemory(&newData, size);
|
||||||
|
if (allocated == NOT_ALLOCATED) {
|
||||||
|
// early exit because allocation failed
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
newSize = allocated;
|
||||||
|
}
|
||||||
|
// Allocation was successful, can delete previous data
|
||||||
|
deallocateMemory(_data, _size);
|
||||||
|
_data = newData;
|
||||||
|
_size = newSize;
|
||||||
|
_stamp++;
|
||||||
|
}
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Size Resource::Sysmem::resize(Size size) {
|
||||||
|
if (size != _size) {
|
||||||
|
Byte* newData = 0;
|
||||||
|
Size newSize = 0;
|
||||||
|
if (size > 0) {
|
||||||
|
Size allocated = allocateMemory(&newData, size);
|
||||||
|
if (allocated == NOT_ALLOCATED) {
|
||||||
|
// early exit because allocation failed
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
newSize = allocated;
|
||||||
|
// Restore back data from old buffer in the new one
|
||||||
|
if (_data) {
|
||||||
|
Size copySize = ((newSize < _size)? newSize: _size);
|
||||||
|
memcpy( newData, _data, copySize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reallocation was successful, can delete previous data
|
||||||
|
deallocateMemory(_data, _size);
|
||||||
|
_data = newData;
|
||||||
|
_size = newSize;
|
||||||
|
_stamp++;
|
||||||
|
}
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) {
|
||||||
|
if (allocate(size) == size) {
|
||||||
|
if (bytes) {
|
||||||
|
memcpy( _data, bytes, _size );
|
||||||
|
_stamp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Size Resource::Sysmem::setSubData( Size offset, Size size, const Byte* bytes) {
|
||||||
|
if (((offset + size) <= getSize()) && bytes) {
|
||||||
|
memcpy( _data + offset, bytes, size );
|
||||||
|
_stamp++;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Size Resource::Sysmem::append(Size size, const Byte* bytes) {
|
||||||
|
if (size > 0) {
|
||||||
|
Size oldSize = getSize();
|
||||||
|
Size totalSize = oldSize + size;
|
||||||
|
if (resize(totalSize) == totalSize) {
|
||||||
|
return setSubData(oldSize, size, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::Buffer() :
|
||||||
|
Resource(),
|
||||||
|
_sysmem(NULL),
|
||||||
|
_gpuObject(NULL) {
|
||||||
|
_sysmem = new Sysmem();
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::~Buffer() {
|
||||||
|
if (_sysmem) {
|
||||||
|
delete _sysmem;
|
||||||
|
_sysmem = 0;
|
||||||
|
}
|
||||||
|
if (_gpuObject) {
|
||||||
|
delete _gpuObject;
|
||||||
|
_gpuObject = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::Size Buffer::resize(Size size) {
|
||||||
|
return editSysmem().resize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::Size Buffer::setData(Size size, const Byte* data) {
|
||||||
|
return editSysmem().setData(size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::Size Buffer::setSubData(Size offset, Size size, const Byte* data) {
|
||||||
|
return editSysmem().setSubData( offset, size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::Size Buffer::append(Size size, const Byte* data) {
|
||||||
|
return editSysmem().append( size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace gpu {
|
||||||
|
namespace backend {
|
||||||
|
|
||||||
|
BufferObject::~BufferObject() {
|
||||||
|
if (_buffer!=0) {
|
||||||
|
glDeleteBuffers(1, &_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncGPUObject(const Buffer& buffer) {
|
||||||
|
BufferObject* object = buffer.getGPUObject();
|
||||||
|
|
||||||
|
if (object && (object->_stamp == buffer.getSysmem().getStamp())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to have a gpu object?
|
||||||
|
if (!object) {
|
||||||
|
object = new BufferObject();
|
||||||
|
glGenBuffers(1, &object->_buffer);
|
||||||
|
buffer.setGPUObject(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now let's update the content of the bo with the sysmem version
|
||||||
|
// TODO: in the future, be smarter about when to actually upload the glBO version based on the data that did change
|
||||||
|
//if () {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, object->_buffer);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, buffer.getSysmem().getSize(), buffer.getSysmem().readData(), GL_DYNAMIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
object->_stamp = buffer.getSysmem().getStamp();
|
||||||
|
object->_size = buffer.getSysmem().getSize();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
166
interface/src/gpu/Resource.h
Normal file
166
interface/src/gpu/Resource.h
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
//
|
||||||
|
// Resource.h
|
||||||
|
// interface/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 10/8/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
|
||||||
|
//
|
||||||
|
#ifndef hifi_gpu_Resource_h
|
||||||
|
#define hifi_gpu_Resource_h
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
|
namespace gpu {
|
||||||
|
|
||||||
|
class Buffer;
|
||||||
|
typedef int Stamp;
|
||||||
|
|
||||||
|
// TODO: move the backend namespace into dedicated files, for now we keep it close to the gpu objects definition for convenience
|
||||||
|
namespace backend {
|
||||||
|
|
||||||
|
class BufferObject {
|
||||||
|
public:
|
||||||
|
Stamp _stamp;
|
||||||
|
GLuint _buffer;
|
||||||
|
GLuint _size;
|
||||||
|
|
||||||
|
BufferObject() :
|
||||||
|
_stamp(0),
|
||||||
|
_buffer(0),
|
||||||
|
_size(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~BufferObject();
|
||||||
|
};
|
||||||
|
void syncGPUObject(const Buffer& buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Resource {
|
||||||
|
public:
|
||||||
|
typedef unsigned char Byte;
|
||||||
|
typedef unsigned int Size;
|
||||||
|
|
||||||
|
static const Size NOT_ALLOCATED = -1;
|
||||||
|
|
||||||
|
// The size in bytes of data stored in the resource
|
||||||
|
virtual Size getSize() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Resource() {}
|
||||||
|
virtual ~Resource() {}
|
||||||
|
|
||||||
|
// Sysmem is the underneath cache for the data in ram of a resource.
|
||||||
|
class Sysmem {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Sysmem();
|
||||||
|
Sysmem(Size size, const Byte* bytes);
|
||||||
|
~Sysmem();
|
||||||
|
|
||||||
|
Size getSize() const { return _size; }
|
||||||
|
|
||||||
|
// Allocate the byte array
|
||||||
|
// \param pSize The nb of bytes to allocate, if already exist, content is lost.
|
||||||
|
// \return The nb of bytes allocated, nothing if allready the appropriate size.
|
||||||
|
Size allocate(Size pSize);
|
||||||
|
|
||||||
|
// Resize the byte array
|
||||||
|
// Keep previous data [0 to min(pSize, mSize)]
|
||||||
|
Size resize(Size pSize);
|
||||||
|
|
||||||
|
// Assign data bytes and size (allocate for size, then copy bytes if exists)
|
||||||
|
Size setData(Size size, const Byte* bytes );
|
||||||
|
|
||||||
|
// Update Sub data,
|
||||||
|
// doesn't allocate and only copy size * bytes at the offset location
|
||||||
|
// only if all fits in the existing allocated buffer
|
||||||
|
Size setSubData(Size offset, Size size, const Byte* bytes);
|
||||||
|
|
||||||
|
// Append new data at the end of the current buffer
|
||||||
|
// do a resize( size + getSIze) and copy the new data
|
||||||
|
// \return the number of bytes copied
|
||||||
|
Size append(Size size, const Byte* data);
|
||||||
|
|
||||||
|
// Access the byte array.
|
||||||
|
// The edit version allow to map data.
|
||||||
|
inline const Byte* readData() const { return _data; }
|
||||||
|
inline Byte* editData() { _stamp++; return _data; }
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
const T* read() const { return reinterpret_cast< T* > ( _data ); }
|
||||||
|
template< typename T >
|
||||||
|
T* edit() { _stamp++; return reinterpret_cast< T* > ( _data ); }
|
||||||
|
|
||||||
|
// Access the current version of the sysmem, used to compare if copies are in sync
|
||||||
|
inline Stamp getStamp() const { return _stamp; }
|
||||||
|
|
||||||
|
static Size allocateMemory(Byte** memAllocated, Size size);
|
||||||
|
static void deallocateMemory(Byte* memDeallocated, Size size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Sysmem(const Sysmem& sysmem) {}
|
||||||
|
Sysmem &operator=(const Sysmem& other) {return *this;}
|
||||||
|
|
||||||
|
Stamp _stamp;
|
||||||
|
Size _size;
|
||||||
|
Byte* _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Buffer : public Resource {
|
||||||
|
public:
|
||||||
|
|
||||||
|
Buffer();
|
||||||
|
Buffer(const Buffer& buf);
|
||||||
|
~Buffer();
|
||||||
|
|
||||||
|
// The size in bytes of data stored in the buffer
|
||||||
|
inline Size getSize() const { return getSysmem().getSize(); }
|
||||||
|
inline const Byte* getData() const { return getSysmem().readData(); }
|
||||||
|
|
||||||
|
// Resize the buffer
|
||||||
|
// Keep previous data [0 to min(pSize, mSize)]
|
||||||
|
Size resize(Size pSize);
|
||||||
|
|
||||||
|
// Assign data bytes and size (allocate for size, then copy bytes if exists)
|
||||||
|
// \return the size of the buffer
|
||||||
|
Size setData(Size size, const Byte* data);
|
||||||
|
|
||||||
|
// Assign data bytes and size (allocate for size, then copy bytes if exists)
|
||||||
|
// \return the number of bytes copied
|
||||||
|
Size setSubData(Size offset, Size size, const Byte* data);
|
||||||
|
|
||||||
|
// Append new data at the end of the current buffer
|
||||||
|
// do a resize( size + getSize) and copy the new data
|
||||||
|
// \return the number of bytes copied
|
||||||
|
Size append(Size size, const Byte* data);
|
||||||
|
|
||||||
|
// this is a temporary hack so the current rendering code can access the underneath gl Buffer Object
|
||||||
|
// TODO: remove asap, when the backend is doing more of the gl features
|
||||||
|
inline GLuint getGLBufferObject() const { backend::syncGPUObject(*this); return getGPUObject()->_buffer; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Sysmem* _sysmem;
|
||||||
|
|
||||||
|
typedef backend::BufferObject GPUObject;
|
||||||
|
mutable backend::BufferObject* _gpuObject;
|
||||||
|
|
||||||
|
inline const Sysmem& getSysmem() const { assert(_sysmem); return (*_sysmem); }
|
||||||
|
inline Sysmem& editSysmem() { assert(_sysmem); return (*_sysmem); }
|
||||||
|
|
||||||
|
inline GPUObject* getGPUObject() const { return _gpuObject; }
|
||||||
|
inline void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||||
|
|
||||||
|
friend void backend::syncGPUObject(const Buffer& buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -690,7 +690,6 @@ void Stats::display(
|
||||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stats::setMetavoxelStats(int internal, int leaves, int sendProgress,
|
void Stats::setMetavoxelStats(int internal, int leaves, int sendProgress,
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "TextRenderer.h"
|
#include "TextRenderer.h"
|
||||||
|
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
|
||||||
// the width/height of the cached glyph textures
|
// the width/height of the cached glyph textures
|
||||||
const int IMAGE_SIZE = 256;
|
const int IMAGE_SIZE = 256;
|
||||||
|
|
||||||
|
@ -63,7 +67,16 @@ int TextRenderer::calculateHeight(const char* str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int TextRenderer::draw(int x, int y, const char* str) {
|
int TextRenderer::draw(int x, int y, const char* str) {
|
||||||
glEnable(GL_TEXTURE_2D);
|
// Grab the current color
|
||||||
|
float currentColor[4];
|
||||||
|
glGetFloatv(GL_CURRENT_COLOR, currentColor);
|
||||||
|
int compactColor = ((int( currentColor[0] * 255.f) & 0xFF)) |
|
||||||
|
((int( currentColor[1] * 255.f) & 0xFF) << 8) |
|
||||||
|
((int( currentColor[2] * 255.f) & 0xFF) << 16) |
|
||||||
|
((int( currentColor[3] * 255.f) & 0xFF) << 24);
|
||||||
|
|
||||||
|
// TODO: Remove that code once we test for performance improvments
|
||||||
|
//glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
int maxHeight = 0;
|
int maxHeight = 0;
|
||||||
for (const char* ch = str; *ch != 0; ch++) {
|
for (const char* ch = str; *ch != 0; ch++) {
|
||||||
|
@ -76,20 +89,24 @@ int TextRenderer::draw(int x, int y, const char* str) {
|
||||||
if (glyph.bounds().height() > maxHeight) {
|
if (glyph.bounds().height() > maxHeight) {
|
||||||
maxHeight = glyph.bounds().height();
|
maxHeight = glyph.bounds().height();
|
||||||
}
|
}
|
||||||
|
//glBindTexture(GL_TEXTURE_2D, glyph.textureID());
|
||||||
glBindTexture(GL_TEXTURE_2D, glyph.textureID());
|
|
||||||
|
|
||||||
int left = x + glyph.bounds().x();
|
int left = x + glyph.bounds().x();
|
||||||
int right = x + glyph.bounds().x() + glyph.bounds().width();
|
int right = x + glyph.bounds().x() + glyph.bounds().width();
|
||||||
int bottom = y + glyph.bounds().y();
|
int bottom = y + glyph.bounds().y();
|
||||||
int top = y + glyph.bounds().y() + glyph.bounds().height();
|
int top = y + glyph.bounds().y() + glyph.bounds().height();
|
||||||
|
|
||||||
|
glm::vec2 leftBottom = glm::vec2(float(left), float(bottom));
|
||||||
|
glm::vec2 rightTop = glm::vec2(float(right), float(top));
|
||||||
|
|
||||||
float scale = QApplication::desktop()->windowHandle()->devicePixelRatio() / IMAGE_SIZE;
|
float scale = QApplication::desktop()->windowHandle()->devicePixelRatio() / IMAGE_SIZE;
|
||||||
float ls = glyph.location().x() * scale;
|
float ls = glyph.location().x() * scale;
|
||||||
float rs = (glyph.location().x() + glyph.bounds().width()) * scale;
|
float rs = (glyph.location().x() + glyph.bounds().width()) * scale;
|
||||||
float bt = glyph.location().y() * scale;
|
float bt = glyph.location().y() * scale;
|
||||||
float tt = (glyph.location().y() + glyph.bounds().height()) * scale;
|
float tt = (glyph.location().y() + glyph.bounds().height()) * scale;
|
||||||
|
|
||||||
|
// TODO: Remove that code once we test for performance improvments
|
||||||
|
/*
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2f(ls, bt);
|
glTexCoord2f(ls, bt);
|
||||||
glVertex2f(left, bottom);
|
glVertex2f(left, bottom);
|
||||||
|
@ -100,11 +117,38 @@ int TextRenderer::draw(int x, int y, const char* str) {
|
||||||
glTexCoord2f(ls, tt);
|
glTexCoord2f(ls, tt);
|
||||||
glVertex2f(left, top);
|
glVertex2f(left, top);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
*/
|
||||||
|
|
||||||
|
const int NUM_COORDS_SCALARS_PER_GLYPH = 16;
|
||||||
|
float vertexBuffer[NUM_COORDS_SCALARS_PER_GLYPH] = { leftBottom.x, leftBottom.y, ls, bt,
|
||||||
|
rightTop.x, leftBottom.y, rs, bt,
|
||||||
|
rightTop.x, rightTop.y, rs, tt,
|
||||||
|
leftBottom.x, rightTop.y, ls, tt, };
|
||||||
|
|
||||||
|
const int NUM_COLOR_SCALARS_PER_GLYPH = 4;
|
||||||
|
unsigned int colorBuffer[NUM_COLOR_SCALARS_PER_GLYPH] = { compactColor, compactColor, compactColor, compactColor };
|
||||||
|
|
||||||
|
gpu::Buffer::Size offset = sizeof(vertexBuffer) * _numGlyphsBatched;
|
||||||
|
gpu::Buffer::Size colorOffset = sizeof(colorBuffer) * _numGlyphsBatched;
|
||||||
|
if ((offset + sizeof(vertexBuffer)) > _glyphsBuffer.getSize()) {
|
||||||
|
_glyphsBuffer.append(sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer);
|
||||||
|
_glyphsColorBuffer.append(sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer);
|
||||||
|
} else {
|
||||||
|
_glyphsBuffer.setSubData(offset, sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer);
|
||||||
|
_glyphsColorBuffer.setSubData(colorOffset, sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer);
|
||||||
|
}
|
||||||
|
_numGlyphsBatched++;
|
||||||
|
|
||||||
x += glyph.width();
|
x += glyph.width();
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
// TODO: remove these calls once we move to a full batched rendering of the text, for now, one draw call per draw() function call
|
||||||
|
drawBatch();
|
||||||
|
clearBatch();
|
||||||
|
|
||||||
|
// TODO: Remove that code once we test for performance improvments
|
||||||
|
// glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
// glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
return maxHeight;
|
return maxHeight;
|
||||||
}
|
}
|
||||||
|
@ -131,8 +175,10 @@ TextRenderer::TextRenderer(const Properties& properties) :
|
||||||
_x(IMAGE_SIZE),
|
_x(IMAGE_SIZE),
|
||||||
_y(IMAGE_SIZE),
|
_y(IMAGE_SIZE),
|
||||||
_rowHeight(0),
|
_rowHeight(0),
|
||||||
_color(properties.color) {
|
_color(properties.color),
|
||||||
|
_glyphsBuffer(),
|
||||||
|
_numGlyphsBatched(0)
|
||||||
|
{
|
||||||
_font.setKerning(false);
|
_font.setKerning(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,9 +274,74 @@ const Glyph& TextRenderer::getGlyph(char c) {
|
||||||
return glyph;
|
return glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextRenderer::drawBatch() {
|
||||||
|
if (_numGlyphsBatched <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Right now the drawBatch is called while calling the draw() function but in the future we'll need to apply the correct transform stack
|
||||||
|
/*
|
||||||
|
GLint matrixMode;
|
||||||
|
glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
*/
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
// TODO: Apply the correct font atlas texture, for now only one texture per TextRenderer so it should be good
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _currentTextureID);
|
||||||
|
|
||||||
|
GLuint vbo = _glyphsBuffer.getGLBufferObject();
|
||||||
|
GLuint colorvbo = _glyphsColorBuffer.getGLBufferObject();
|
||||||
|
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
|
const int NUM_POS_COORDS = 2;
|
||||||
|
const int NUM_TEX_COORDS = 2;
|
||||||
|
const int VERTEX_STRIDE = (NUM_POS_COORDS + NUM_TEX_COORDS) * sizeof(float);
|
||||||
|
const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
glVertexPointer(2, GL_FLOAT, VERTEX_STRIDE, 0);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, VERTEX_STRIDE, (GLvoid*) VERTEX_TEXCOORD_OFFSET );
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, colorvbo);
|
||||||
|
glColorPointer(4, GL_UNSIGNED_BYTE, 0, (GLvoid*) 0 );
|
||||||
|
|
||||||
|
glDrawArrays(GL_QUADS, 0, _numGlyphsBatched * 4);
|
||||||
|
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
// TODO: Right now the drawBatch is called while calling the draw() function but in the future we'll need to apply the correct transform stack
|
||||||
|
/*
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(matrixMode);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextRenderer::clearBatch() {
|
||||||
|
_numGlyphsBatched = 0;
|
||||||
|
}
|
||||||
|
|
||||||
QHash<TextRenderer::Properties, TextRenderer*> TextRenderer::_instances;
|
QHash<TextRenderer::Properties, TextRenderer*> TextRenderer::_instances;
|
||||||
|
|
||||||
Glyph::Glyph(int textureID, const QPoint& location, const QRect& bounds, int width) :
|
Glyph::Glyph(int textureID, const QPoint& location, const QRect& bounds, int width) :
|
||||||
_textureID(textureID), _location(location), _bounds(bounds), _width(width) {
|
_textureID(textureID), _location(location), _bounds(bounds), _width(width) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
|
#include "gpu/Resource.h"
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
// a special "character" that renders as a solid block
|
// a special "character" that renders as a solid block
|
||||||
|
@ -64,6 +66,8 @@ public:
|
||||||
int computeWidth(char ch);
|
int computeWidth(char ch);
|
||||||
int computeWidth(const char* str);
|
int computeWidth(const char* str);
|
||||||
|
|
||||||
|
void drawBatch();
|
||||||
|
void clearBatch();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
TextRenderer(const Properties& properties);
|
TextRenderer(const Properties& properties);
|
||||||
|
@ -100,6 +104,11 @@ private:
|
||||||
// text color
|
// text color
|
||||||
QColor _color;
|
QColor _color;
|
||||||
|
|
||||||
|
// Graphics Buffer containing the current accumulated glyphs to render
|
||||||
|
gpu::Buffer _glyphsBuffer;
|
||||||
|
gpu::Buffer _glyphsColorBuffer;
|
||||||
|
int _numGlyphsBatched;
|
||||||
|
|
||||||
static QHash<Properties, TextRenderer*> _instances;
|
static QHash<Properties, TextRenderer*> _instances;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
BillboardOverlay::BillboardOverlay()
|
BillboardOverlay::BillboardOverlay()
|
||||||
: _fromImage(-1,-1,-1,-1),
|
: _fromImage(-1,-1,-1,-1),
|
||||||
_scale(1.0f),
|
_scale(1.0f),
|
||||||
_isFacingAvatar(true) {
|
_isFacingAvatar(true),
|
||||||
|
_newTextureNeeded(true) {
|
||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +29,9 @@ void BillboardOverlay::render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_billboard.isEmpty()) {
|
if (!_billboard.isEmpty()) {
|
||||||
|
if (_newTextureNeeded && _billboardTexture) {
|
||||||
|
_billboardTexture.reset();
|
||||||
|
}
|
||||||
if (!_billboardTexture) {
|
if (!_billboardTexture) {
|
||||||
QImage image = QImage::fromData(_billboard);
|
QImage image = QImage::fromData(_billboard);
|
||||||
if (image.format() != QImage::Format_ARGB32) {
|
if (image.format() != QImage::Format_ARGB32) {
|
||||||
|
@ -38,6 +42,7 @@ void BillboardOverlay::render() {
|
||||||
_fromImage.setRect(0, 0, _size.width(), _size.height());
|
_fromImage.setRect(0, 0, _size.width(), _size.height());
|
||||||
}
|
}
|
||||||
_billboardTexture.reset(new Texture());
|
_billboardTexture.reset(new Texture());
|
||||||
|
_newTextureNeeded = false;
|
||||||
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
|
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _size.width(), _size.height(), 0,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _size.width(), _size.height(), 0,
|
||||||
GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
|
GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
|
||||||
|
@ -107,9 +112,10 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
|
||||||
|
|
||||||
QScriptValue urlValue = properties.property("url");
|
QScriptValue urlValue = properties.property("url");
|
||||||
if (urlValue.isValid()) {
|
if (urlValue.isValid()) {
|
||||||
_url = urlValue.toVariant().toString();
|
QString newURL = urlValue.toVariant().toString();
|
||||||
|
if (newURL != _url) {
|
||||||
setBillboardURL(_url);
|
setBillboardURL(newURL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue subImageBounds = properties.property("subImage");
|
QScriptValue subImageBounds = properties.property("subImage");
|
||||||
|
@ -150,9 +156,16 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BillboardOverlay::setBillboardURL(const QUrl url) {
|
void BillboardOverlay::setBillboardURL(const QString& url) {
|
||||||
|
_url = url;
|
||||||
|
QUrl actualURL = url;
|
||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
QNetworkReply* reply = NetworkAccessManager::getInstance().get(QNetworkRequest(url));
|
|
||||||
|
// clear the billboard if previously set
|
||||||
|
_billboard.clear();
|
||||||
|
_newTextureNeeded = true;
|
||||||
|
|
||||||
|
QNetworkReply* reply = NetworkAccessManager::getInstance().get(QNetworkRequest(actualURL));
|
||||||
connect(reply, &QNetworkReply::finished, this, &BillboardOverlay::replyFinished);
|
connect(reply, &QNetworkReply::finished, this, &BillboardOverlay::replyFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,13 @@ private slots:
|
||||||
void replyFinished();
|
void replyFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setBillboardURL(const QUrl url);
|
void setBillboardURL(const QString& url);
|
||||||
|
|
||||||
QUrl _url;
|
QString _url;
|
||||||
QByteArray _billboard;
|
QByteArray _billboard;
|
||||||
QSize _size;
|
QSize _size;
|
||||||
QScopedPointer<Texture> _billboardTexture;
|
QScopedPointer<Texture> _billboardTexture;
|
||||||
|
bool _newTextureNeeded;
|
||||||
|
|
||||||
QRect _fromImage; // where from in the image to sample
|
QRect _fromImage; // where from in the image to sample
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
#include <StreamUtils.h>
|
||||||
|
|
||||||
#include "Circle3DOverlay.h"
|
#include "Circle3DOverlay.h"
|
||||||
#include "renderer/GlowEffect.h"
|
#include "renderer/GlowEffect.h"
|
||||||
|
@ -40,12 +41,17 @@ void Circle3DOverlay::render() {
|
||||||
return; // do nothing if we're not visible
|
return; // do nothing if we're not visible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float alpha = getAlpha();
|
||||||
|
|
||||||
|
if (alpha == 0.0) {
|
||||||
|
return; // do nothing if our alpha is 0, we're not visible
|
||||||
|
}
|
||||||
|
|
||||||
const float FULL_CIRCLE = 360.0f;
|
const float FULL_CIRCLE = 360.0f;
|
||||||
const float SLICES = 180.0f; // The amount of segment to create the circle
|
const float SLICES = 180.0f; // The amount of segment to create the circle
|
||||||
const float SLICE_ANGLE = FULL_CIRCLE / SLICES;
|
const float SLICE_ANGLE = FULL_CIRCLE / SLICES;
|
||||||
|
|
||||||
//const int slices = 15;
|
//const int slices = 15;
|
||||||
float alpha = getAlpha();
|
|
||||||
xColor color = getColor();
|
xColor color = getColor();
|
||||||
const float MAX_COLOR = 255.0f;
|
const float MAX_COLOR = 255.0f;
|
||||||
glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
||||||
|
@ -291,6 +297,25 @@ void Circle3DOverlay::setProperties(const QScriptValue &properties) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin,
|
||||||
|
const glm::vec3& direction, float& distance, BoxFace& face) const {
|
||||||
|
|
||||||
|
bool intersects = Planar3DOverlay::findRayIntersection(origin, direction, distance, face);
|
||||||
|
if (intersects) {
|
||||||
|
glm::vec3 hitAt = origin + (direction * distance);
|
||||||
|
float distanceToHit = glm::distance(hitAt, _position);
|
||||||
|
|
||||||
|
float maxDimension = glm::max(_dimensions.x, _dimensions.y);
|
||||||
|
float innerRadius = maxDimension * getInnerRadius();
|
||||||
|
float outerRadius = maxDimension * getOuterRadius();
|
||||||
|
|
||||||
|
// TODO: this really only works for circles, we should be handling the ellipse case as well...
|
||||||
|
if (distanceToHit < innerRadius || distanceToHit > outerRadius) {
|
||||||
|
intersects = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return intersects;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,8 @@ public:
|
||||||
void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = value; }
|
void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = value; }
|
||||||
void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; }
|
void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; }
|
||||||
|
|
||||||
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float _startAt;
|
float _startAt;
|
||||||
float _endAt;
|
float _endAt;
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
|
#include <PlaneShape.h>
|
||||||
|
#include <RayIntersectionInfo.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <StreamUtils.h>
|
#include <StreamUtils.h>
|
||||||
|
|
||||||
|
@ -74,3 +76,29 @@ void Planar3DOverlay::setProperties(const QScriptValue& properties) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
|
float& distance, BoxFace& face) const {
|
||||||
|
|
||||||
|
RayIntersectionInfo rayInfo;
|
||||||
|
rayInfo._rayStart = origin;
|
||||||
|
rayInfo._rayDirection = direction;
|
||||||
|
rayInfo._rayLength = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
|
PlaneShape plane;
|
||||||
|
|
||||||
|
const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f);
|
||||||
|
glm::vec3 normal = _rotation * UNROTATED_NORMAL;
|
||||||
|
plane.setNormal(normal);
|
||||||
|
plane.setPoint(_position); // the position is definitely a point on our plane
|
||||||
|
|
||||||
|
bool intersects = plane.findRayIntersection(rayInfo);
|
||||||
|
|
||||||
|
if (intersects) {
|
||||||
|
distance = rayInfo._hitDistance;
|
||||||
|
// TODO: if it intersects, we want to check to see if the intersection point is within our dimensions
|
||||||
|
// glm::vec3 hitAt = origin + direction * distance;
|
||||||
|
// _dimensions
|
||||||
|
}
|
||||||
|
return intersects;
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ public:
|
||||||
|
|
||||||
virtual void setProperties(const QScriptValue& properties);
|
virtual void setProperties(const QScriptValue& properties);
|
||||||
|
|
||||||
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
glm::vec2 _dimensions;
|
glm::vec2 _dimensions;
|
||||||
};
|
};
|
||||||
|
|
|
@ -174,6 +174,16 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
|
||||||
sittingPoints.setProperty("length", _sittingPoints.size());
|
sittingPoints.setProperty("length", _sittingPoints.size());
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable
|
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;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,3 +653,20 @@ AACube EntityItemProperties::getMaximumAACubeInMeters() const {
|
||||||
|
|
||||||
return AACube(minimumCorner, diameter);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ public:
|
||||||
|
|
||||||
AACube getMaximumAACubeInTreeUnits() const;
|
AACube getMaximumAACubeInTreeUnits() const;
|
||||||
AACube getMaximumAACubeInMeters() const;
|
AACube getMaximumAACubeInMeters() const;
|
||||||
|
AABox getAABoxInMeters() const;
|
||||||
|
|
||||||
void debugDump() const;
|
void debugDump() const;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "Vec3.h"
|
#include "Vec3.h"
|
||||||
|
@ -48,6 +50,10 @@ float Vec3::distance(const glm::vec3& v1, const glm::vec3& v2) {
|
||||||
return glm::distance(v1, v2);
|
return glm::distance(v1, v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Vec3::orientedAngle(const glm::vec3& v1, const glm::vec3& v2, const glm::vec3& v3) {
|
||||||
|
return glm::degrees(glm::orientedAngle(glm::normalize(v1), glm::normalize(v2), glm::normalize(v3)));
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 Vec3::normalize(const glm::vec3& v) {
|
glm::vec3 Vec3::normalize(const glm::vec3& v) {
|
||||||
return glm::normalize(v);
|
return glm::normalize(v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ public slots:
|
||||||
glm::vec3 subtract(const glm::vec3& v1, const glm::vec3& v2);
|
glm::vec3 subtract(const glm::vec3& v1, const glm::vec3& v2);
|
||||||
float length(const glm::vec3& v);
|
float length(const glm::vec3& v);
|
||||||
float distance(const glm::vec3& v1, const glm::vec3& v2);
|
float distance(const glm::vec3& v1, const glm::vec3& v2);
|
||||||
|
float orientedAngle(const glm::vec3& v1, const glm::vec3& v2, const glm::vec3& v3);
|
||||||
glm::vec3 normalize(const glm::vec3& v);
|
glm::vec3 normalize(const glm::vec3& v);
|
||||||
void print(const QString& lable, const glm::vec3& v);
|
void print(const QString& lable, const glm::vec3& v);
|
||||||
bool equal(const glm::vec3& v1, const glm::vec3& v2);
|
bool equal(const glm::vec3& v1, const glm::vec3& v2);
|
||||||
|
|
Loading…
Reference in a new issue