Merge branch 'master' of https://github.com/highfidelity/hifi into orange

This commit is contained in:
Sam Gateau 2015-04-06 09:56:16 -07:00
commit d6f74aa0ad
12 changed files with 546 additions and 155 deletions

View file

@ -330,6 +330,8 @@
elLightSections[i].style.display = 'block';
}
elLightSpotLight.checked = properties.isSpotlight;
elLightColorRed.value = properties.color.red;
elLightColorGreen.value = properties.color.green;
elLightColorBlue.value = properties.color.blue;

View file

@ -301,6 +301,8 @@ SelectionDisplay = (function () {
var grabberSolid = true;
var grabberMoveUpPosition = { x: 0, y: 0, z: 0 };
var lightOverlayColor = { red: 255, green: 153, blue: 0 };
var grabberPropertiesCorner = {
position: { x:0, y: 0, z: 0},
size: grabberSizeCorner,
@ -340,6 +342,11 @@ SelectionDisplay = (function () {
borderSize: 1.4,
};
var spotLightLineProperties = {
color: lightOverlayColor,
lineWidth: 1.5,
};
var highlightBox = Overlays.addOverlay("cube", {
position: { x:0, y: 0, z: 0},
size: 1,
@ -434,6 +441,44 @@ SelectionDisplay = (function () {
var grabberEdgeFR = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberEdgeFL = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberSpotLightCircle = Overlays.addOverlay("circle3d", {
color: lightOverlayColor,
isSolid: false
});
var grabberSpotLightLineT = Overlays.addOverlay("line3d", spotLightLineProperties);
var grabberSpotLightLineB = Overlays.addOverlay("line3d", spotLightLineProperties);
var grabberSpotLightLineL = Overlays.addOverlay("line3d", spotLightLineProperties);
var grabberSpotLightLineR = Overlays.addOverlay("line3d", spotLightLineProperties);
var grabberSpotLightCenter = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberSpotLightRadius = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberSpotLightL = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberSpotLightR = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberSpotLightT = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberSpotLightB = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberPointLightCircleX = Overlays.addOverlay("circle3d", {
rotation: Quat.fromPitchYawRollDegrees(0, 90, 0),
color: lightOverlayColor,
isSolid: false
});
var grabberPointLightCircleY = Overlays.addOverlay("circle3d", {
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
color: lightOverlayColor,
isSolid: false
});
var grabberPointLightCircleZ = Overlays.addOverlay("circle3d", {
rotation: Quat.fromPitchYawRollDegrees(0, 0, 0),
color: lightOverlayColor,
isSolid: false
});
var grabberPointLightT = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberPointLightB = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberPointLightL = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberPointLightR = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberPointLightF = Overlays.addOverlay("cube", grabberPropertiesEdge);
var grabberPointLightN = Overlays.addOverlay("cube", grabberPropertiesEdge);
var stretchHandles = [
grabberLBN,
grabberRBN,
@ -461,6 +506,25 @@ SelectionDisplay = (function () {
grabberEdgeNL,
grabberEdgeFR,
grabberEdgeFL,
grabberSpotLightLineT,
grabberSpotLightLineB,
grabberSpotLightLineL,
grabberSpotLightLineR,
grabberSpotLightCenter,
grabberSpotLightRadius,
grabberSpotLightL,
grabberSpotLightR,
grabberSpotLightT,
grabberSpotLightB,
grabberPointLightT,
grabberPointLightB,
grabberPointLightL,
grabberPointLightR,
grabberPointLightF,
grabberPointLightN,
];
@ -648,6 +712,10 @@ SelectionDisplay = (function () {
yRailOverlay,
zRailOverlay,
baseOfEntityProjectionOverlay,
grabberSpotLightCircle,
grabberPointLightCircleX,
grabberPointLightCircleY,
grabberPointLightCircleZ,
].concat(stretchHandles);
overlayNames[highlightBox] = "highlightBox";
@ -942,13 +1010,20 @@ SelectionDisplay = (function () {
var translateHandlesVisible = true;
var stretchHandlesVisible = true;
var selectionBoxVisible = true;
var isPointLight = false;
if (selectionManager.selections.length == 1) {
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
isPointLight = properties.type == "Light" && !properties.isSpotlight;
}
if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL" || mode == "TRANSLATE_X in case they Z") {
rotationOverlaysVisible = true;
rotateHandlesVisible = false;
translateHandlesVisible = false;
stretchHandlesVisible = false;
selectionBoxVisible = false;
} else if (mode == "TRANSLATE_UP_DOWN") {
} else if (mode == "TRANSLATE_UP_DOWN" || isPointLight) {
rotateHandlesVisible = false;
stretchHandlesVisible = false;
} else if (mode != "UNKNOWN") {
@ -1122,6 +1197,171 @@ SelectionDisplay = (function () {
var stretchHandlesVisible = spaceMode == SPACE_LOCAL;
var extendedStretchHandlesVisible = stretchHandlesVisible && showExtendedStretchHandles;
if (selectionManager.selections.length == 1 ) {
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
if (properties.type == "Light" && properties.isSpotlight == true) {
var stretchHandlesVisible = false;
var extendedStretchHandlesVisible = false;
Overlays.editOverlay(grabberSpotLightCenter, {
position: position,
visible: false,
});
Overlays.editOverlay(grabberSpotLightRadius, {
position: NEAR,
rotation: rotation,
visible: true,
});
var distance = (properties.dimensions.z / 2) * Math.tan(properties.cutoff * (Math.PI / 180));
Overlays.editOverlay(grabberSpotLightL, {
position: EdgeNL,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberSpotLightR, {
position: EdgeNR,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberSpotLightT, {
position: EdgeTN,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberSpotLightB, {
position: EdgeBN,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberSpotLightCircle, {
position: NEAR,
dimensions: { x: distance * 2, y: distance * 2, z: 1 },
lineWidth: 1.5,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberSpotLightLineT, {
start: position,
end: EdgeTN,
visible: true,
});
Overlays.editOverlay(grabberSpotLightLineB, {
start: position,
end: EdgeBN,
visible: true,
});
Overlays.editOverlay(grabberSpotLightLineR, {
start: position,
end: EdgeNR,
visible: true,
});
Overlays.editOverlay(grabberSpotLightLineL, {
start: position,
end: EdgeNL,
visible: true,
});
Overlays.editOverlay(grabberPointLightCircleX, { visible: false });
Overlays.editOverlay(grabberPointLightCircleY, { visible: false });
Overlays.editOverlay(grabberPointLightCircleZ, { visible: false });
Overlays.editOverlay(grabberPointLightT, { visible: false });
Overlays.editOverlay(grabberPointLightB, { visible: false });
Overlays.editOverlay(grabberPointLightL, { visible: false });
Overlays.editOverlay(grabberPointLightR, { visible: false });
Overlays.editOverlay(grabberPointLightF, { visible: false });
Overlays.editOverlay(grabberPointLightN, { visible: false });
} else if (properties.type == "Light" && properties.isSpotlight == false) {
var stretchHandlesVisible = false;
var extendedStretchHandlesVisible = false;
Overlays.editOverlay(grabberPointLightT, {
position: TOP,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberPointLightB, {
position: BOTTOM,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberPointLightL, {
position: LEFT,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberPointLightR, {
position: RIGHT,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberPointLightF, {
position: FAR,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberPointLightN, {
position: NEAR,
rotation: rotation,
visible: true,
});
Overlays.editOverlay(grabberPointLightCircleX, {
position: position,
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(0, 90, 0)),
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
visible: true,
});
Overlays.editOverlay(grabberPointLightCircleY, {
position: position,
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(90, 0, 0)),
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
visible: true,
});
Overlays.editOverlay(grabberPointLightCircleZ, {
position: position,
rotation: rotation,
dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 },
visible: true,
});
Overlays.editOverlay(grabberSpotLightRadius, { visible: false });
Overlays.editOverlay(grabberSpotLightL, { visible: false });
Overlays.editOverlay(grabberSpotLightR, { visible: false });
Overlays.editOverlay(grabberSpotLightT, { visible: false });
Overlays.editOverlay(grabberSpotLightB, { visible: false });
Overlays.editOverlay(grabberSpotLightCircle, { visible: false });
Overlays.editOverlay(grabberSpotLightLineL, { visible: false });
Overlays.editOverlay(grabberSpotLightLineR, { visible: false });
Overlays.editOverlay(grabberSpotLightLineT, { visible: false });
Overlays.editOverlay(grabberSpotLightLineB, { visible: false });
} else {
Overlays.editOverlay(grabberSpotLightCenter, { visible: false });
Overlays.editOverlay(grabberSpotLightRadius, { visible: false });
Overlays.editOverlay(grabberSpotLightL, { visible: false });
Overlays.editOverlay(grabberSpotLightR, { visible: false });
Overlays.editOverlay(grabberSpotLightT, { visible: false });
Overlays.editOverlay(grabberSpotLightB, { visible: false });
Overlays.editOverlay(grabberSpotLightCircle, { visible: false });
Overlays.editOverlay(grabberSpotLightLineL, { visible: false });
Overlays.editOverlay(grabberSpotLightLineR, { visible: false });
Overlays.editOverlay(grabberSpotLightLineT, { visible: false });
Overlays.editOverlay(grabberSpotLightLineB, { visible: false });
Overlays.editOverlay(grabberPointLightCircleX, { visible: false });
Overlays.editOverlay(grabberPointLightCircleY, { visible: false });
Overlays.editOverlay(grabberPointLightCircleZ, { visible: false });
Overlays.editOverlay(grabberPointLightT, { visible: false });
Overlays.editOverlay(grabberPointLightB, { visible: false });
Overlays.editOverlay(grabberPointLightL, { visible: false });
Overlays.editOverlay(grabberPointLightR, { visible: false });
Overlays.editOverlay(grabberPointLightF, { visible: false });
Overlays.editOverlay(grabberPointLightN, { visible: false });
}
}
Overlays.editOverlay(grabberLBN, { visible: stretchHandlesVisible, rotation: rotation, position: LBN });
Overlays.editOverlay(grabberRBN, { visible: stretchHandlesVisible, rotation: rotation, position: RBN });
Overlays.editOverlay(grabberLBF, { visible: stretchHandlesVisible, rotation: rotation, position: LBF });
@ -1422,7 +1662,7 @@ SelectionDisplay = (function () {
// direction - direction to stretch in
// pivot - point to use as a pivot
// offset - the position of the overlay tool relative to the selections center position
var makeStretchTool = function(stretchMode, direction, pivot, offset) {
var makeStretchTool = function(stretchMode, direction, pivot, offset, customOnMove) {
var signs = {
x: direction.x < 0 ? -1 : (direction.x > 0 ? 1 : 0),
y: direction.y < 0 ? -1 : (direction.y > 0 ? 1 : 0),
@ -1554,7 +1794,7 @@ SelectionDisplay = (function () {
};
var onMove = function(event) {
var proportional = spaceMode == SPACE_WORLD || event.isShifted;
var proportional = spaceMode == SPACE_WORLD || event.isShifted || activeTool.mode == "STRETCH_RADIUS";
var position, dimensions, rotation;
if (spaceMode == SPACE_LOCAL) {
@ -1577,61 +1817,66 @@ SelectionDisplay = (function () {
vector = vec3Mult(mask, vector);
vector = grid.snapToSpacing(vector);
var changeInDimensions = Vec3.multiply(-1, vec3Mult(signs, vector));
var newDimensions;
if (proportional) {
var absX = Math.abs(changeInDimensions.x);
var absY = Math.abs(changeInDimensions.y);
var absZ = Math.abs(changeInDimensions.z);
var pctChange = 0;
if (absX > absY && absX > absZ) {
pctChange = changeInDimensions.x / initialProperties.dimensions.x;
pctChange = changeInDimensions.x / initialDimensions.x;
} else if (absY > absZ) {
pctChange = changeInDimensions.y / initialProperties.dimensions.y;
pctChange = changeInDimensions.y / initialDimensions.y;
} else {
pctChange = changeInDimensions.z / initialProperties.dimensions.z;
pctChange = changeInDimensions.z / initialDimensions.z;
}
pctChange += 1.0;
newDimensions = Vec3.multiply(pctChange, initialDimensions);
if (customOnMove) {
var change = Vec3.multiply(-1, vec3Mult(signs, vector));
customOnMove(vector, change);
} else {
newDimensions = Vec3.sum(initialDimensions, changeInDimensions);
}
newDimensions.x = Math.max(newDimensions.x, MINIMUM_DIMENSION);
newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION);
newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION);
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(deltaPivot, changeInDimensions));
var newPosition = Vec3.sum(initialPosition, changeInPosition);
for (var i = 0; i < SelectionManager.selections.length; i++) {
Entities.editEntity(SelectionManager.selections[i], {
position: newPosition,
dimensions: newDimensions,
});
}
vector = grid.snapToSpacing(vector);
var wantDebug = false;
if (wantDebug) {
print(stretchMode);
Vec3.print(" newIntersection:", newIntersection);
Vec3.print(" vector:", vector);
Vec3.print(" oldPOS:", oldPOS);
Vec3.print(" newPOS:", newPOS);
Vec3.print(" changeInDimensions:", changeInDimensions);
Vec3.print(" newDimensions:", newDimensions);
var changeInDimensions = Vec3.multiply(-1, vec3Mult(signs, vector));
var newDimensions;
if (proportional) {
var absX = Math.abs(changeInDimensions.x);
var absY = Math.abs(changeInDimensions.y);
var absZ = Math.abs(changeInDimensions.z);
var pctChange = 0;
if (absX > absY && absX > absZ) {
pctChange = changeInDimensions.x / initialProperties.dimensions.x;
pctChange = changeInDimensions.x / initialDimensions.x;
} else if (absY > absZ) {
pctChange = changeInDimensions.y / initialProperties.dimensions.y;
pctChange = changeInDimensions.y / initialDimensions.y;
} else {
pctChange = changeInDimensions.z / initialProperties.dimensions.z;
pctChange = changeInDimensions.z / initialDimensions.z;
}
pctChange += 1.0;
newDimensions = Vec3.multiply(pctChange, initialDimensions);
} else {
newDimensions = Vec3.sum(initialDimensions, changeInDimensions);
}
newDimensions.x = Math.max(newDimensions.x, MINIMUM_DIMENSION);
newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION);
newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION);
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(deltaPivot, changeInDimensions));
var newPosition = Vec3.sum(initialPosition, changeInPosition);
for (var i = 0; i < SelectionManager.selections.length; i++) {
Entities.editEntity(SelectionManager.selections[i], {
position: newPosition,
dimensions: newDimensions,
});
}
Vec3.print(" changeInPosition:", changeInPosition);
Vec3.print(" newPosition:", newPosition);
var wantDebug = false;
if (wantDebug) {
print(stretchMode);
Vec3.print(" newIntersection:", newIntersection);
Vec3.print(" vector:", vector);
Vec3.print(" oldPOS:", oldPOS);
Vec3.print(" newPOS:", newPOS);
Vec3.print(" changeInDimensions:", changeInDimensions);
Vec3.print(" newDimensions:", newDimensions);
Vec3.print(" changeInPosition:", changeInPosition);
Vec3.print(" newPosition:", newPosition);
}
SelectionManager._update();
}
SelectionManager._update();
};
return {
@ -1642,15 +1887,57 @@ SelectionDisplay = (function () {
};
};
function addStretchTool(overlay, mode, pivot, direction, offset) {
function addStretchTool(overlay, mode, pivot, direction, offset, handleMove) {
if (!pivot) {
pivot = direction;
}
var tool = makeStretchTool(mode, direction, pivot, offset);
var tool = makeStretchTool(mode, direction, pivot, offset, handleMove);
addGrabberTool(overlay, tool);
}
function cutoffStretchFunc(vector, change) {
vector = change;
Vec3.print("Radius stretch: ", vector);
var length = vector.x + vector.y + vector.z;
var props = selectionManager.savedProperties[selectionManager.selections[0].id];
var radius = props.dimensions.z / 2;
var originalCutoff = props.cutoff;
var originalSize = radius * Math.tan(originalCutoff * (Math.PI / 180));
var newSize = originalSize + length;
var cutoff = Math.atan2(newSize, radius) * 180 / Math.PI;
Entities.editEntity(selectionManager.selections[0], {
cutoff: cutoff,
});
SelectionManager._update();
};
function radiusStretchFunc(vector, change) {
var props = selectionManager.savedProperties[selectionManager.selections[0].id];
// Find the axis being adjusted
var size;
if (Math.abs(change.x) > 0) {
size = props.dimensions.x + change.x;
} else if (Math.abs(change.y) > 0) {
size = props.dimensions.y + change.y;
} else if (Math.abs(change.z) > 0) {
size = props.dimensions.z + change.z;
}
var newDimensions = { x: size, y: size, z: size };
Entities.editEntity(selectionManager.selections[0], {
dimensions: newDimensions,
});
SelectionManager._update();
}
addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 });
addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 });
addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: -1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 });
@ -1658,6 +1945,19 @@ SelectionDisplay = (function () {
addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: -1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 });
addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: 1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 });
addStretchTool(grabberSpotLightRadius, "STRETCH_RADIUS", { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 });
addStretchTool(grabberSpotLightT, "STRETCH_CUTOFF_T", { x: 0, y: 0, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }, cutoffStretchFunc);
addStretchTool(grabberSpotLightB, "STRETCH_CUTOFF_B", { x: 0, y: 0, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }, cutoffStretchFunc);
addStretchTool(grabberSpotLightL, "STRETCH_CUTOFF_L", { x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, cutoffStretchFunc);
addStretchTool(grabberSpotLightR, "STRETCH_CUTOFF_R", { x: 0, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, cutoffStretchFunc);
addStretchTool(grabberPointLightT, "STRETCH_RADIUS_T", { x: 0, y: 0, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 0, z: 1 }, radiusStretchFunc);
addStretchTool(grabberPointLightB, "STRETCH_RADIUS_B", { x: 0, y: 0, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: 0, z: 1 }, radiusStretchFunc);
addStretchTool(grabberPointLightL, "STRETCH_RADIUS_L", { x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: 0, y: 0, z: 1 }, radiusStretchFunc);
addStretchTool(grabberPointLightR, "STRETCH_RADIUS_R", { x: 0, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 0, y: 0, z: 1 }, radiusStretchFunc);
addStretchTool(grabberPointLightF, "STRETCH_RADIUS_F", { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }, radiusStretchFunc);
addStretchTool(grabberPointLightN, "STRETCH_RADIUS_N", { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }, radiusStretchFunc);
addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}, { x: -1, y: -1, z: -1 });
addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}, { x: 1, y: -1, z: -1 });
addStretchTool(grabberLBF, "STRETCH_LBF", null, {x: 1, y: 0, z: -1}, { x: -1, y: -1, z: 1 });
@ -2399,6 +2699,17 @@ SelectionDisplay = (function () {
case grabberEdgeNL:
case grabberEdgeFR:
case grabberEdgeFL:
case grabberSpotLightRadius:
case grabberSpotLightT:
case grabberSpotLightB:
case grabberSpotLightL:
case grabberSpotLightR:
case grabberPointLightT:
case grabberPointLightB:
case grabberPointLightR:
case grabberPointLightL:
case grabberPointLightN:
case grabberPointLightF:
pickedColor = grabberColorEdge;
pickedAlpha = grabberAlpha;
highlightNeeded = true;

View file

@ -976,6 +976,11 @@ void Application::keyPressEvent(QKeyEvent* event) {
_myAvatar->setDriveKeys(UP, 1.0f);
break;
case Qt::Key_F: {
_physicsEngine.dumpNextStats();
break;
}
case Qt::Key_Asterisk:
Menu::getInstance()->triggerOption(MenuOption::Stars);
break;
@ -1183,6 +1188,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_Comma: {
renderCollisionHulls = !renderCollisionHulls;
break;
}
default:

View file

@ -31,6 +31,10 @@ class Text3DOverlay;
#define OVR_CLIENT_DISTORTION 1
// Direct HMD mode is currently only supported on windows and some linux systems will
// misbehave if we try to enable the Oculus SDK at all, so isolate support for Direct
// mode only to windows for now
#ifdef Q_OS_WIN
// On Win32 platforms, enabling Direct HMD requires that the SDK be
// initialized before the GL context is set up, but this breaks v-sync
// for any application that has a Direct mode enable Rift connected
@ -40,6 +44,7 @@ class Text3DOverlay;
// caveat that it will break v-sync in NON-VR mode if you have an Oculus
// Rift connect and in Direct mode
#define OVR_DIRECT_MODE 1
#endif
/// Handles interaction with the Oculus Rift.

View file

@ -98,6 +98,9 @@ void Circle3DOverlay::render(RenderArgs* args) {
const float MAX_COLOR = 255.0f;
glm::vec4 color(colorX.red / MAX_COLOR, colorX.green / MAX_COLOR, colorX.blue / MAX_COLOR, alpha);
bool colorChanged = colorX.red != _lastColor.red || colorX.green != _lastColor.green || colorX.blue != _lastColor.blue;
_lastColor = colorX;
glDisable(GL_LIGHTING);
glm::vec3 position = getPosition();
@ -131,7 +134,7 @@ void Circle3DOverlay::render(RenderArgs* args) {
_quadVerticesID = geometryCache->allocateID();
}
if (geometryChanged) {
if (geometryChanged || colorChanged) {
QVector<glm::vec2> points;
@ -170,7 +173,7 @@ void Circle3DOverlay::render(RenderArgs* args) {
_lineVerticesID = geometryCache->allocateID();
}
if (geometryChanged) {
if (geometryChanged || colorChanged) {
QVector<glm::vec2> points;
float angle = startAt;

View file

@ -70,6 +70,7 @@ protected:
int _majorTicksVerticesID;
int _minorTicksVerticesID;
xColor _lastColor;
float _lastStartAt;
float _lastEndAt;
float _lastOuterRadius;

View file

@ -41,8 +41,16 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityI
}
void LightEntityItem::setDimensions(const glm::vec3& value) {
float maxDimension = glm::max(value.x, value.y, value.z);
_dimensions = glm::vec3(maxDimension, maxDimension, maxDimension);
if (_isSpotlight) {
// If we are a spotlight, treat the z value as our radius or length, and
// recalculate the x/y dimensions to properly encapsulate the spotlight.
const float length = value.z;
const float width = length * glm::tan(glm::radians(_cutoff));
_dimensions = glm::vec3(width, width, length);
} else {
float maxDimension = glm::max(value.x, value.y, value.z);
_dimensions = glm::vec3(maxDimension, maxDimension, maxDimension);
}
}
@ -58,6 +66,33 @@ EntityItemProperties LightEntityItem::getProperties() const {
return properties;
}
void LightEntityItem::setIsSpotlight(bool value) {
if (value != _isSpotlight) {
_isSpotlight = value;
if (_isSpotlight) {
const float length = _dimensions.z;
const float width = length * glm::tan(glm::radians(_cutoff));
_dimensions = glm::vec3(width, width, length);
} else {
float maxDimension = glm::max(_dimensions.x, _dimensions.y, _dimensions.z);
_dimensions = glm::vec3(maxDimension, maxDimension, maxDimension);
}
}
}
void LightEntityItem::setCutoff(float value) {
_cutoff = glm::clamp(value, 0.0f, 90.0f);
if (_isSpotlight) {
// If we are a spotlight, adjusting the cutoff will affect the area we encapsulate,
// so update the dimensions to reflect this.
const float length = _dimensions.z;
const float width = length * glm::tan(glm::radians(_cutoff));
_dimensions = glm::vec3(width, width, length);
}
}
bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class

View file

@ -56,7 +56,7 @@ public:
}
bool getIsSpotlight() const { return _isSpotlight; }
void setIsSpotlight(bool value) { _isSpotlight = value; }
void setIsSpotlight(bool value);
float getIntensity() const { return _intensity; }
void setIntensity(float value) { _intensity = value; }
@ -65,7 +65,7 @@ public:
void setExponent(float value) { _exponent = value; }
float getCutoff() const { return _cutoff; }
void setCutoff(float value) { _cutoff = value; }
void setCutoff(float value);
static bool getLightsArePickable() { return _lightsArePickable; }
static void setLightsArePickable(bool value) { _lightsArePickable = value; }

View file

@ -257,6 +257,7 @@ btPairCachingGhostObject* CharacterController::getGhostObject() {
}
bool CharacterController::recoverFromPenetration(btCollisionWorld* collisionWorld) {
BT_PROFILE("recoverFromPenetration");
// Here we must refresh the overlapping paircache as the penetrating movement itself or the
// previous recovery iteration might have used setWorldTransform and pushed us into an object
// that is not in the previous cache contents from the last timestep, as will happen if we
@ -355,6 +356,7 @@ bool CharacterController::recoverFromPenetration(btCollisionWorld* collisionWorl
void CharacterController::scanDown(btCollisionWorld* world) {
BT_PROFILE("scanDown");
// we test with downward raycast and if we don't find floor close enough then turn on "hover"
btKinematicClosestNotMeRayResultCallback callback(_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
@ -374,6 +376,7 @@ void CharacterController::scanDown(btCollisionWorld* world) {
}
void CharacterController::stepUp(btCollisionWorld* world) {
BT_PROFILE("stepUp");
// phase 1: up
// compute start and end
@ -440,6 +443,7 @@ void CharacterController::updateTargetPositionBasedOnCollision(const btVector3&
}
void CharacterController::stepForward(btCollisionWorld* collisionWorld, const btVector3& movement) {
BT_PROFILE("stepForward");
// phase 2: forward
_targetPosition = _currentPosition + movement;
@ -496,6 +500,7 @@ void CharacterController::stepForward(btCollisionWorld* collisionWorld, const bt
}
void CharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt) {
BT_PROFILE("stepDown");
// phase 3: down
//
// The "stepDown" phase first makes a normal sweep down that cancels the lift from the "stepUp" phase.
@ -607,6 +612,7 @@ void CharacterController::warp(const btVector3& origin) {
void CharacterController::preStep(btCollisionWorld* collisionWorld) {
BT_PROFILE("preStep");
if (!_enabled) {
return;
}
@ -627,6 +633,7 @@ void CharacterController::preStep(btCollisionWorld* collisionWorld) {
}
void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar dt) {
BT_PROFILE("playerStep");
if (!_enabled) {
return; // no motion
}
@ -875,6 +882,7 @@ void CharacterController::updateShapeIfNecessary() {
}
void CharacterController::preSimulation(btScalar timeStep) {
BT_PROFILE("preSimulation");
if (_enabled && _dynamicsWorld) {
glm::quat rotation = _avatarData->getOrientation();
_currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS);
@ -897,6 +905,7 @@ void CharacterController::preSimulation(btScalar timeStep) {
}
void CharacterController::postSimulation() {
BT_PROFILE("postSimulation");
if (_enabled && _ghostObject) {
const btTransform& avatarTransform = _ghostObject->getWorldTransform();
glm::quat rotation = bulletToGLM(avatarTransform.getRotation());

View file

@ -155,6 +155,7 @@ void PhysicsEngine::clearEntitiesInternal() {
// end EntitySimulation overrides
void PhysicsEngine::relayIncomingChangesToSimulation() {
BT_PROFILE("incomingChanges");
// process incoming changes
QSet<ObjectMotionState*>::iterator stateItr = _incomingChanges.begin();
while (stateItr != _incomingChanges.end()) {
@ -287,66 +288,76 @@ void PhysicsEngine::init(EntityEditPacketSender* packetSender) {
}
void PhysicsEngine::stepSimulation() {
lock();
// NOTE: the grand order of operations is:
// (1) pull incoming changes
// (2) step simulation
// (3) synchronize outgoing motion states
// (4) send outgoing packets
// This is step (1) pull incoming changes
relayIncomingChangesToSimulation();
const int MAX_NUM_SUBSTEPS = 4;
const float MAX_TIMESTEP = (float)MAX_NUM_SUBSTEPS * PHYSICS_ENGINE_FIXED_SUBSTEP;
float dt = 1.0e-6f * (float)(_clock.getTimeMicroseconds());
_clock.reset();
float timeStep = btMin(dt, MAX_TIMESTEP);
// TODO: move character->preSimulation() into relayIncomingChanges
if (_characterController) {
if (_characterController->needsRemoval()) {
_characterController->setDynamicsWorld(NULL);
}
_characterController->updateShapeIfNecessary();
if (_characterController->needsAddition()) {
_characterController->setDynamicsWorld(_dynamicsWorld);
}
_characterController->preSimulation(timeStep);
}
// This is step (2) step simulation
int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP);
_numSubsteps += (uint32_t)numSubsteps;
stepNonPhysicalKinematics(usecTimestampNow());
unlock();
// TODO: make all of this harvest stuff into one function: relayOutgoingChanges()
if (numSubsteps > 0) {
// This is step (3) which is done outside of stepSimulation() so we can lock _entityTree.
//
// Unfortunately we have to unlock the simulation (above) before we try to lock the _entityTree
// to avoid deadlock -- the _entityTree may try to lock its EntitySimulation (from which this
// PhysicsEngine derives) when updating/adding/deleting entities so we need to wait for our own
// lock on the tree before we re-lock ourselves.
//
// TODO: untangle these lock sequences.
_entityTree->lockForWrite();
{
lock();
_dynamicsWorld->synchronizeMotionStates();
CProfileManager::Reset();
BT_PROFILE("stepSimulation");
// NOTE: the grand order of operations is:
// (1) pull incoming changes
// (2) step simulation
// (3) synchronize outgoing motion states
// (4) send outgoing packets
if (_characterController) {
_characterController->postSimulation();
}
unlock();
_entityTree->unlock();
// This is step (1) pull incoming changes
relayIncomingChangesToSimulation();
computeCollisionEvents();
const int MAX_NUM_SUBSTEPS = 4;
const float MAX_TIMESTEP = (float)MAX_NUM_SUBSTEPS * PHYSICS_ENGINE_FIXED_SUBSTEP;
float dt = 1.0e-6f * (float)(_clock.getTimeMicroseconds());
_clock.reset();
float timeStep = btMin(dt, MAX_TIMESTEP);
// TODO: move character->preSimulation() into relayIncomingChanges
if (_characterController) {
if (_characterController->needsRemoval()) {
_characterController->setDynamicsWorld(NULL);
}
_characterController->updateShapeIfNecessary();
if (_characterController->needsAddition()) {
_characterController->setDynamicsWorld(_dynamicsWorld);
}
_characterController->preSimulation(timeStep);
}
// This is step (2) step simulation
int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP);
_numSubsteps += (uint32_t)numSubsteps;
stepNonPhysicalKinematics(usecTimestampNow());
unlock();
// TODO: make all of this harvest stuff into one function: relayOutgoingChanges()
if (numSubsteps > 0) {
BT_PROFILE("postSimulation");
// This is step (3) which is done outside of stepSimulation() so we can lock _entityTree.
//
// Unfortunately we have to unlock the simulation (above) before we try to lock the _entityTree
// to avoid deadlock -- the _entityTree may try to lock its EntitySimulation (from which this
// PhysicsEngine derives) when updating/adding/deleting entities so we need to wait for our own
// lock on the tree before we re-lock ourselves.
//
// TODO: untangle these lock sequences.
_entityTree->lockForWrite();
lock();
_dynamicsWorld->synchronizeMotionStates();
if (_characterController) {
_characterController->postSimulation();
}
unlock();
_entityTree->unlock();
computeCollisionEvents();
}
}
if (_dumpNextStats) {
_dumpNextStats = false;
CProfileManager::dumpAll();
}
}
void PhysicsEngine::stepNonPhysicalKinematics(const quint64& now) {
BT_PROFILE("nonPhysicalKinematics");
QSet<ObjectMotionState*>::iterator stateItr = _nonPhysicalKinematicObjects.begin();
while (stateItr != _nonPhysicalKinematicObjects.end()) {
ObjectMotionState* motionState = *stateItr;
@ -358,6 +369,7 @@ void PhysicsEngine::stepNonPhysicalKinematics(const quint64& now) {
// TODO?: need to occasionally scan for stopped non-physical kinematics objects
void PhysicsEngine::computeCollisionEvents() {
BT_PROFILE("computeCollisionEvents");
// update all contacts every frame
int numManifolds = _collisionDispatcher->getNumManifolds();
for (int i = 0; i < numManifolds; ++i) {

View file

@ -86,6 +86,8 @@ public:
void setCharacterController(CharacterController* character);
void dumpNextStats() { _dumpNextStats = true; }
private:
/// \param motionState pointer to Object's MotionState
void removeObjectFromBullet(ObjectMotionState* motionState);
@ -121,6 +123,8 @@ private:
/// character collisions
CharacterController* _characterController = NULL;
bool _dumpNextStats = false;
};
#endif // hifi_PhysicsEngine_h

View file

@ -15,6 +15,8 @@
* Copied and modified from btDiscreteDynamicsWorld.cpp by AndrewMeadows on 2014.11.12.
* */
#include <LinearMath/btQuickprof.h>
#include "ThreadSafeDynamicsWorld.h"
ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld(
@ -25,50 +27,51 @@ ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld(
: btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration) {
}
int ThreadSafeDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep) {
int subSteps = 0;
if (maxSubSteps) {
//fixed timestep with interpolation
m_fixedTimeStep = fixedTimeStep;
m_localTime += timeStep;
if (m_localTime >= fixedTimeStep)
{
subSteps = int( m_localTime / fixedTimeStep);
m_localTime -= subSteps * fixedTimeStep;
}
} else {
//variable timestep
fixedTimeStep = timeStep;
m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
m_fixedTimeStep = 0;
if (btFuzzyZero(timeStep))
{
subSteps = 0;
maxSubSteps = 0;
} else
{
subSteps = 1;
maxSubSteps = 1;
}
}
int ThreadSafeDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep) {
BT_PROFILE("stepSimulation");
int subSteps = 0;
if (maxSubSteps) {
//fixed timestep with interpolation
m_fixedTimeStep = fixedTimeStep;
m_localTime += timeStep;
if (m_localTime >= fixedTimeStep)
{
subSteps = int( m_localTime / fixedTimeStep);
m_localTime -= subSteps * fixedTimeStep;
}
} else {
//variable timestep
fixedTimeStep = timeStep;
m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
m_fixedTimeStep = 0;
if (btFuzzyZero(timeStep))
{
subSteps = 0;
maxSubSteps = 0;
} else
{
subSteps = 1;
maxSubSteps = 1;
}
}
/*//process some debugging flags
if (getDebugDrawer()) {
btIDebugDraw* debugDrawer = getDebugDrawer ();
gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
}*/
if (subSteps) {
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
int clampedSimulationSteps = (subSteps > maxSubSteps)? maxSubSteps : subSteps;
/*//process some debugging flags
if (getDebugDrawer()) {
btIDebugDraw* debugDrawer = getDebugDrawer ();
gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
}*/
if (subSteps) {
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
int clampedSimulationSteps = (subSteps > maxSubSteps)? maxSubSteps : subSteps;
saveKinematicState(fixedTimeStep*clampedSimulationSteps);
saveKinematicState(fixedTimeStep*clampedSimulationSteps);
applyGravity();
applyGravity();
for (int i=0;i<clampedSimulationSteps;i++) {
internalSingleStepSimulation(fixedTimeStep);
}
}
for (int i=0;i<clampedSimulationSteps;i++) {
internalSingleStepSimulation(fixedTimeStep);
}
}
// NOTE: We do NOT call synchronizeMotionState() after each substep (to avoid multiple locks on the
// object data outside of the physics engine). A consequence of this is that the transforms of the
@ -77,7 +80,7 @@ int ThreadSafeDynamicsWorld::stepSimulation( btScalar timeStep, int maxSubSteps,
// NOTE: We do NOT call synchronizeMotionStates() here. Instead it is called by an external class
// that knows how to lock threads correctly.
clearForces();
clearForces();
return subSteps;
}