Update capsule when scale/load and teleport without safe landing

This commit is contained in:
luiscuenca 2018-09-05 16:51:34 -07:00
parent 99e6e3d112
commit abb632afda
3 changed files with 108 additions and 21 deletions

View file

@ -113,6 +113,7 @@ MyAvatar::MyAvatar(QThread* thread) :
_recentModeReadings(MODE_READINGS_RING_BUFFER_SIZE), _recentModeReadings(MODE_READINGS_RING_BUFFER_SIZE),
_bodySensorMatrix(), _bodySensorMatrix(),
_goToPending(false), _goToPending(false),
_goToSafe(true),
_goToPosition(), _goToPosition(),
_goToOrientation(), _goToOrientation(),
_prevShouldDrawHead(true), _prevShouldDrawHead(true),
@ -509,7 +510,9 @@ void MyAvatar::update(float deltaTime) {
if (_physicsSafetyPending && qApp->isPhysicsEnabled() && _characterController.isEnabledAndReady()) { if (_physicsSafetyPending && qApp->isPhysicsEnabled() && _characterController.isEnabledAndReady()) {
// When needed and ready, arrange to check and fix. // When needed and ready, arrange to check and fix.
_physicsSafetyPending = false; _physicsSafetyPending = false;
safeLanding(_goToPosition); // no-op if already safe if (_goToSafe) {
safeLanding(_goToPosition); // no-op if already safe
}
} }
Head* head = getHead(); Head* head = getHead();
@ -3007,7 +3010,7 @@ void MyAvatar::goToFeetLocation(const glm::vec3& newPosition,
void MyAvatar::goToLocation(const glm::vec3& newPosition, void MyAvatar::goToLocation(const glm::vec3& newPosition,
bool hasOrientation, const glm::quat& newOrientation, 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: // 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 // - 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; _goToPending = true;
_goToPosition = newPosition; _goToPosition = newPosition;
_goToSafe = withSafeLanding;
_goToOrientation = getWorldOrientation(); _goToOrientation = getWorldOrientation();
if (hasOrientation) { if (hasOrientation) {
qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - new orientation is " qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - new orientation is "
@ -3299,6 +3303,17 @@ bool MyAvatar::getCollisionsEnabled() {
return _characterController.computeCollisionGroup() != BULLET_COLLISION_GROUP_COLLISIONLESS; 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) { void MyAvatar::setCharacterControllerEnabled(bool enabled) {
qCDebug(interfaceapp) << "MyAvatar.characterControllerEnabled is deprecated. Use MyAvatar.collisionsEnabled instead."; qCDebug(interfaceapp) << "MyAvatar.characterControllerEnabled is deprecated. Use MyAvatar.collisionsEnabled instead.";
setCollisionsEnabled(enabled); setCollisionsEnabled(enabled);

View file

@ -1017,6 +1017,12 @@ public:
*/ */
Q_INVOKABLE bool getCollisionsEnabled(); Q_INVOKABLE bool getCollisionsEnabled();
/**jsdoc
* @function MyAvatar.getCollisionCapsule
* @returns {object}
*/
Q_INVOKABLE QVariantMap getCollisionCapsule();
/**jsdoc /**jsdoc
* @function MyAvatar.setCharacterControllerEnabled * @function MyAvatar.setCharacterControllerEnabled
* @param {boolean} enabled * @param {boolean} enabled
@ -1178,11 +1184,12 @@ public slots:
* @param {boolean} [hasOrientation=false] - Set to <code>true</code> to set the orientation of the avatar. * @param {boolean} [hasOrientation=false] - Set to <code>true</code> to set the orientation of the avatar.
* @param {Quat} [orientation=Quat.IDENTITY] - The new orientation for the avatar. * @param {Quat} [orientation=Quat.IDENTITY] - The new orientation for the avatar.
* @param {boolean} [shouldFaceLocation=false] - Set to <code>true</code> to position the avatar a short distance away from * @param {boolean} [shouldFaceLocation=false] - Set to <code>true</code> to position the avatar a short distance away from
* @param {boolean} [withSafeLanding=true] - Set to <code>false</code> MyAvatar::safeLanding will not be called (used when teleporting).
* the new position and orientate the avatar to face the position. * the new position and orientate the avatar to face the position.
*/ */
void goToLocation(const glm::vec3& newPosition, void goToLocation(const glm::vec3& newPosition,
bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(), bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(),
bool shouldFaceLocation = false); bool shouldFaceLocation = false, bool withSafeLanding = true);
/**jsdoc /**jsdoc
* @function MyAvatar.goToLocation * @function MyAvatar.goToLocation
* @param {object} properties * @param {object} properties
@ -1720,6 +1727,7 @@ private:
bool _goToPending { false }; bool _goToPending { false };
bool _physicsSafetyPending { false }; bool _physicsSafetyPending { false };
bool _goToSafe { true };
glm::vec3 _goToPosition; glm::vec3 _goToPosition;
glm::quat _goToOrientation; glm::quat _goToOrientation;

View file

@ -136,9 +136,7 @@ Script.include("/~/system/libraries/controllers.js");
this.state = TELEPORTER_STATES.IDLE; this.state = TELEPORTER_STATES.IDLE;
this.currentTarget = TARGET.INVALID; this.currentTarget = TARGET.INVALID;
this.currentResult = null; this.currentResult = null;
this.capsuleHeight = 2.0; this.capsuleThreshold = 0.05;
this.capsuleRadius = 0.25;
this.pickHeightOffset = 0.01;
this.getOtherModule = function() { this.getOtherModule = function() {
var otherModule = this.hand === RIGHT_HAND ? leftTeleporter : rightTeleporter; var otherModule = this.hand === RIGHT_HAND ? leftTeleporter : rightTeleporter;
@ -176,18 +174,38 @@ Script.include("/~/system/libraries/controllers.js");
maxDistance: 8.0 maxDistance: 8.0
}); });
this.teleportCollisionPick = Picks.createPick(PickType.Collision, { this.teleportCollisionPick;
enabled: true,
filter: Picks.PICK_ENTITIES + Picks.PICK_AVATARS, this.recreateCollisionPick = function() {
shape: { if (_this.teleportCollisionPick !== undefined) {
shapeType: "capsule-y", Picks.removePick(_this.teleportCollisionPick);
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 }, var capsuleData = MyAvatar.getCollisionCapsule();
parentID: Pointers.getPointerProperties(_this.teleportParabolaHandInvisible).renderStates["invisible"].end, var capsuleHeight = Vec3.distance(capsuleData.start, capsuleData.end);
threshold: 0.05 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, { this.teleportParabolaHeadVisible = Pointers.createPointer(PickType.Parabola, {
joint: "Avatar", joint: "Avatar",
filter: Picks.PICK_ENTITIES, filter: Picks.PICK_ENTITIES,
@ -222,8 +240,6 @@ Script.include("/~/system/libraries/controllers.js");
Pointers.removePointer(_this.teleportParabolaHeadInvisible); Pointers.removePointer(_this.teleportParabolaHeadInvisible);
Picks.removePick(_this.teleportCollisionPick); Picks.removePick(_this.teleportCollisionPick);
}; };
// Picks.setIgnoreItems(_this.teleportCollisionPick, []);
this.axisButtonStateX = 0; // Left/right axis button pressed. this.axisButtonStateX = 0; // Left/right axis button pressed.
this.axisButtonStateY = 0; // Up/down 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) { } else if (target === TARGET.SURFACE) {
var offset = getAvatarFootOffset(); var offset = getAvatarFootOffset();
result.intersection.y += offset; result.intersection.y += offset;
MyAvatar.goToLocation(result.intersection, true, HMD.orientation, false); MyAvatar.goToLocation(result.intersection, true, HMD.orientation, false, false);
HMD.centerUI(); HMD.centerUI();
MyAvatar.centerBody(); 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-Disabler');
Messages.subscribe('Hifi-Teleport-Ignore-Add'); Messages.subscribe('Hifi-Teleport-Ignore-Add');
Messages.subscribe('Hifi-Teleport-Ignore-Remove'); Messages.subscribe('Hifi-Teleport-Ignore-Remove');