mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +02:00
Merge pull request #8632 from hyperlogic/out-of-body-experience
MyAvatar.addThrust() works again.
This commit is contained in:
commit
e27ee050bf
4 changed files with 30 additions and 15 deletions
|
@ -1336,8 +1336,7 @@ void MyAvatar::updateMotors() {
|
|||
|
||||
// legacy support for 'MyAvatar::applyThrust()', which has always been implemented as a
|
||||
// short-lived linearAcceleration
|
||||
_characterController.setLinearAcceleration(_thrust);
|
||||
_thrust = Vectors::ZERO;
|
||||
_characterController.setLinearAcceleration(glm::vec3(0.0f, _thrust.y, 0.0f));
|
||||
}
|
||||
|
||||
void MyAvatar::prepareForPhysicsSimulation() {
|
||||
|
@ -1867,9 +1866,15 @@ void MyAvatar::updatePosition(float deltaTime) {
|
|||
worldVelocity = motorRotation * _scriptedMotorVelocity;
|
||||
applyVelocityToSensorToWorldMatrix(worldVelocity, deltaTime);
|
||||
}
|
||||
|
||||
// OUTOFBODY_HACK: apply scaling factor to _thrust, to get the same behavior as an periodically applied motor.
|
||||
const float THRUST_DAMPING_FACTOR = 0.25f;
|
||||
applyVelocityToSensorToWorldMatrix(THRUST_DAMPING_FACTOR * _thrust, deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
_thrust = Vectors::ZERO;
|
||||
|
||||
// capture the head rotation, in sensor space, when the user first indicates they would like to move/fly.
|
||||
if (!_hoverReferenceCameraFacingIsCaptured && (fabs(_driveKeys[TRANSLATE_Z]) > 0.1f || fabs(_driveKeys[TRANSLATE_X]) > 0.1f)) {
|
||||
_hoverReferenceCameraFacingIsCaptured = true;
|
||||
|
|
|
@ -392,6 +392,10 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
|||
dt = MAX_OVERLAY_DT;
|
||||
}
|
||||
|
||||
// OUTOFBODY_HACK: smoothly update update _hipsOffsetLength, otherwise we risk introducing oscillation in the hips offset.
|
||||
float tau = dt / 0.5f;
|
||||
_maxHipsOffsetLength = (1.0f - tau) * _maxHipsOffsetLength + tau * _desiredMaxHipsOffsetLength;
|
||||
|
||||
if (_relativePoses.size() != underPoses.size()) {
|
||||
loadPoses(underPoses);
|
||||
} else {
|
||||
|
@ -516,7 +520,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
|||
float OTHER_WEIGHT = 1.0f;
|
||||
float totalWeight = 0.0f;
|
||||
|
||||
glm::vec3 newHipsOffset = Vectors::ZERO;
|
||||
glm::vec3 additionalHipsOffset = Vectors::ZERO;
|
||||
for (auto& target: targets) {
|
||||
int targetIndex = target.getIndex();
|
||||
if (targetIndex == _headIndex && _headIndex != -1) {
|
||||
|
@ -527,43 +531,45 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
|||
glm::vec3 under = _skeleton->getAbsolutePose(_headIndex, underPoses).trans;
|
||||
glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans;
|
||||
const float HEAD_OFFSET_SLAVE_FACTOR = 0.65f;
|
||||
newHipsOffset += (OTHER_WEIGHT * HEAD_OFFSET_SLAVE_FACTOR) * (actual - under);
|
||||
additionalHipsOffset += (OTHER_WEIGHT * HEAD_OFFSET_SLAVE_FACTOR) * (actual - under);
|
||||
totalWeight += OTHER_WEIGHT;
|
||||
} else if (target.getType() == IKTarget::Type::HmdHead) {
|
||||
glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans;
|
||||
glm::vec3 thisOffset = target.getTranslation() - actual;
|
||||
glm::vec3 futureHipsOffset = _hipsOffset + thisOffset;
|
||||
if (glm::length(futureHipsOffset) < _maxHipsOffsetLength) {
|
||||
if (glm::length(glm::vec2(futureHipsOffset.x, futureHipsOffset.z)) < _maxHipsOffsetLength) {
|
||||
// it is imperative to shift the hips and bring the head to its designated position
|
||||
// so we slam newHipsOffset here and ignore all other targets
|
||||
newHipsOffset = futureHipsOffset;
|
||||
additionalHipsOffset = futureHipsOffset - _hipsOffset;
|
||||
totalWeight = 0.0f;
|
||||
break;
|
||||
} else {
|
||||
newHipsOffset += HMD_WEIGHT * (target.getTranslation() - actual);
|
||||
additionalHipsOffset += HMD_WEIGHT * (target.getTranslation() - actual);
|
||||
totalWeight += HMD_WEIGHT;
|
||||
}
|
||||
}
|
||||
} else if (target.getType() == IKTarget::Type::RotationAndPosition) {
|
||||
glm::vec3 actualPosition = _skeleton->getAbsolutePose(targetIndex, _relativePoses).trans;
|
||||
glm::vec3 targetPosition = target.getTranslation();
|
||||
newHipsOffset += OTHER_WEIGHT * (targetPosition - actualPosition);
|
||||
additionalHipsOffset += OTHER_WEIGHT * (targetPosition - actualPosition);
|
||||
totalWeight += OTHER_WEIGHT;
|
||||
}
|
||||
}
|
||||
if (totalWeight > 1.0f) {
|
||||
newHipsOffset /= totalWeight;
|
||||
additionalHipsOffset /= totalWeight;
|
||||
}
|
||||
|
||||
// smooth transitions by relaxing _hipsOffset toward the new value
|
||||
const float HIPS_OFFSET_SLAVE_TIMESCALE = 0.10f;
|
||||
float tau = dt < HIPS_OFFSET_SLAVE_TIMESCALE ? dt / HIPS_OFFSET_SLAVE_TIMESCALE : 1.0f;
|
||||
float newOffsetLength = glm::length(newHipsOffset);
|
||||
if (newOffsetLength > _maxHipsOffsetLength) {
|
||||
// clamp the hips offset
|
||||
newHipsOffset *= _maxHipsOffsetLength / newOffsetLength;
|
||||
_hipsOffset += additionalHipsOffset * tau;
|
||||
|
||||
// clamp the horizontal component of the hips offset
|
||||
float hipsOffsetLength2D = glm::length(glm::vec2(_hipsOffset.x, _hipsOffset.z));
|
||||
if (hipsOffsetLength2D > _maxHipsOffsetLength) {
|
||||
_hipsOffset.x *= _maxHipsOffsetLength / hipsOffsetLength2D;
|
||||
_hipsOffset.z *= _maxHipsOffsetLength / hipsOffsetLength2D;
|
||||
}
|
||||
_hipsOffset += (newHipsOffset - _hipsOffset) * tau;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +585,7 @@ void AnimInverseKinematics::clearIKJointLimitHistory() {
|
|||
void AnimInverseKinematics::setMaxHipsOffsetLength(float maxLength) {
|
||||
// OUTOFBODY_HACK: manually adjust scale here
|
||||
const float METERS_TO_CENTIMETERS = 100.0f;
|
||||
_maxHipsOffsetLength = METERS_TO_CENTIMETERS * maxLength;
|
||||
_desiredMaxHipsOffsetLength = METERS_TO_CENTIMETERS * maxLength;
|
||||
}
|
||||
|
||||
RotationConstraint* AnimInverseKinematics::getConstraint(int index) {
|
||||
|
|
|
@ -85,6 +85,7 @@ protected:
|
|||
|
||||
// experimental data for moving hips during IK
|
||||
glm::vec3 _hipsOffset { Vectors::ZERO };
|
||||
float _desiredMaxHipsOffsetLength { 1.0f };
|
||||
float _maxHipsOffsetLength { 1.0f };
|
||||
int _headIndex { -1 };
|
||||
int _hipsIndex { -1 };
|
||||
|
|
|
@ -733,6 +733,9 @@ float CharacterController::measureMaxHipsOffsetRadius(const glm::vec3& currentHi
|
|||
startTransform.setOrigin(startPos);
|
||||
btVector3 endPos = startPos + rotation * ((maxSweepDistance / hipsOffsetLength) * hipsOffset);
|
||||
|
||||
// ensure sweep is horizontal.
|
||||
startPos.setY(endPos.getY());
|
||||
|
||||
// sweep test a sphere
|
||||
btSphereShape sphere(_radius);
|
||||
CharacterSweepResult result(&_ghost);
|
||||
|
|
Loading…
Reference in a new issue