diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 23668bcc25..e1ea06c599 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -23,10 +23,15 @@ Line3DOverlay::Line3DOverlay() : Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) : Base3DOverlay(line3DOverlay), - _start(line3DOverlay->_start), - _end(line3DOverlay->_end), _geometryCacheID(DependencyManager::get()->allocateID()) { + setParentID(line3DOverlay->getParentID()); + setParentJointIndex(line3DOverlay->getParentJointIndex()); + setLocalTransform(line3DOverlay->getLocalTransform()); + _direction = line3DOverlay->getDirection(); + _length = line3DOverlay->getLength(); + _endParentID = line3DOverlay->getEndParentID(); + _endParentJointIndex = line3DOverlay->getEndJointIndex(); } Line3DOverlay::~Line3DOverlay() { @@ -37,17 +42,23 @@ Line3DOverlay::~Line3DOverlay() { } glm::vec3 Line3DOverlay::getStart() const { - bool success; - glm::vec3 worldStart = localToWorld(_start, getParentID(), getParentJointIndex(), success); - if (!success) { - qDebug() << "Line3DOverlay::getStart failed"; - } - return worldStart; + return getPosition(); } glm::vec3 Line3DOverlay::getEnd() const { bool success; - glm::vec3 worldEnd = localToWorld(_end, getParentID(), getParentJointIndex(), success); + glm::vec3 localEnd; + glm::vec3 worldEnd; + + if (_endParentID != QUuid()) { + glm::vec3 localOffset = _direction * _length; + bool success; + worldEnd = localToWorld(localOffset, _endParentID, _endParentJointIndex, success); + return worldEnd; + } + + localEnd = getLocalEnd(); + worldEnd = localToWorld(localEnd, getParentID(), getParentJointIndex(), success); if (!success) { qDebug() << "Line3DOverlay::getEnd failed"; } @@ -55,27 +66,55 @@ glm::vec3 Line3DOverlay::getEnd() const { } void Line3DOverlay::setStart(const glm::vec3& start) { - bool success; - _start = worldToLocal(start, getParentID(), getParentJointIndex(), success); - if (!success) { - qDebug() << "Line3DOverlay::setStart failed"; - } + setPosition(start); } void Line3DOverlay::setEnd(const glm::vec3& end) { bool success; - _end = worldToLocal(end, getParentID(), getParentJointIndex(), success); + glm::vec3 localStart; + glm::vec3 localEnd; + glm::vec3 offset; + + if (_endParentID != QUuid()) { + offset = worldToLocal(end, _endParentID, _endParentJointIndex, success); + } else { + localStart = getLocalStart(); + localEnd = worldToLocal(end, getParentID(), getParentJointIndex(), success); + offset = localEnd - localStart; + } if (!success) { qDebug() << "Line3DOverlay::setEnd failed"; + return; + } + + _length = glm::length(offset); + if (_length > 0.0f) { + _direction = glm::normalize(offset); + } else { + _direction = glm::vec3(0.0f); + } +} + +void Line3DOverlay::setLocalEnd(const glm::vec3& localEnd) { + glm::vec3 offset; + if (_endParentID != QUuid()) { + offset = localEnd; + } else { + glm::vec3 localStart = getLocalStart(); + offset = localEnd - localStart; + } + _length = glm::length(offset); + if (_length > 0.0f) { + _direction = glm::normalize(offset); + } else { + _direction = glm::vec3(0.0f); } } AABox Line3DOverlay::getBounds() const { auto extents = Extents{}; - extents.addPoint(_start); - extents.addPoint(_end); - extents.transform(getTransform()); - + extents.addPoint(getStart()); + extents.addPoint(getEnd()); return AABox(extents); } @@ -90,18 +129,20 @@ void Line3DOverlay::render(RenderArgs* args) { glm::vec4 colorv4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); auto batch = args->_batch; if (batch) { - batch->setModelTransform(getTransform()); + batch->setModelTransform(Transform()); + glm::vec3 start = getStart(); + glm::vec3 end = getEnd(); auto geometryCache = DependencyManager::get(); if (getIsDashedLine()) { // TODO: add support for color to renderDashedLine() geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); - geometryCache->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID); + geometryCache->renderDashedLine(*batch, start, end, colorv4, _geometryCacheID); } else if (_glow > 0.0f) { - geometryCache->renderGlowLine(*batch, _start, _end, colorv4, _glow, _glowWidth, _geometryCacheID); + geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _glowWidth, _geometryCacheID); } else { geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); - geometryCache->renderLine(*batch, _start, _end, colorv4, _geometryCacheID); + geometryCache->renderLine(*batch, start, end, colorv4, _geometryCacheID); } } } @@ -116,6 +157,10 @@ const render::ShapeKey Line3DOverlay::getShapeKey() { void Line3DOverlay::setProperties(const QVariantMap& originalProperties) { QVariantMap properties = originalProperties; + glm::vec3 newStart(0.0f); + bool newStartSet { false }; + glm::vec3 newEnd(0.0f); + bool newEndSet { false }; auto start = properties["start"]; // if "start" property was not there, check to see if they included aliases: startPoint @@ -123,30 +168,57 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) { start = properties["startPoint"]; } if (start.isValid()) { - setStart(vec3FromVariant(start)); + newStart = vec3FromVariant(start); + newStartSet = true; } properties.remove("start"); // so that Base3DOverlay doesn't respond to it - auto localStart = properties["localStart"]; - if (localStart.isValid()) { - _start = vec3FromVariant(localStart); - } - properties.remove("localStart"); // so that Base3DOverlay doesn't respond to it - auto end = properties["end"]; // if "end" property was not there, check to see if they included aliases: endPoint if (!end.isValid()) { end = properties["endPoint"]; } if (end.isValid()) { - setEnd(vec3FromVariant(end)); + newEnd = vec3FromVariant(end); + newEndSet = true; + } + properties.remove("end"); // so that Base3DOverlay doesn't respond to it + + auto length = properties["length"]; + if (length.isValid()) { + _length = length.toFloat(); + } + + Base3DOverlay::setProperties(properties); + + auto endParentIDProp = properties["endParentID"]; + if (endParentIDProp.isValid()) { + _endParentID = QUuid(endParentIDProp.toString()); + } + auto endParentJointIndexProp = properties["endParentJointIndex"]; + if (endParentJointIndexProp.isValid()) { + _endParentJointIndex = endParentJointIndexProp.toInt(); + } + + auto localStart = properties["localStart"]; + if (localStart.isValid()) { + glm::vec3 tmpLocalEnd = getLocalEnd(); + setLocalStart(vec3FromVariant(localStart)); + setLocalEnd(tmpLocalEnd); } auto localEnd = properties["localEnd"]; if (localEnd.isValid()) { - _end = vec3FromVariant(localEnd); + setLocalEnd(vec3FromVariant(localEnd)); + } + + // these are saved until after Base3DOverlay::setProperties so parenting infomation can be set, first + if (newStartSet) { + setStart(newStart); + } + if (newEndSet) { + setEnd(newEnd); } - properties.remove("localEnd"); // so that Base3DOverlay doesn't respond to it auto glow = properties["glow"]; if (glow.isValid()) { @@ -161,7 +233,6 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) { setGlow(glowWidth.toFloat()); } - Base3DOverlay::setProperties(properties); } QVariant Line3DOverlay::getProperty(const QString& property) { @@ -171,6 +242,15 @@ QVariant Line3DOverlay::getProperty(const QString& property) { if (property == "end" || property == "endPoint" || property == "p2") { return vec3toVariant(getEnd()); } + if (property == "localStart") { + return vec3toVariant(getLocalStart()); + } + if (property == "localEnd") { + return vec3toVariant(getLocalEnd()); + } + if (property == "length") { + return QVariant(getLength()); + } return Base3DOverlay::getProperty(property); } diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index b4e2ba8168..aceecff6b2 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -15,7 +15,7 @@ class Line3DOverlay : public Base3DOverlay { Q_OBJECT - + public: static QString const TYPE; virtual QString getType() const override { return TYPE; } @@ -37,6 +37,9 @@ public: void setStart(const glm::vec3& start); void setEnd(const glm::vec3& end); + void setLocalStart(const glm::vec3& localStart) { setLocalPosition(localStart); } + void setLocalEnd(const glm::vec3& localEnd); + void setGlow(const float& glow) { _glow = glow; } void setGlowWidth(const float& glowWidth) { _glowWidth = glowWidth; } @@ -47,13 +50,26 @@ public: virtual void locationChanged(bool tellPhysics = true) override; -protected: - glm::vec3 _start; - glm::vec3 _end; + glm::vec3 getDirection() const { return _direction; } + float getLength() const { return _length; } + glm::vec3 getLocalStart() const { return getLocalPosition(); } + glm::vec3 getLocalEnd() const { return getLocalStart() + _direction * _length; } + QUuid getEndParentID() const { return _endParentID; } + quint16 getEndJointIndex() const { return _endParentJointIndex; } + +private: + QUuid _endParentID; + quint16 _endParentJointIndex { INVALID_JOINT_INDEX }; + + // _direction and _length are in the parent's frame. If _endParentID is set, they are + // relative to that. Otherwise, they are relative to the local-start-position (which is the + // same as localPosition) + glm::vec3 _direction; // in parent frame + float _length { 1.0 }; // in parent frame + float _glow { 0.0 }; float _glowWidth { 0.0 }; int _geometryCacheID; }; - #endif // hifi_Line3DOverlay_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 55a9c8b9e4..8ab65efd24 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -160,13 +160,14 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { addJob("DrawOverlay3DOpaque", overlayOpaquesInputs, true); addJob("DrawOverlay3DTransparent", overlayTransparentsInputs, false); - // Debugging stages { // Bounds do not draw on stencil buffer, so they must come last addJob("DrawMetaBounds", metas); + addJob("DrawOverlayOpaqueBounds", overlayOpaques); + addJob("DrawOverlayTransparentBounds", overlayTransparents); // Debugging Deferred buffer job const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index cf3c9af83a..b8548a8d29 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -761,6 +761,10 @@ function MyController(hand) { this.stylus = null; this.homeButtonTouched = false; + this.controllerJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? + "_CONTROLLER_RIGHTHAND" : + "_CONTROLLER_LEFTHAND"); + // Until there is some reliable way to keep track of a "stack" of parentIDs, we'll have problems // when more than one avatar does parenting grabs on things. This script tries to work // around this with two associative arrays: previousParentID and previousParentJointIndex. If @@ -812,9 +816,6 @@ function MyController(hand) { // for visualizations this.overlayLine = null; - - // for lights - this.overlayLine = null; this.searchSphere = null; this.waitForTriggerRelease = false; @@ -941,9 +942,7 @@ function MyController(hand) { ignoreRayIntersection: true, drawInFront: false, parentID: AVATAR_SELF_ID, - parentJointIndex: MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? - "_CONTROLLER_RIGHTHAND" : - "_CONTROLLER_LEFTHAND") + parentJointIndex: this.controllerJointIndex }); } }; @@ -1028,32 +1027,38 @@ function MyController(hand) { } }; - this.overlayLineOn = function(closePoint, farPoint, color) { + this.overlayLineOn = function(closePoint, farPoint, color, farParentID) { if (this.overlayLine === null) { var lineProperties = { name: "line", glow: 1.0, - start: closePoint, - end: farPoint, - color: color, - ignoreRayIntersection: true, // always ignore this - drawInFront: true, // Even when burried inside of something, show it. - visible: true, - alpha: 1 - }; - this.overlayLine = Overlays.addOverlay("line3d", lineProperties); - - } else { - Overlays.editOverlay(this.overlayLine, { lineWidth: 5, start: closePoint, end: farPoint, color: color, - visible: true, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. - alpha: 1 - }); + visible: true, + alpha: 1, + parentID: AVATAR_SELF_ID, + parentJointIndex: this.controllerJointIndex, + endParentID: farParentID + }; + this.overlayLine = Overlays.addOverlay("line3d", lineProperties); + + } else { + if (farParentID && farParentID != NULL_UUID) { + Overlays.editOverlay(this.overlayLine, { + color: color, + endParentID: farParentID + }); + } else { + Overlays.editOverlay(this.overlayLine, { + length: Vec3.distance(farPoint, closePoint), + color: color, + endParentID: farParentID + }); + } } }; @@ -2245,7 +2250,10 @@ function MyController(hand) { var rayPickInfo = this.calcRayPickInfo(this.hand); - this.overlayLineOn(rayPickInfo.searchRay.origin, Vec3.subtract(grabbedProperties.position, this.offsetPosition), COLORS_GRAB_DISTANCE_HOLD); + this.overlayLineOn(rayPickInfo.searchRay.origin, + Vec3.subtract(grabbedProperties.position, this.offsetPosition), + COLORS_GRAB_DISTANCE_HOLD, + this.grabbedThingID); var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, this.currentObjectPosition)); var success = Entities.updateAction(this.grabbedThingID, this.actionID, { @@ -2437,9 +2445,7 @@ function MyController(hand) { this.actionID = null; var handJointIndex; if (this.ignoreIK) { - handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? - "_CONTROLLER_RIGHTHAND" : - "_CONTROLLER_LEFTHAND"); + handJointIndex = this.controllerJointIndex; } else { handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); } @@ -3246,9 +3252,7 @@ function MyController(hand) { return true; } - var controllerJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? - "_CONTROLLER_RIGHTHAND" : - "_CONTROLLER_LEFTHAND"); + var controllerJointIndex = this.controllerJointIndex; if (props.parentJointIndex == controllerJointIndex) { return true; } @@ -3274,9 +3278,7 @@ function MyController(hand) { children = children.concat(Entities.getChildrenIDsOfJoint(AVATAR_SELF_ID, handJointIndex)); // find children of faux controller joint - var controllerJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? - "_CONTROLLER_RIGHTHAND" : - "_CONTROLLER_LEFTHAND"); + var controllerJointIndex = this.controllerJointIndex; children = children.concat(Entities.getChildrenIDsOfJoint(MyAvatar.sessionUUID, controllerJointIndex)); children = children.concat(Entities.getChildrenIDsOfJoint(AVATAR_SELF_ID, controllerJointIndex)); @@ -3288,7 +3290,8 @@ function MyController(hand) { children = children.concat(Entities.getChildrenIDsOfJoint(AVATAR_SELF_ID, controllerCRJointIndex)); children.forEach(function(childID) { - if (childID !== _this.stylus) { + if (childID !== _this.stylus && + childID !== _this.overlayLine) { // we appear to be holding something and this script isn't in a state that would be holding something. // unhook it. if we previously took note of this entity's parent, put it back where it was. This // works around some problems that happen when more than one hand or avatar is passing something around.