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),
_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);

View file

@ -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 <code>true</code> to set the orientation of 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} [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.
*/
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;

View file

@ -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');