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

This commit is contained in:
Stephen Birarda 2014-10-10 09:28:14 -07:00
commit 76d00f351d
24 changed files with 1216 additions and 165 deletions

View file

@ -244,7 +244,7 @@ EntityPropertyDialogBox = (function () {
properties.color.blue = array[index++].value;
}
Entities.editEntity(editModelID, properties);
selectionDisplay.highlightSelectable(editModelID, propeties);
selectionDisplay.select(editModelID, false);
}
modelSelected = false;
});

View file

@ -31,10 +31,33 @@ SelectionDisplay = (function () {
var handleHoverColor = { red: 224, green: 67, blue: 36 };
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 rotateHandleAlpha = 0.7;
var grabberSizeCorner = 0.025;
var grabberSizeEdge = 0.015;
var grabberSizeFace = 0.025;
@ -151,7 +174,8 @@ SelectionDisplay = (function () {
alpha: 0.5,
solid: true,
visible: false,
rotation: baseOverlayRotation
rotation: baseOverlayRotation,
ignoreRayIntersection: true, // always ignore this
});
var yawOverlayAngles = { x: 90, y: 0, z: 0 };
@ -161,6 +185,34 @@ SelectionDisplay = (function () {
var rollOverlayAngles = { x: 0, y: 180, z: 0 };
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", {
position: { x:0, y: 0, z: 0},
@ -171,12 +223,13 @@ SelectionDisplay = (function () {
visible: false,
rotation: yawOverlayRotation,
hasTickMarks: true,
majorTickMarksAngle: 12.5,
majorTickMarksAngle: innerSnapAngle,
minorTickMarksAngle: 0,
majorTickMarksLength: -0.25,
minorTickMarksLength: 0,
majorTickMarksColor: { red: 0, green: 0, blue: 0 },
minorTickMarksColor: { red: 0, green: 0, blue: 0 },
ignoreRayIntersection: true, // always ignore this
});
var rotateOverlayOuter = Overlays.addOverlay("circle3d", {
@ -195,6 +248,7 @@ SelectionDisplay = (function () {
minorTickMarksLength: 0.1,
majorTickMarksColor: { red: 0, green: 0, blue: 0 },
minorTickMarksColor: { red: 0, green: 0, blue: 0 },
ignoreRayIntersection: true, // always ignore this
});
var rotateOverlayCurrent = Overlays.addOverlay("circle3d", {
@ -205,10 +259,11 @@ SelectionDisplay = (function () {
solid: true,
visible: false,
rotation: yawOverlayRotation,
ignoreRayIntersection: true, // always ignore this
});
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},
color: rotateHandleColor,
alpha: rotateHandleAlpha,
@ -220,7 +275,7 @@ SelectionDisplay = (function () {
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},
color: rotateHandleColor,
alpha: rotateHandleAlpha,
@ -232,7 +287,7 @@ SelectionDisplay = (function () {
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},
color: rotateHandleColor,
alpha: rotateHandleAlpha,
@ -279,11 +334,14 @@ SelectionDisplay = (function () {
overlayNames[pitchHandle] = "pitchHandle";
overlayNames[rollHandle] = "rollHandle";
overlayNames[rotateOverlayTarget] = "rotateOverlayTarget";
overlayNames[rotateOverlayInner] = "rotateOverlayInner";
overlayNames[rotateOverlayOuter] = "rotateOverlayOuter";
overlayNames[rotateOverlayCurrent] = "rotateOverlayCurrent";
overlayNames[rotateZeroOverlay] = "rotateZeroOverlay";
overlayNames[rotateCurrentOverlay] = "rotateCurrentOverlay";
that.cleanup = function () {
Overlays.deleteOverlay(highlightBox);
Overlays.deleteOverlay(selectionBox);
@ -322,10 +380,15 @@ SelectionDisplay = (function () {
Overlays.deleteOverlay(pitchHandle);
Overlays.deleteOverlay(rollHandle);
Overlays.deleteOverlay(rotateOverlayTarget);
Overlays.deleteOverlay(rotateOverlayInner);
Overlays.deleteOverlay(rotateOverlayOuter);
Overlays.deleteOverlay(rotateOverlayCurrent);
Overlays.deleteOverlay(rotateZeroOverlay);
Overlays.deleteOverlay(rotateCurrentOverlay);
};
that.highlightSelectable = function(entityID) {
@ -377,8 +440,8 @@ SelectionDisplay = (function () {
var diagonal = (Vec3.length(properties.dimensions) / 2) * 1.1;
var halfDimensions = Vec3.multiply(properties.dimensions, 0.5);
var innerRadius = diagonal;
var outerRadius = diagonal * 1.15;
innerRadius = diagonal;
outerRadius = diagonal * 1.15;
var innerActive = false;
var innerAlpha = 0.2;
var outerAlpha = 0.2;
@ -412,10 +475,6 @@ SelectionDisplay = (function () {
var pitchCorner;
var rollCorner;
var yawHandleRotation;
var pitchHandleRotation;
var rollHandleRotation;
// determine which bottom corner we are closest to
/*------------------------------
example:
@ -432,27 +491,45 @@ SelectionDisplay = (function () {
if (MyAvatar.position.x > center.x) {
// must be BRF or BRN
if (MyAvatar.position.z < center.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 });
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: right + rotateHandleOffset,
y: bottom - rotateHandleOffset,
z: near - rotateHandleOffset };
pitchCorner = { x: right + rotateHandleOffset,
y: top + rotateHandleOffset,
z: far + rotateHandleOffset };
rollCorner = { x: left - rotateHandleOffset,
pitchCorner = { x: left - rotateHandleOffset,
y: top + rotateHandleOffset,
z: near - rotateHandleOffset};
rollCorner = { x: right + rotateHandleOffset,
y: top + rotateHandleOffset,
z: far + rotateHandleOffset };
yawCenter = { x: center.x, y: bottom, z: center.z };
pitchCenter = { x: left, y: center.y, z: center.z};
rollCenter = { x: center.x, y: center.y, z: far };
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 {
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 });
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 90 });
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,
z: far + rotateHandleOffset };
@ -465,14 +542,25 @@ SelectionDisplay = (function () {
y: top + rotateHandleOffset,
z: near - rotateHandleOffset};
yawCenter = { x: center.x, y: bottom, z: center.z };
pitchCenter = { x: left, y: center.y, z: center.z };
rollCenter = { x: center.x, y: center.y, z: near};
Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
}
} else {
// must be BLF or BLN
if (MyAvatar.position.z < center.z) {
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 });
rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 });
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,
z: near - rotateHandleOffset };
@ -485,68 +573,106 @@ SelectionDisplay = (function () {
y: top + rotateHandleOffset,
z: far + rotateHandleOffset};
yawCenter = { x: center.x, y: bottom, z: center.z };
pitchCenter = { x: right, y: center.y, z: center.z };
rollCenter = { x: center.x, y: center.y, z: far};
Overlays.editOverlay(pitchHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
Overlays.editOverlay(rollHandle, { url: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/rotate-arrow-west-north.png" });
} else {
yawHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 180, z: 0 });
pitchHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 });
rollHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 });
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: left - rotateHandleOffset,
y: bottom - rotateHandleOffset,
z: far + rotateHandleOffset };
pitchCorner = { x: left - rotateHandleOffset,
rollCorner = { x: left - rotateHandleOffset,
y: top + rotateHandleOffset,
z: near - rotateHandleOffset };
rollCorner = { x: right + rotateHandleOffset,
pitchCorner = { x: right + rotateHandleOffset,
y: top + rotateHandleOffset,
z: far + rotateHandleOffset};
yawCenter = { x: center.x, y: bottom, z: center.z };
rollCenter = { x: center.x, y: center.y, z: near };
pitchCenter = { x: right, y: center.y, z: center.z};
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 });
print("selectionBoxVisible:" + selectionBoxVisible);
Overlays.editOverlay(selectionBox,
{
visible: true,
visible: selectionBoxVisible,
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: center.x, y: top + grabberMoveUpOffset, z: center.z } });
Overlays.editOverlay(grabberLBN, { visible: true, position: { x: left, y: bottom, z: near } });
Overlays.editOverlay(grabberRBN, { visible: true, position: { x: right, y: bottom, z: near } });
Overlays.editOverlay(grabberLBF, { visible: true, position: { x: left, y: bottom, z: far } });
Overlays.editOverlay(grabberRBF, { visible: true, position: { x: right, y: bottom, z: far } });
Overlays.editOverlay(grabberLTN, { visible: true, position: { x: left, y: top, z: near } });
Overlays.editOverlay(grabberRTN, { visible: true, position: { x: right, y: top, z: near } });
Overlays.editOverlay(grabberLTF, { visible: true, position: { x: left, y: top, z: far } });
Overlays.editOverlay(grabberRTF, { visible: true, position: { x: right, y: top, z: far } });
Overlays.editOverlay(grabberLBN, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: near } });
Overlays.editOverlay(grabberRBN, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: near } });
Overlays.editOverlay(grabberLBF, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: far } });
Overlays.editOverlay(grabberRBF, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: far } });
Overlays.editOverlay(grabberLTN, { visible: stretchHandlesVisible, position: { x: left, y: top, z: near } });
Overlays.editOverlay(grabberRTN, { visible: stretchHandlesVisible, position: { x: right, y: top, z: near } });
Overlays.editOverlay(grabberLTF, { visible: stretchHandlesVisible, position: { x: left, 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(grabberBOTTOM, { visible: true, position: { x: center.x, y: bottom, z: center.z } });
Overlays.editOverlay(grabberLEFT, { visible: true, position: { x: left, y: center.y, z: center.z } });
Overlays.editOverlay(grabberRIGHT, { visible: true, position: { x: right, y: center.y, z: center.z } });
Overlays.editOverlay(grabberNEAR, { visible: true, position: { x: center.x, y: center.y, z: near } });
Overlays.editOverlay(grabberFAR, { visible: true, position: { x: center.x, y: center.y, z: far } });
Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: center.z } });
Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: center.z } });
Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: center.z } });
Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: center.z } });
Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, position: { x: center.x, y: center.y, z: near } });
Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, position: { x: center.x, y: center.y, z: far } });
Overlays.editOverlay(grabberEdgeTR, { visible: true, position: { x: right, y: top, z: center.z } });
Overlays.editOverlay(grabberEdgeTL, { visible: true, position: { x: left, y: top, z: center.z } });
Overlays.editOverlay(grabberEdgeTF, { visible: true, position: { x: center.x, y: top, z: far } });
Overlays.editOverlay(grabberEdgeTN, { visible: true, position: { x: center.x, y: top, z: near } });
Overlays.editOverlay(grabberEdgeBR, { visible: true, position: { x: right, y: bottom, z: center.z } });
Overlays.editOverlay(grabberEdgeBL, { visible: true, position: { x: left, y: bottom, z: center.z } });
Overlays.editOverlay(grabberEdgeBF, { visible: true, position: { x: center.x, y: bottom, z: far } });
Overlays.editOverlay(grabberEdgeBN, { visible: true, position: { x: center.x, y: bottom, z: near } });
Overlays.editOverlay(grabberEdgeNR, { visible: true, position: { x: right, y: center.y, z: near } });
Overlays.editOverlay(grabberEdgeNL, { visible: true, position: { x: left, y: center.y, z: near } });
Overlays.editOverlay(grabberEdgeFR, { visible: true, position: { x: right, y: center.y, z: far } });
Overlays.editOverlay(grabberEdgeFL, { visible: true, position: { x: left, y: center.y, z: far } });
Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, position: { x: right, y: top, z: center.z } });
Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, position: { x: left, y: top, z: center.z } });
Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: far } });
Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, position: { x: center.x, y: top, z: near } });
Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: center.z } });
Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: center.z } });
Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: far } });
Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, position: { x: center.x, y: bottom, z: near } });
Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: near } });
Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: near } });
Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, position: { x: right, y: center.y, z: far } });
Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, position: { x: left, y: center.y, z: far } });
Overlays.editOverlay(baseOfEntityProjectionOverlay,
@ -562,14 +688,12 @@ SelectionDisplay = (function () {
rotation: properties.rotation,
});
Overlays.editOverlay(rotateOverlayTarget, { visible: false });
Overlays.editOverlay(rotateOverlayInner,
{
visible: false,
position: { x: properties.position.x,
y: properties.position.y - (properties.dimensions.y / 2),
z: properties.position.z},
size: innerRadius,
innerRadius: 0.9,
alpha: innerAlpha
@ -578,10 +702,6 @@ SelectionDisplay = (function () {
Overlays.editOverlay(rotateOverlayOuter,
{
visible: false,
position: { x: properties.position.x,
y: properties.position.y - (properties.dimensions.y / 2),
z: properties.position.z},
size: outerRadius,
innerRadius: 0.9,
startAt: 0,
@ -592,20 +712,19 @@ SelectionDisplay = (function () {
Overlays.editOverlay(rotateOverlayCurrent,
{
visible: false,
position: { x: properties.position.x,
y: properties.position.y - (properties.dimensions.y / 2),
z: properties.position.z},
size: outerRadius,
startAt: 0,
endAt: 0,
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
Overlays.editOverlay(yawHandle, { visible: false, position: yawCorner, rotation: yawHandleRotation});
Overlays.editOverlay(pitchHandle, { visible: false, position: pitchCorner, rotation: pitchHandleRotation});
Overlays.editOverlay(rollHandle, { visible: false, position: rollCorner, rotation: rollHandleRotation});
Overlays.editOverlay(yawHandle, { visible: rotateHandlesVisible, position: yawCorner, rotation: yawHandleRotation});
Overlays.editOverlay(pitchHandle, { visible: rotateHandlesVisible, position: pitchCorner, rotation: pitchHandleRotation});
Overlays.editOverlay(rollHandle, { visible: rotateHandlesVisible, position: rollCorner, rotation: rollHandleRotation});
Entities.editEntity(entityID, { localRenderAlpha: 0.1 });
};
@ -655,10 +774,14 @@ SelectionDisplay = (function () {
Overlays.editOverlay(pitchHandle, { visible: false });
Overlays.editOverlay(rollHandle, { visible: false });
Overlays.editOverlay(rotateOverlayTarget, { visible: false });
Overlays.editOverlay(rotateOverlayInner, { visible: false });
Overlays.editOverlay(rotateOverlayOuter, { visible: false });
Overlays.editOverlay(rotateOverlayCurrent, { visible: false });
Overlays.editOverlay(rotateZeroOverlay, { visible: false });
Overlays.editOverlay(rotateCurrentOverlay, { visible: false });
Entities.editEntity(entityID, { localRenderAlpha: 1.0 });
currentSelection = { id: -1, isKnownID: false };
@ -1440,7 +1563,185 @@ SelectionDisplay = (function () {
Entities.editEntity(currentSelection, selectedEntityProperties);
tooltip.updateText(selectedEntityProperties);
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() {
if (currentSelection.isKnownID &&
@ -1477,6 +1778,36 @@ SelectionDisplay = (function () {
case grabberMoveUp:
mode = "TRANSLATE_UP_DOWN";
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;
case grabberRBN:
@ -1559,20 +1890,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) {
print("rotate handle case...");
// After testing our stretch handles, then check out rotate handles
Overlays.editOverlay(yawHandle, { ignoreRayIntersection: false });
Overlays.editOverlay(pitchHandle, { ignoreRayIntersection: false });
Overlays.editOverlay(rollHandle, { ignoreRayIntersection: false });
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) {
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:
print("mousePressEvent()...... " + overlayNames[result.overlayID]);
mode = "UNKNOWN";
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) {
@ -1614,6 +2056,15 @@ SelectionDisplay = (function () {
that.mouseMoveEvent = function(event) {
//print("mouseMoveEvent()... mode:" + 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":
that.translateUpDown(event);
break;
@ -1671,14 +2122,34 @@ SelectionDisplay = (function () {
};
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";
// if something is selected, then reset the "original" properties for any potential next click+move operation
if (entitySelected) {
if (showHandles) {
that.select(currentSelection, event);
}
selectedEntityProperties = Entities.getEntityProperties(currentSelection);
selectedEntityPropertiesOriginalPosition = properties.position;
selectedEntityPropertiesOriginalDimensions = properties.dimensions;
}
};
Controller.mousePressEvent.connect(that.mousePressEvent);

View file

@ -570,6 +570,19 @@ function handeMenuEvent(menuItem) {
}
} else if (menuItem == "Edit Properties...") {
// 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") {
modelImporter.paste();
} else if (menuItem == "Export Models") {

View file

@ -41,7 +41,7 @@ configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVe
# grab the implementation and header files from src dirs
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)
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
endforeach(SUBDIR)

View file

@ -600,10 +600,14 @@ void Application::paintGL() {
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
if (!OculusManager::isConnected()) {
// If there isn't an HMD, match exactly to avatar's head
_myCamera.setPosition(_myAvatar->getHead()->getEyePosition());
_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) {
static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f;
@ -659,7 +663,6 @@ void Application::paintGL() {
_viewFrustumOffsetCamera.setRotation(_myCamera.getRotation() * frustumRotation);
_viewFrustumOffsetCamera.initialize(); // force immediate snap to ideal position and orientation
_viewFrustumOffsetCamera.update(1.f/_fps);
whichCamera = &_viewFrustumOffsetCamera;
}

View file

@ -22,13 +22,16 @@
Camera::Camera() :
_needsToInitialize(true),
_mode(CAMERA_MODE_THIRD_PERSON),
_position(0.0f, 0.0f, 0.0f),
_fieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES),
_aspectRatio(16.0f/9.0f),
_nearClip(DEFAULT_NEAR_CLIP), // default
_farClip(DEFAULT_FAR_CLIP), // default
_hmdPosition(),
_hmdRotation(),
_targetPosition(),
_targetRotation(),
_scale(1.0f)
{
}
@ -64,26 +67,6 @@ void Camera::setFarClip(float 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) :
_camera(camera), _viewFrustum(viewFrustum)
{

View file

@ -38,17 +38,23 @@ public:
void setPosition(const glm::vec3& p) { _position = p; }
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 setFieldOfView(float f);
void setAspectRatio(float a);
void setNearClip(float n);
void setFarClip(float f);
void setEyeOffsetPosition(const glm::vec3& p);
void setEyeOffsetOrientation(const glm::quat& o);
void setScale(const float s);
void setEyeOffsetPosition(const glm::vec3& p) { _eyeOffsetPosition = p; }
void setEyeOffsetOrientation(const glm::quat& o) { _eyeOffsetOrientation = o; }
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; }
float getFieldOfView() const { return _fieldOfView; }
float getAspectRatio() const { return _aspectRatio; }
@ -60,7 +66,6 @@ public:
private:
bool _needsToInitialize;
CameraMode _mode;
glm::vec3 _position;
float _fieldOfView; // degrees
@ -70,7 +75,10 @@ private:
glm::vec3 _eyeOffsetPosition;
glm::quat _eyeOffsetOrientation;
glm::quat _rotation;
glm::vec3 _hmdPosition;
glm::quat _hmdRotation;
glm::vec3 _targetPosition;
glm::quat _targetRotation;
float _scale;
};

View file

@ -1151,7 +1151,7 @@ const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {
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);
}

View file

@ -337,15 +337,20 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
#else
ovrEyeType eye = _ovrHmdDesc.EyeRenderOrder[eyeIndex];
#endif
//Set the camera rotation for this eye
// Set the camera rotation for this eye
eyeRenderPose[eye] = ovrHmd_GetEyePose(_ovrHmd, eye);
orientation.x = eyeRenderPose[eye].Orientation.x;
orientation.y = eyeRenderPose[eye].Orientation.y;
orientation.z = eyeRenderPose[eye].Orientation.z;
orientation.w = eyeRenderPose[eye].Orientation.w;
_camera->setRotation(bodyOrientation * orientation);
_camera->setPosition(position + trackerPosition);
// Update the application camera with the latest HMD position
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
glm::vec3 thisEyePosition = position + trackerPosition +
@ -407,10 +412,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
renderDistortionMesh(eyeRenderPose);
glBindTexture(GL_TEXTURE_2D, 0);
// Update camera for use by rest of Interface.
whichCamera.setPosition((_leftEyePosition + _rightEyePosition) / 2.f);
whichCamera.setRotation(_camera->getRotation());
#endif
}

View 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();
//}
}
};
};

View 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

View file

@ -690,7 +690,6 @@ void Stats::display(
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
}
}
void Stats::setMetavoxelStats(int internal, int leaves, int sendProgress,

View file

@ -21,6 +21,10 @@
#include "InterfaceConfig.h"
#include "TextRenderer.h"
#include "glm/glm.hpp"
#include <glm/gtc/matrix_transform.hpp>
// the width/height of the cached glyph textures
const int IMAGE_SIZE = 256;
@ -63,8 +67,17 @@ int TextRenderer::calculateHeight(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;
for (const char* ch = str; *ch != 0; ch++) {
const Glyph& glyph = getGlyph(*ch);
@ -76,20 +89,24 @@ int TextRenderer::draw(int x, int y, const char* str) {
if (glyph.bounds().height() > maxHeight) {
maxHeight = glyph.bounds().height();
}
glBindTexture(GL_TEXTURE_2D, glyph.textureID());
//glBindTexture(GL_TEXTURE_2D, glyph.textureID());
int left = x + glyph.bounds().x();
int right = x + glyph.bounds().x() + glyph.bounds().width();
int bottom = y + glyph.bounds().y();
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 ls = glyph.location().x() * scale;
float rs = (glyph.location().x() + glyph.bounds().width()) * scale;
float bt = glyph.location().y() * scale;
float tt = (glyph.location().y() + glyph.bounds().height()) * scale;
// TODO: Remove that code once we test for performance improvments
/*
glBegin(GL_QUADS);
glTexCoord2f(ls, bt);
glVertex2f(left, bottom);
@ -100,12 +117,39 @@ int TextRenderer::draw(int x, int y, const char* str) {
glTexCoord2f(ls, tt);
glVertex2f(left, top);
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();
}
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;
}
@ -131,8 +175,10 @@ TextRenderer::TextRenderer(const Properties& properties) :
_x(IMAGE_SIZE),
_y(IMAGE_SIZE),
_rowHeight(0),
_color(properties.color) {
_color(properties.color),
_glyphsBuffer(),
_numGlyphsBatched(0)
{
_font.setKerning(false);
}
@ -228,9 +274,74 @@ const Glyph& TextRenderer::getGlyph(char c) {
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;
Glyph::Glyph(int textureID, const QPoint& location, const QRect& bounds, int width) :
_textureID(textureID), _location(location), _bounds(bounds), _width(width) {
}

View file

@ -19,6 +19,8 @@
#include <QImage>
#include <QVector>
#include "gpu/Resource.h"
#include "InterfaceConfig.h"
// a special "character" that renders as a solid block
@ -64,6 +66,8 @@ public:
int computeWidth(char ch);
int computeWidth(const char* str);
void drawBatch();
void clearBatch();
private:
TextRenderer(const Properties& properties);
@ -100,6 +104,11 @@ private:
// text 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;
};

View file

@ -18,7 +18,8 @@
BillboardOverlay::BillboardOverlay()
: _fromImage(-1,-1,-1,-1),
_scale(1.0f),
_isFacingAvatar(true) {
_isFacingAvatar(true),
_newTextureNeeded(true) {
_isLoaded = false;
}
@ -28,6 +29,9 @@ void BillboardOverlay::render() {
}
if (!_billboard.isEmpty()) {
if (_newTextureNeeded && _billboardTexture) {
_billboardTexture.reset();
}
if (!_billboardTexture) {
QImage image = QImage::fromData(_billboard);
if (image.format() != QImage::Format_ARGB32) {
@ -38,6 +42,7 @@ void BillboardOverlay::render() {
_fromImage.setRect(0, 0, _size.width(), _size.height());
}
_billboardTexture.reset(new Texture());
_newTextureNeeded = false;
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _size.width(), _size.height(), 0,
GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
@ -107,9 +112,10 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
QScriptValue urlValue = properties.property("url");
if (urlValue.isValid()) {
_url = urlValue.toVariant().toString();
setBillboardURL(_url);
QString newURL = urlValue.toVariant().toString();
if (newURL != _url) {
setBillboardURL(newURL);
}
}
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;
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);
}

View file

@ -33,12 +33,13 @@ private slots:
void replyFinished();
private:
void setBillboardURL(const QUrl url);
void setBillboardURL(const QString& url);
QUrl _url;
QString _url;
QByteArray _billboard;
QSize _size;
QScopedPointer<Texture> _billboardTexture;
bool _newTextureNeeded;
QRect _fromImage; // where from in the image to sample

View file

@ -13,6 +13,7 @@
#include <QGLWidget>
#include <SharedUtil.h>
#include <StreamUtils.h>
#include "Circle3DOverlay.h"
#include "renderer/GlowEffect.h"
@ -39,13 +40,18 @@ void Circle3DOverlay::render() {
if (!_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 SLICES = 180.0f; // The amount of segment to create the circle
const float SLICE_ANGLE = FULL_CIRCLE / SLICES;
//const int slices = 15;
float alpha = getAlpha();
xColor color = getColor();
const float MAX_COLOR = 255.0f;
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;
}

View file

@ -45,6 +45,8 @@ public:
void setMinorTickMarksLength(float value) { _minorTickMarksLength = value; }
void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = 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:
float _startAt;

View file

@ -12,6 +12,8 @@
#include "InterfaceConfig.h"
#include <QGLWidget>
#include <PlaneShape.h>
#include <RayIntersectionInfo.h>
#include <SharedUtil.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;
}

View file

@ -37,6 +37,8 @@ public:
virtual void setProperties(const QScriptValue& properties);
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
protected:
glm::vec2 _dimensions;
};

View file

@ -70,7 +70,7 @@ AttributeRegistry::AttributeRegistry() :
_heightfieldColorAttribute->setLODThresholdMultiplier(HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER);
_heightfieldMaterialAttribute->setLODThresholdMultiplier(HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER);
const float VOXEL_LOD_THRESHOLD_MULTIPLIER = 32.0f;
const float VOXEL_LOD_THRESHOLD_MULTIPLIER = 16.0f;
_voxelColorAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER);
_voxelColorAttribute->setUserFacing(true);
_voxelMaterialAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER);
@ -2112,53 +2112,41 @@ bool VoxelHermiteAttribute::merge(void*& parent, void* children[], bool postRead
QRgb* dest = contents.data() + ((zIndex * halfSize * area) + (yIndex * halfSize * size) + (xIndex * halfSize)) *
VoxelHermiteData::EDGE_COUNT;
const QRgb* src = childContents.data();
int offsets[VoxelHermiteData::EDGE_COUNT];
if (childSize == size) {
// simple case: one destination value for four child values
for (int z = 0; z < halfSizeComplement; z++) {
int offset4 = (z == halfSize) ? 0 : (childArea * VoxelHermiteData::EDGE_COUNT);
offsets[2] = (z == halfSize) ? 0 : (childArea * VoxelHermiteData::EDGE_COUNT);
for (int y = 0; y < halfSizeComplement; y++) {
int offset2 = (y == halfSize) ? 0 : (childSize * VoxelHermiteData::EDGE_COUNT);
int offset6 = offset4 + offset2;
offsets[1] = (y == halfSize) ? 0 : (childSize * VoxelHermiteData::EDGE_COUNT);
for (QRgb* end = dest + halfSizeComplement * VoxelHermiteData::EDGE_COUNT; dest != end;
dest += VoxelHermiteData::EDGE_COUNT) {
int offset1 = (dest == end - VoxelHermiteData::EDGE_COUNT) ? 0 : VoxelHermiteData::EDGE_COUNT;
offsets[0] = (dest == end - VoxelHermiteData::EDGE_COUNT) ? 0 : VoxelHermiteData::EDGE_COUNT;
for (int i = 0; i < VoxelHermiteData::EDGE_COUNT; i++) {
QRgb v[] = { src[i], src[offset1 + i], src[offset2 + i], src[offset2 + offset1 + i],
src[offset4 + i], src[offset4 + offset1 + i], src[offset6 + i], src[offset6 + offset1 + i] };
glm::vec3 n[] = { unpackNormal(v[0]), unpackNormal(v[1]), unpackNormal(v[2]), unpackNormal(v[3]),
unpackNormal(v[4]), unpackNormal(v[5]), unpackNormal(v[6]), unpackNormal(v[7]) };
float l[] = { glm::length(n[0]), glm::length(n[1]), glm::length(n[2]), glm::length(n[3]),
glm::length(n[4]), glm::length(n[5]), glm::length(n[6]), glm::length(n[7]) };
float lengthTotal = l[0] + l[1] + l[2] + l[3] + l[4] + l[5] + l[6] + l[7];
QRgb v0 = src[i], v1 = src[i + offsets[i]];
glm::vec3 n0 = unpackNormal(v0), n1 = unpackNormal(v1);
float l0 = glm::length(n0), l1 = glm::length(n1);
float lengthTotal = l0 + l1;
if (lengthTotal == 0.0f) {
dest[i] = qRgba(0, 0, 0, 0);
continue;
}
glm::vec3 combinedNormal = n[0] * l[0] + n[1] * l[1] + n[2] * l[2] + n[3] * l[3] + n[4] * l[4] +
n[5] * l[5] + n[6] * l[6] + n[7] * l[7];
glm::vec3 combinedNormal = n0 + n1;
float combinedLength = glm::length(combinedNormal);
if (combinedLength > 0.0f) {
combinedNormal /= combinedLength;
}
float combinedOffset = 0.0f;
int mask = 1 << i;
for (int j = 0; j < MERGE_COUNT; j++) {
float offset = qAlpha(v[j]) * (0.5f / EIGHT_BIT_MAXIMUM);
if (j & mask) {
offset += 0.5f;
}
combinedOffset += offset * l[j];
}
dest[i] = packNormal(combinedNormal, EIGHT_BIT_MAXIMUM * combinedOffset / lengthTotal);
float combinedOffset = qAlpha(v0) * 0.5f * l0 + (qAlpha(v1) + EIGHT_BIT_MAXIMUM) * 0.5f * l1;
dest[i] = packNormal(combinedNormal, combinedOffset / lengthTotal);
}
src += (VoxelHermiteData::EDGE_COUNT + offset1);
src += (VoxelHermiteData::EDGE_COUNT + offsets[0]);
}
dest += (halfSize * VoxelHermiteData::EDGE_COUNT);
src += offset2;
src += offsets[1];
}
dest += (halfSize * size * VoxelHermiteData::EDGE_COUNT);
src += offset4;
src += offsets[2];
}
} else {
// more complex: N destination values for four child values

View file

@ -85,7 +85,7 @@ PacketVersion versionForPacketType(PacketType type) {
case PacketTypeAudioStreamStats:
return 1;
case PacketTypeMetavoxelData:
return 4;
return 5;
case PacketTypeVoxelData:
return VERSION_VOXELS_HAS_FILE_BREAKS;
default:

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <glm/gtx/vector_angle.hpp>
#include <QDebug>
#include "Vec3.h"
@ -37,7 +39,7 @@ glm::vec3 Vec3::sum(const glm::vec3& v1, const glm::vec3& v2) {
return v1 + v2;
}
glm::vec3 Vec3::subtract(const glm::vec3& v1, const glm::vec3& v2) {
return v1 - v2;
return v1 - v2;
}
float Vec3::length(const glm::vec3& v) {
@ -48,6 +50,10 @@ float Vec3::distance(const glm::vec3& v1, const glm::vec3& 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) {
return glm::normalize(v);
}

View file

@ -34,6 +34,7 @@ public slots:
glm::vec3 subtract(const glm::vec3& v1, const glm::vec3& v2);
float length(const glm::vec3& v);
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);
void print(const QString& lable, const glm::vec3& v);
bool equal(const glm::vec3& v1, const glm::vec3& v2);