From 98a8d3361bde86aaf83d9291357a060405e74a79 Mon Sep 17 00:00:00 2001 From: David Back Date: Mon, 16 Jul 2018 18:21:58 -0700 Subject: [PATCH 01/13] stop findGroupParent at cloneable --- libraries/entities/src/EntityItemProperties.cpp | 1 + .../controllers/controllerModules/highlightNearbyEntities.js | 2 +- .../controllers/controllerModules/nearParentGrabEntity.js | 3 ++- scripts/system/libraries/controllerDispatcherUtils.js | 5 ++++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index efd2376677..650e391378 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -3676,6 +3676,7 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityIDToClone) { setName(getName() + "-clone-" + entityIDToClone.toString()); setLocked(false); + setParentID(QUuid()); setLifetime(getCloneLifetime()); setDynamic(getCloneDynamic()); setClientOnly(getCloneAvatarEntity()); diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index bc09ebee7a..2fecf2947e 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -47,7 +47,7 @@ var canGrabEntity = false; if (dispatcherUtils.entityIsGrabbable(props) || entityIsCloneable(props)) { // if we've attempted to grab a child, roll up to the root of the tree - var groupRootProps = dispatcherUtils.findGroupParent(controllerData, props); + var groupRootProps = dispatcherUtils.findGroupParent(controllerData, props, false); canGrabEntity = true; if (!dispatcherUtils.entityIsGrabbable(groupRootProps)) { canGrabEntity = false; diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 00d7ad0491..3152f74e79 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -254,7 +254,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.hapticTargetID = props.id; } // if we've attempted to grab a child, roll up to the root of the tree - var groupRootProps = findGroupParent(controllerData, props); + var stopAtCloneable = true; + var groupRootProps = findGroupParent(controllerData, props, stopAtCloneable); if (entityIsGrabbable(groupRootProps)) { return groupRootProps; } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 5dfb0d5b69..87176501b2 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -355,10 +355,13 @@ ensureDynamic = function (entityID) { } }; -findGroupParent = function (controllerData, targetProps) { +findGroupParent = function (controllerData, targetProps, stopAtCloneable) { while (targetProps.parentID && targetProps.parentID !== Uuid.NULL && Entities.getNestableType(targetProps.parentID) == "entity") { + if (stopAtCloneable && entityIsCloneable(targetProps)) { + break; + } var parentProps = Entities.getEntityProperties(targetProps.parentID, DISPATCHER_PROPERTIES); if (!parentProps) { break; From e11030bbc3ebb7229933bbdbf861652a79fbc6cd Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 1 Aug 2018 09:46:17 -0700 Subject: [PATCH 02/13] mukul's changes, enable parabolic teleport --- .../controllers/controllerModules/teleport.js | 78 ++++++------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 4255eeb400..21acb9346b 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -22,7 +22,6 @@ Script.include("/~/system/libraries/controllers.js"); (function() { // BEGIN LOCAL_SCOPE var TARGET_MODEL_URL = Script.resolvePath("../../assets/models/teleport-destination.fbx"); - var TOO_CLOSE_MODEL_URL = Script.resolvePath("../../assets/models/teleport-cancel.fbx"); var SEAT_MODEL_URL = Script.resolvePath("../../assets/models/teleport-seat.fbx"); var TARGET_MODEL_DIMENSIONS = { @@ -49,8 +48,6 @@ Script.include("/~/system/libraries/controllers.js"); blue: 73 }; - var COOL_IN_DURATION = 300; - var handInfo = { right: { controllerInput: Controller.Standard.RightHand @@ -61,37 +58,19 @@ Script.include("/~/system/libraries/controllers.js"); }; var cancelPath = { - type: "line3d", color: COLORS_TELEPORT_CANCEL, - ignorePickIntersection: true, alpha: 1, - solid: true, - drawInFront: true, - glow: 1.0 + width: 0.025 }; var teleportPath = { - type: "line3d", color: COLORS_TELEPORT_CAN_TELEPORT, - ignorePickIntersection: true, alpha: 1, - solid: true, - drawInFront: true, - glow: 1.0 + width: 0.025 }; var seatPath = { - type: "line3d", color: COLORS_TELEPORT_SEAT, - ignorePickIntersection: true, alpha: 1, - solid: true, - drawInFront: true, - glow: 1.0 - }; - var cancelEnd = { - type: "model", - url: TOO_CLOSE_MODEL_URL, - dimensions: TARGET_MODEL_DIMENSIONS, - ignorePickIntersection: true + width: 0.025 }; var teleportEnd = { type: "model", @@ -107,20 +86,18 @@ Script.include("/~/system/libraries/controllers.js"); }; - var teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd}, + var teleportRenderStates = [{name: "cancel", path: cancelPath}, {name: "teleport", path: teleportPath, end: teleportEnd}, {name: "seat", path: seatPath, end: seatEnd}]; - var DEFAULT_DISTANCE = 50; + var DEFAULT_DISTANCE = 8.0; var teleportDefaultRenderStates = [{name: "cancel", distance: DEFAULT_DISTANCE, path: cancelPath}]; - var coolInTimeout = null; var ignoredEntities = []; var TELEPORTER_STATES = { IDLE: 'idle', - COOL_IN: 'cool_in', TARGETTING: 'targetting', TARGETTING_INVALID: 'targetting_invalid' }; @@ -133,7 +110,7 @@ Script.include("/~/system/libraries/controllers.js"); SEAT: 'seat' // The current target is a seat }; - var speed = 7.0; + var speed = 12.0; var accelerationAxis = {x: 0.0, y: -5.0, z: 0.0}; function Teleporter(hand) { @@ -151,8 +128,10 @@ Script.include("/~/system/libraries/controllers.js"); return otherModule; }; - this.teleportParabolaHandVisible = Pointers.createPointer(PickType.Ray, { + this.teleportParabolaHandVisible = Pointers.createPointer(PickType.Parabola, { joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + dirOffset: { x: 0, y: 1, z: 0.1 }, + posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 }, filter: Picks.PICK_ENTITIES, faceAvatar: true, scaleWithAvatar: true, @@ -161,10 +140,13 @@ Script.include("/~/system/libraries/controllers.js"); accelerationAxis: accelerationAxis, rotateAccelerationWithAvatar: true, renderStates: teleportRenderStates, - defaultRenderStates: teleportDefaultRenderStates + defaultRenderStates: teleportDefaultRenderStates, + maxDistance: 8.0 }); - this.teleportParabolaHandInvisible = Pointers.createPointer(PickType.Ray, { + this.teleportParabolaHandInvisible = Pointers.createPointer(PickType.Parabola, { joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + dirOffset: { x: 0, y: 1, z: 0.1 }, + posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 }, filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE, faceAvatar: true, scaleWithAvatar: true, @@ -172,9 +154,10 @@ Script.include("/~/system/libraries/controllers.js"); speed: speed, accelerationAxis: accelerationAxis, rotateAccelerationWithAvatar: true, - renderStates: teleportRenderStates + renderStates: teleportRenderStates, + maxDistance: 8.0 }); - this.teleportParabolaHeadVisible = Pointers.createPointer(PickType.Ray, { + this.teleportParabolaHeadVisible = Pointers.createPointer(PickType.Parabola, { joint: "Avatar", filter: Picks.PICK_ENTITIES, faceAvatar: true, @@ -184,9 +167,10 @@ Script.include("/~/system/libraries/controllers.js"); accelerationAxis: accelerationAxis, rotateAccelerationWithAvatar: true, renderStates: teleportRenderStates, - defaultRenderStates: teleportDefaultRenderStates + defaultRenderStates: teleportDefaultRenderStates, + maxDistance: 8.0 }); - this.teleportParabolaHeadInvisible = Pointers.createPointer(PickType.Ray, { + this.teleportParabolaHeadInvisible = Pointers.createPointer(PickType.Parabola, { joint: "Avatar", filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE, faceAvatar: true, @@ -195,7 +179,8 @@ Script.include("/~/system/libraries/controllers.js"); speed: speed, accelerationAxis: accelerationAxis, rotateAccelerationWithAvatar: true, - renderStates: teleportRenderStates + renderStates: teleportRenderStates, + maxDistance: 8.0 }); this.cleanup = function() { @@ -216,16 +201,7 @@ Script.include("/~/system/libraries/controllers.js"); 100); this.enterTeleport = function() { - if (coolInTimeout !== null) { - Script.clearTimeout(coolInTimeout); - } - - this.state = TELEPORTER_STATES.COOL_IN; - coolInTimeout = Script.setTimeout(function() { - if (_this.state === TELEPORTER_STATES.COOL_IN) { - _this.state = TELEPORTER_STATES.TARGETTING; - } - }, COOL_IN_DURATION); + this.state = TELEPORTER_STATES.TARGETTING; }; this.isReady = function(controllerData, deltaTime) { @@ -287,11 +263,7 @@ Script.include("/~/system/libraries/controllers.js"); } else if (teleportLocationType === TARGET.INVALID || teleportLocationType === TARGET.INVISIBLE) { this.setTeleportState(mode, "", "cancel"); } else if (teleportLocationType === TARGET.SURFACE) { - if (this.state === TELEPORTER_STATES.COOL_IN) { - this.setTeleportState(mode, "cancel", ""); - } else { - this.setTeleportState(mode, "teleport", ""); - } + this.setTeleportState(mode, "teleport", ""); } else if (teleportLocationType === TARGET.SEAT) { this.setTeleportState(mode, "", "seat"); } @@ -304,7 +276,7 @@ Script.include("/~/system/libraries/controllers.js"); return makeRunningValues(true, [], []); } - if (target === TARGET.NONE || target === TARGET.INVALID || this.state === TELEPORTER_STATES.COOL_IN) { + if (target === TARGET.NONE || target === TARGET.INVALID) { // Do nothing } else if (target === TARGET.SEAT) { Entities.callEntityMethod(result.objectID, 'sit'); From a8c408abe82621431ba3af10f4b252fde39d283f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 1 Aug 2018 10:59:21 -0700 Subject: [PATCH 03/13] correct render bounds for parabolas --- interface/src/raypick/ParabolaPointer.cpp | 38 +++++++++++++++++++---- interface/src/raypick/ParabolaPointer.h | 1 + 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp index 9371995a2a..fd6bdc7dbb 100644 --- a/interface/src/raypick/ParabolaPointer.cpp +++ b/interface/src/raypick/ParabolaPointer.cpp @@ -117,8 +117,6 @@ ParabolaPointer::RenderState::RenderState(const OverlayID& startID, const Overla _pathWidth = pathWidth; if (render::Item::isValidID(_pathID)) { auto renderItem = std::make_shared(pathColor, pathAlpha, pathWidth, isVisibleInSecondaryCamera, pathEnabled); - // TODO: update bounds properly - renderItem->editBound().setBox(glm::vec3(-16000.0f), 32000.0f); transaction.resetItem(_pathID, std::make_shared(renderItem)); scene->enqueueTransaction(transaction); } @@ -182,6 +180,7 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve item.setAcceleration(acceleration); item.setParabolicDistance(parabolicDistance); item.setWidth(width); + item.updateBounds(); }); scene->enqueueTransaction(transaction); } @@ -304,10 +303,10 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::setVisible(bool visible) } void ParabolaPointer::RenderState::ParabolaRenderItem::updateKey() { - // FIXME: There's no way to designate a render item as non-shadow-reciever, and since a parabola's bounding box covers the entire domain, - // it seems to block all shadows. I think this is a bug with shadows. - //auto builder = _parabolaData.color.a < 1.0f ? render::ItemKey::Builder::transparentShape() : render::ItemKey::Builder::opaqueShape(); - auto builder = render::ItemKey::Builder::transparentShape(); + auto builder = _parabolaData.color.a < 1.0f ? render::ItemKey::Builder::transparentShape() : render::ItemKey::Builder::opaqueShape(); + + // TODO: parabolas should cast shadows, but they're so thin that the cascaded shadow maps make them look pretty bad + //builder.withShadowCaster(); if (_enabled && _visible) { builder.withVisible(); @@ -324,6 +323,33 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::updateKey() { _key = builder.build(); } +void ParabolaPointer::RenderState::ParabolaRenderItem::updateBounds() { + glm::vec3 max = _origin; + glm::vec3 min = _origin; + + glm::vec3 end = _origin + _parabolaData.velocity * _parabolaData.parabolicDistance + + 0.5f * _parabolaData.acceleration * _parabolaData.parabolicDistance * _parabolaData.parabolicDistance; + max = glm::max(max, end); + min = glm::min(min, end); + + for (int i = 0; i < 3; i++) { + if (fabsf(_parabolaData.velocity[i]) > EPSILON && fabsf(_parabolaData.acceleration[i]) > EPSILON) { + float maxT = -_parabolaData.velocity[i] / _parabolaData.acceleration[i]; + if (maxT > 0.0f && maxT < _parabolaData.parabolicDistance) { + glm::vec3 maxPoint = _origin + _parabolaData.velocity * maxT + 0.5f * _parabolaData.acceleration * maxT * maxT; + max = glm::max(max, maxPoint); + min = glm::min(min, maxPoint); + } + } + } + + glm::vec3 halfWidth = glm::vec3(0.5f * _parabolaData.width); + max += halfWidth; + min -= halfWidth; + + _bound = AABox(min, max - min); +} + const gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabolaPipeline() { if (!_parabolaPipeline || !_transparentParabolaPipeline) { auto vs = parabola_vert::getShader(); diff --git a/interface/src/raypick/ParabolaPointer.h b/interface/src/raypick/ParabolaPointer.h index ee4977e1e4..93f9a7b055 100644 --- a/interface/src/raypick/ParabolaPointer.h +++ b/interface/src/raypick/ParabolaPointer.h @@ -36,6 +36,7 @@ public: void setVisible(bool visible); void updateKey(); void updateUniformBuffer() { _uniformBuffer->setSubData(0, _parabolaData); } + void updateBounds(); void setColor(const glm::vec3& color) { _parabolaData.color = glm::vec4(color, _parabolaData.color.a); } void setAlpha(const float& alpha) { _parabolaData.color.a = alpha; } From 0b9e520b53c912c5e38d203a5f6d190b164148c7 Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 1 Aug 2018 16:00:25 -0700 Subject: [PATCH 04/13] fix grab cloning parented entitiy --- libraries/entities/src/EntityItemProperties.cpp | 2 ++ .../controllerModules/nearActionGrabEntity.js | 10 ++++++---- .../controllerModules/nearParentGrabEntity.js | 10 ++++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1f9bf2eb18..27fe55673f 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -3743,6 +3743,8 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityIDToClone) { setName(getName() + "-clone-" + entityIDToClone.toString()); setLocked(false); + setParentID(QUuid()); + setParentJointIndex(-1); setLifetime(getCloneLifetime()); setDynamic(getCloneDynamic()); setClientOnly(getCloneAvatarEntity()); diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index f528c6f80f..a8de76aebd 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -174,10 +174,12 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); this.hapticTargetID = props.id; } - // if we've attempted to grab a child, roll up to the root of the tree - var groupRootProps = findGroupParent(controllerData, props); - if (entityIsGrabbable(groupRootProps)) { - return groupRootProps; + if (!entityIsCloneable(props)) { + // if we've attempted to grab a non-cloneable child, roll up to the root of the tree + var groupRootProps = findGroupParent(controllerData, props); + if (entityIsGrabbable(groupRootProps)) { + return groupRootProps; + } } return props; } diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index a0a4608fbc..3089545dc1 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -268,10 +268,12 @@ Script.include("/~/system/libraries/controllers.js"); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); this.hapticTargetID = props.id; } - // if we've attempted to grab a child, roll up to the root of the tree - var groupRootProps = findGroupParent(controllerData, props); - if (entityIsGrabbable(groupRootProps)) { - return groupRootProps; + if (!entityIsCloneable(props)) { + // if we've attempted to grab a non-cloneable child, roll up to the root of the tree + var groupRootProps = findGroupParent(controllerData, props); + if (entityIsGrabbable(groupRootProps)) { + return groupRootProps; + } } return props; } From 6b7f5b662e719b37142d7b7c5d6daf0275e2367e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Aug 2018 09:58:29 -0700 Subject: [PATCH 05/13] jsdoc fixes --- interface/src/raypick/PickScriptingInterface.h | 2 +- interface/src/raypick/PointerScriptingInterface.cpp | 13 +++++++------ libraries/pointers/src/Pick.h | 2 ++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 131f14d168..9b6290b764 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -138,7 +138,7 @@ public: * @property {Vec3} intersection The intersection point in world-space. * @property {Vec3} surfaceNormal The surface normal at the intersected point. All NANs if type == INTERSECTED_HUD. * @property {Variant} extraInfo Additional intersection details when available for Model objects. - * @property {StylusTip} parabola The PickParabola that was used. Valid even if there was no intersection. + * @property {PickParabola} parabola The PickParabola that was used. Valid even if there was no intersection. */ /**jsdoc diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index 5bb4293ef3..a9b9b6e9ea 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -92,7 +92,7 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) * @typedef {object} Pointers.LaserPointerProperties * @property {boolean} [faceAvatar=false] If true, the end of the Pointer will always rotate to face the avatar. * @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height. - * @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the laser is pointing. + * @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing. * @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance. * @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale. * @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface. @@ -207,9 +207,10 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope * The rendering properties of the parabolic path * * @typedef {object} Pointers.ParabolaProperties -* @property {Color} color The color of the parabola. -* @property {number} alpha The alpha of the parabola. -* @property {number} width The width of the parabola, in meters. +* @property {Color} color=255,255,255 The color of the parabola. +* @property {number} alpha=1.0 The alpha of the parabola. +* @property {number} width=0.01 The width of the parabola, in meters. +* @property {boolean} isVisibleInSecondaryCamera=false The width of the parabola, in meters. */ /**jsdoc * A set of properties used to define the visual aspect of a Parabola Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.ParabolaPointerRenderState}, @@ -232,10 +233,10 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope */ /**jsdoc * A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick. -* @typedef {object} Pointers.LaserPointerProperties +* @typedef {object} Pointers.ParabolaPointerProperties * @property {boolean} [faceAvatar=false] If true, the end of the Pointer will always rotate to face the avatar. * @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height. -* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the laser is pointing. +* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing. * @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance. * @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale. * @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface. diff --git a/libraries/pointers/src/Pick.h b/libraries/pointers/src/Pick.h index dd59b50cc4..790c5dfd27 100644 --- a/libraries/pointers/src/Pick.h +++ b/libraries/pointers/src/Pick.h @@ -145,6 +145,7 @@ public: * * @property {number} Ray Ray Picks intersect a ray with the nearest object in front of them, along a given direction. * @property {number} Stylus Stylus Picks provide "tapping" functionality on/into flat surfaces. + * @property {number} Parabola Parabola Picks intersect a parabola with the nearest object in front of them, with a given initial velocity and acceleration. */ /**jsdoc * @@ -154,6 +155,7 @@ public: * * * + * * *
{@link PickType(0)|PickType.Ray}
{@link PickType(0)|PickType.Stylus}
{@link PickType(0)|PickType.Parabola}
* @typedef {number} PickType From 40889c8f09a10fdd8100895b9c22f154a781377e Mon Sep 17 00:00:00 2001 From: MuteTab Date: Mon, 6 Aug 2018 15:35:54 -0700 Subject: [PATCH 06/13] Added getWorldFeetPosition() function to Avatar --- .../avatars-renderer/src/avatars-renderer/Avatar.cpp | 8 ++++++++ libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 69356cdfaa..873fc94021 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1577,6 +1577,14 @@ void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) { radius = halfExtents.x; } +glm::vec3 Avatar::getWorldFeetPosition() { + ShapeInfo shapeInfo; + computeShapeInfo(shapeInfo); + glm::vec3 halfExtents = shapeInfo.getHalfExtents(); // x = radius, y = halfHeight + glm::vec3 localFeet(0.0f, shapeInfo.getOffset().y - halfExtents.y - halfExtents.x, 0.0f); + return getWorldOrientation() * localFeet + getWorldPosition(); +} + float Avatar::computeMass() { float radius; glm::vec3 start, end; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 157f7b2ec6..5a12e0ffef 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -249,6 +249,12 @@ public: virtual void computeShapeInfo(ShapeInfo& shapeInfo); void getCapsule(glm::vec3& start, glm::vec3& end, float& radius); float computeMass(); + /**jsdoc + * Get the position of the current avatar's feet (or rather, bottom of its collision capsule) in world coordinates. + * @function MyAvatar.getWorldFeetPosition() + * @returns {Vec3} + */ + Q_INVOKABLE glm::vec3 getWorldFeetPosition(); void setPositionViaScript(const glm::vec3& position) override; void setOrientationViaScript(const glm::quat& orientation) override; From de5c7f6dcd47585110e243778b100e279882eb25 Mon Sep 17 00:00:00 2001 From: MuteTab Date: Mon, 6 Aug 2018 16:02:00 -0700 Subject: [PATCH 07/13] Change lambda for address manager position getter. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9b2498138e..82d50c33ab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1247,7 +1247,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); // use our MyAvatar position and quat for address manager path - addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldPosition(); }); + addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldFeetPosition(); }); addressManager->setOrientationGetter([this]{ return getMyAvatar()->getWorldOrientation(); }); connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); From d04ac2b8edbd46125e9d795145162edd5f576f14 Mon Sep 17 00:00:00 2001 From: MuteTab Date: Mon, 6 Aug 2018 19:40:47 -0700 Subject: [PATCH 08/13] Fixed jsdoc comments for Avatar::getWorldFeetPosition --- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 5a12e0ffef..919a13095f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -251,8 +251,8 @@ public: float computeMass(); /**jsdoc * Get the position of the current avatar's feet (or rather, bottom of its collision capsule) in world coordinates. - * @function MyAvatar.getWorldFeetPosition() - * @returns {Vec3} + * @function MyAvatar.getWorldFeetPosition + * @returns {Vec3} The position of the Avatar's feet in world coordinates. */ Q_INVOKABLE glm::vec3 getWorldFeetPosition(); From b590ff793a867169a03d6c518c7b736f7faecb1f Mon Sep 17 00:00:00 2001 From: MuteTab Date: Mon, 6 Aug 2018 20:26:44 -0700 Subject: [PATCH 09/13] New function for changing location in domains such that the AVatar's leg-length is taken into account. --- interface/src/avatar/MyAvatar.cpp | 50 ++++++++++++++++++++++++++++++- interface/src/avatar/MyAvatar.h | 14 +++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3f738ea4cb..5a5d99d6f0 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -154,7 +154,7 @@ MyAvatar::MyAvatar(QThread* thread) : // connect to AddressManager signal for location jumps connect(DependencyManager::get().data(), &AddressManager::locationChangeRequired, - this, static_cast(&MyAvatar::goToLocation)); + this, static_cast(&MyAvatar::goToFeetLocation)); // handle scale constraints imposed on us by the domain-server auto& domainHandler = DependencyManager::get()->getDomainHandler(); @@ -2623,6 +2623,54 @@ void MyAvatar::goToLocation(const QVariant& propertiesVar) { } } +void MyAvatar::goToFeetLocation(const glm::vec3& newPosition, + bool hasOrientation, const glm::quat& newOrientation, + bool shouldFaceLocation) { + + qCDebug(interfaceapp).nospace() << "MyAvatar goToFeetLocation - moving to " << newPosition.x << ", " + << newPosition.y << ", " << newPosition.z; + + ShapeInfo shapeInfo; + computeShapeInfo(shapeInfo); + glm::vec3 halfExtents = shapeInfo.getHalfExtents(); + glm::vec3 localFeetPos = shapeInfo.getOffset() - glm::vec3(0.0f, halfExtents.y + halfExtents.x, 0.0f); + glm::mat4 localFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, localFeetPos); + + glm::mat4 worldFeet; + if (hasOrientation) { + worldFeet = createMatFromQuatAndPos(newOrientation, newPosition); + } else { + worldFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, newPosition); + } + + glm::mat4 avatarMat = worldFeet * glm::inverse(localFeet); + + glm::vec3 adjustedPosition = extractTranslation(avatarMat); + + _goToPending = true; + _goToPosition = adjustedPosition; + _goToOrientation = getWorldOrientation(); + if (hasOrientation) { + qCDebug(interfaceapp).nospace() << "MyAvatar goToFeetLocation - new orientation is " + << newOrientation.x << ", " << newOrientation.y << ", " << newOrientation.z << ", " << newOrientation.w; + + // orient the user to face the target + glm::quat quatOrientation = cancelOutRollAndPitch(newOrientation); + + if (shouldFaceLocation) { + quatOrientation = newOrientation * glm::angleAxis(PI, Vectors::UP); + + // move the user a couple units away + const float DISTANCE_TO_USER = 2.0f; + _goToPosition = adjustedPosition - quatOrientation * IDENTITY_FORWARD * DISTANCE_TO_USER; + } + + _goToOrientation = quatOrientation; + } + + emit transformChanged(); +} + void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::quat& newOrientation, bool shouldFaceLocation) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d36e43ca25..b34eb4386d 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1133,6 +1133,20 @@ public slots: */ float getGravity(); + /**jsdoc + * Move the avatar to a new position and/or orientation in the domain, while taking into account Avatar leg-length. + * @function MyAvatar.goToFeetLocation + * @param {Vec3} position - The new position for the avatar, in world coordinates. + * @param {boolean} [hasOrientation=false] - Set to true to set the orientation of the avatar. + * @param {Quat} [orientation=Quat.IDENTITY] - The new orientation for the avatar. + * @param {boolean} [shouldFaceLocation=false] - Set to true to position the avatar a short distance away from + * the new position and orientate the avatar to face the position. + */ + + void goToFeetLocation(const glm::vec3& newPosition, + bool hasOrientation, const glm::quat& newOrientation, + bool shouldFaceLocation); + /**jsdoc * Move the avatar to a new position and/or orientation in the domain. * @function MyAvatar.goToLocation From c9c23b8db3daad1296f531b4528d4354f441c24e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 7 Aug 2018 15:34:17 +1200 Subject: [PATCH 10/13] Fix entity stay highlighted after hand leaves when far grabbing another --- .../controllers/controllerModules/nearParentGrabEntity.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index a0a4608fbc..fe6497ff05 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -100,6 +100,7 @@ Script.include("/~/system/libraries/controllers.js"); this.startNearParentingGrabEntity = function (controllerData, targetProps) { Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); unhighlightTargetEntity(this.targetEntityID); + this.highlightedEntity = null; var message = { hand: this.hand, entityID: this.targetEntityID @@ -177,6 +178,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" })); unhighlightTargetEntity(this.targetEntityID); + this.highlightedEntity = null; this.grabbing = false; this.targetEntityID = null; this.robbed = false; @@ -304,6 +306,10 @@ Script.include("/~/system/libraries/controllers.js"); return makeRunningValues(true, [this.targetEntityID], []); } } else { + if (this.highlightedEntity) { + unhighlightTargetEntity(this.highlightedEntity); + this.highlightedEntity = null; + } this.hapticTargetID = null; this.robbed = false; return makeRunningValues(false, [], []); @@ -322,6 +328,7 @@ Script.include("/~/system/libraries/controllers.js"); if (!props) { // entity was deleted unhighlightTargetEntity(this.targetEntityID); + this.highlightedEntity = NULL; this.grabbing = false; this.targetEntityID = null; this.hapticTargetID = null; @@ -344,6 +351,7 @@ Script.include("/~/system/libraries/controllers.js"); if (!readiness.active) { this.robbed = false; unhighlightTargetEntity(this.highlightedEntity); + this.highlightedEntity = null; return readiness; } if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) { From 1aa9fcd41a4f20cd20f5720c79bd90c700c0e306 Mon Sep 17 00:00:00 2001 From: r3tk0n <39922250+r3tk0n@users.noreply.github.com> Date: Mon, 6 Aug 2018 21:23:06 -0700 Subject: [PATCH 11/13] Fix a typo In jsdoc comments for getWorldFeetPosition() in Avatar.h --- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 919a13095f..c6e8ac59f1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -252,7 +252,7 @@ public: /**jsdoc * Get the position of the current avatar's feet (or rather, bottom of its collision capsule) in world coordinates. * @function MyAvatar.getWorldFeetPosition - * @returns {Vec3} The position of the Avatar's feet in world coordinates. + * @returns {Vec3} The position of the avatar's feet in world coordinates. */ Q_INVOKABLE glm::vec3 getWorldFeetPosition(); From a7170a5892c4806ffa4645b8a1daef4b186b6b03 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 8 Aug 2018 08:49:29 +1200 Subject: [PATCH 12/13] Fix typo --- .../controllers/controllerModules/nearParentGrabEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index fe6497ff05..0e379d1a3b 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -328,7 +328,7 @@ Script.include("/~/system/libraries/controllers.js"); if (!props) { // entity was deleted unhighlightTargetEntity(this.targetEntityID); - this.highlightedEntity = NULL; + this.highlightedEntity = null; this.grabbing = false; this.targetEntityID = null; this.hapticTargetID = null; From 32165dff406b20bf474dd5d518971abfdc858de7 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 7 Aug 2018 14:31:48 -0700 Subject: [PATCH 13/13] Fixed rotations in MyAvatar::goToFeetLocation() --- interface/src/avatar/MyAvatar.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5a5d99d6f0..0d7b00da78 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2636,12 +2636,7 @@ void MyAvatar::goToFeetLocation(const glm::vec3& newPosition, glm::vec3 localFeetPos = shapeInfo.getOffset() - glm::vec3(0.0f, halfExtents.y + halfExtents.x, 0.0f); glm::mat4 localFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, localFeetPos); - glm::mat4 worldFeet; - if (hasOrientation) { - worldFeet = createMatFromQuatAndPos(newOrientation, newPosition); - } else { - worldFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, newPosition); - } + glm::mat4 worldFeet = createMatFromQuatAndPos(Quaternions::IDENTITY, newPosition); glm::mat4 avatarMat = worldFeet * glm::inverse(localFeet);