From abb632afda72c9b0d2ee966199e9f2d94726309c Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 5 Sep 2018 16:51:34 -0700 Subject: [PATCH] Update capsule when scale/load and teleport without safe landing --- interface/src/avatar/MyAvatar.cpp | 19 +++- interface/src/avatar/MyAvatar.h | 10 +- .../controllers/controllerModules/teleport.js | 100 ++++++++++++++---- 3 files changed, 108 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 640c9821a0..4daa3f5eef 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -113,6 +113,7 @@ MyAvatar::MyAvatar(QThread* thread) : _recentModeReadings(MODE_READINGS_RING_BUFFER_SIZE), _bodySensorMatrix(), _goToPending(false), + _goToSafe(true), _goToPosition(), _goToOrientation(), _prevShouldDrawHead(true), @@ -509,7 +510,9 @@ void MyAvatar::update(float deltaTime) { if (_physicsSafetyPending && qApp->isPhysicsEnabled() && _characterController.isEnabledAndReady()) { // When needed and ready, arrange to check and fix. _physicsSafetyPending = false; - safeLanding(_goToPosition); // no-op if already safe + if (_goToSafe) { + safeLanding(_goToPosition); // no-op if already safe + } } Head* head = getHead(); @@ -3007,7 +3010,7 @@ void MyAvatar::goToFeetLocation(const glm::vec3& newPosition, void MyAvatar::goToLocation(const glm::vec3& newPosition, bool hasOrientation, const glm::quat& newOrientation, - bool shouldFaceLocation) { + bool shouldFaceLocation, bool withSafeLanding) { // Most cases of going to a place or user go through this now. Some possible improvements to think about in the future: // - It would be nice if this used the same teleport steps and smoothing as in the teleport.js script, as long as it @@ -3027,6 +3030,7 @@ void MyAvatar::goToLocation(const glm::vec3& newPosition, _goToPending = true; _goToPosition = newPosition; + _goToSafe = withSafeLanding; _goToOrientation = getWorldOrientation(); if (hasOrientation) { qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - new orientation is " @@ -3299,6 +3303,17 @@ bool MyAvatar::getCollisionsEnabled() { return _characterController.computeCollisionGroup() != BULLET_COLLISION_GROUP_COLLISIONLESS; } +QVariantMap MyAvatar::getCollisionCapsule() { + glm::vec3 start, end; + float radius; + getCapsule(start, end, radius); + QVariantMap capsule; + capsule["start"] = vec3toVariant(start); + capsule["end"] = vec3toVariant(end); + capsule["radius"] = QVariant(radius); + return capsule; +} + void MyAvatar::setCharacterControllerEnabled(bool enabled) { qCDebug(interfaceapp) << "MyAvatar.characterControllerEnabled is deprecated. Use MyAvatar.collisionsEnabled instead."; setCollisionsEnabled(enabled); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8121b99e55..0f7ecedcad 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1017,6 +1017,12 @@ public: */ Q_INVOKABLE bool getCollisionsEnabled(); + /**jsdoc + * @function MyAvatar.getCollisionCapsule + * @returns {object} + */ + Q_INVOKABLE QVariantMap getCollisionCapsule(); + /**jsdoc * @function MyAvatar.setCharacterControllerEnabled * @param {boolean} enabled @@ -1178,11 +1184,12 @@ public slots: * @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 + * @param {boolean} [withSafeLanding=true] - Set to false MyAvatar::safeLanding will not be called (used when teleporting). * the new position and orientate the avatar to face the position. */ void goToLocation(const glm::vec3& newPosition, bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(), - bool shouldFaceLocation = false); + bool shouldFaceLocation = false, bool withSafeLanding = true); /**jsdoc * @function MyAvatar.goToLocation * @param {object} properties @@ -1720,6 +1727,7 @@ private: bool _goToPending { false }; bool _physicsSafetyPending { false }; + bool _goToSafe { true }; glm::vec3 _goToPosition; glm::quat _goToOrientation; diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index c69382a47a..2dea25fc78 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -136,9 +136,7 @@ Script.include("/~/system/libraries/controllers.js"); this.state = TELEPORTER_STATES.IDLE; this.currentTarget = TARGET.INVALID; this.currentResult = null; - this.capsuleHeight = 2.0; - this.capsuleRadius = 0.25; - this.pickHeightOffset = 0.01; + this.capsuleThreshold = 0.05; this.getOtherModule = function() { var otherModule = this.hand === RIGHT_HAND ? leftTeleporter : rightTeleporter; @@ -176,18 +174,38 @@ Script.include("/~/system/libraries/controllers.js"); maxDistance: 8.0 }); - this.teleportCollisionPick = Picks.createPick(PickType.Collision, { - enabled: true, - filter: Picks.PICK_ENTITIES + Picks.PICK_AVATARS, - shape: { - shapeType: "capsule-y", - dimensions: { x: _this.capsuleRadius * 2.0, y: _this.capsuleHeight - (_this.capsuleRadius * 2.0), z: _this.capsuleRadius * 2.0 } - }, - position: { x: 0, y: _this.pickHeightOffset + (_this.capsuleHeight * 0.5), z: 0 }, - parentID: Pointers.getPointerProperties(_this.teleportParabolaHandInvisible).renderStates["invisible"].end, - threshold: 0.05 - }); - + this.teleportCollisionPick; + + this.recreateCollisionPick = function() { + if (_this.teleportCollisionPick !== undefined) { + Picks.removePick(_this.teleportCollisionPick); + } + + var capsuleData = MyAvatar.getCollisionCapsule(); + var capsuleHeight = Vec3.distance(capsuleData.start, capsuleData.end); + var offset = Vec3.distance(Vec3.sum(capsuleData.start, {x: 0, y: 0.5*capsuleHeight, z: 0}), MyAvatar.position); + var radius = capsuleData.radius; + var height = 2.0 * radius + capsuleHeight; + + _this.teleportCollisionPick = Picks.createPick(PickType.Collision, { + enabled: true, + parentID: Pointers.getPointerProperties(_this.teleportParabolaHandInvisible).renderStates["invisible"].end, + filter: Picks.PICK_ENTITIES + Picks.PICK_AVATARS, + shape: { + shapeType: "capsule-y", + dimensions: { + x: radius * 2.0, + y: height - (radius * 2.0), + z: radius * 2.0 + } + }, + position: { x: 0, y: offset + (height * 0.5), z: 0 }, + threshold: _this.capsuleThreshold + }); + } + + _this.recreateCollisionPick(); + this.teleportParabolaHeadVisible = Pointers.createPointer(PickType.Parabola, { joint: "Avatar", filter: Picks.PICK_ENTITIES, @@ -222,8 +240,6 @@ Script.include("/~/system/libraries/controllers.js"); Pointers.removePointer(_this.teleportParabolaHeadInvisible); Picks.removePick(_this.teleportCollisionPick); }; - - // Picks.setIgnoreItems(_this.teleportCollisionPick, []); this.axisButtonStateX = 0; // Left/right axis button pressed. this.axisButtonStateY = 0; // Up/down axis button pressed. @@ -355,7 +371,7 @@ Script.include("/~/system/libraries/controllers.js"); } else if (target === TARGET.SURFACE) { var offset = getAvatarFootOffset(); result.intersection.y += offset; - MyAvatar.goToLocation(result.intersection, true, HMD.orientation, false); + MyAvatar.goToLocation(result.intersection, true, HMD.orientation, false, false); HMD.centerUI(); MyAvatar.centerBody(); } @@ -558,7 +574,55 @@ Script.include("/~/system/libraries/controllers.js"); } } }; + + // This class execute a function after the param value haven't been set for a certain time + // It's used in this case to recreate the collision picks once when the avatar scale process ends + + var AfterSet = function(time, maxsteps, callback) { + var self = this; + this.time = time; + this.callback = callback; + this.init = false; + this.value = 0; + this.interval; + this.maxsteps = maxsteps; + this.steps = 0; + this.restateValue = function(value) { + if (self.steps++ > self.maxsteps) { + self.callback.call(this, self.value); + self.steps = 0; + } + if (!self.init) { + console.log("Starting apply after"); + } + self.init = true; + self.value = value; + if (self.interval !== undefined) { + Script.clearInterval(self.interval); + } + self.interval = Script.setInterval(function() { + self.callback.call(this, self.value); + self.init = false; + Script.clearInterval(self.interval); + self.interval = undefined; + }, self.time); + } + } + + var afterSet = new AfterSet(100, 30, function(value) { + leftTeleporter.recreateCollisionPick(); + rightTeleporter.recreateCollisionPick(); + }); + MyAvatar.onLoadComplete.connect(function () { + leftTeleporter.recreateCollisionPick(); + rightTeleporter.recreateCollisionPick(); + }); + + MyAvatar.sensorToWorldScaleChanged.connect(function() { + afterSet.restateValue(MyAvatar.getSensorToWorldScale()); + }); + Messages.subscribe('Hifi-Teleport-Disabler'); Messages.subscribe('Hifi-Teleport-Ignore-Add'); Messages.subscribe('Hifi-Teleport-Ignore-Remove');