mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Fix for incorrect hand offset when backing into collision.
We know properly account for the offset of the head due to clamping from a small maxHipsOffset. This means the hands should look more natural when you are out-of-body and are moving your hand controllers.
This commit is contained in:
parent
0f60abdf4e
commit
b68dbab994
6 changed files with 32 additions and 10 deletions
|
@ -1378,7 +1378,7 @@ void MyAvatar::harvestResultsFromPhysicsSimulation(float deltaTime) {
|
|||
hipsPosition.z *= -1.0f;
|
||||
maxHipsOffsetRadius = _characterController.measureMaxHipsOffsetRadius(hipsPosition, maxHipsOffsetRadius);
|
||||
}
|
||||
_rig->setMaxHipsOffsetLength(maxHipsOffsetRadius);
|
||||
_rig->updateMaxHipsOffsetLength(maxHipsOffsetRadius, deltaTime);
|
||||
|
||||
glm::vec3 position = getPosition();
|
||||
glm::quat orientation = getOrientation();
|
||||
|
|
|
@ -149,6 +149,17 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
|
||||
_rig->updateFromHeadParameters(headParams, deltaTime);
|
||||
|
||||
// OUTOFBODY_HACK: clamp horizontal component of head by maxHipsOffset.
|
||||
// This is to prevent the hands from being incorrect relative to the head because
|
||||
// the hips are being constrained by a small maxHipsOffset due to collision.
|
||||
if (myAvatar->isOutOfBody()) {
|
||||
float headOffsetLength2D = glm::length(glm::vec2(truncatedHMDPositionInRigSpace.x, truncatedHMDPositionInRigSpace.z));
|
||||
if (headOffsetLength2D > _rig->getMaxHipsOffsetLength()) {
|
||||
truncatedHMDPositionInRigSpace.x *= _rig->getMaxHipsOffsetLength() / headOffsetLength2D;
|
||||
truncatedHMDPositionInRigSpace.z *= _rig->getMaxHipsOffsetLength() / headOffsetLength2D;
|
||||
}
|
||||
}
|
||||
|
||||
Rig::HandParameters handParams;
|
||||
|
||||
auto leftPose = myAvatar->getLeftHandControllerPoseInAvatarFrame();
|
||||
|
|
|
@ -392,10 +392,6 @@ 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 {
|
||||
|
@ -585,7 +581,7 @@ void AnimInverseKinematics::clearIKJointLimitHistory() {
|
|||
void AnimInverseKinematics::setMaxHipsOffsetLength(float maxLength) {
|
||||
// OUTOFBODY_HACK: manually adjust scale here
|
||||
const float METERS_TO_CENTIMETERS = 100.0f;
|
||||
_desiredMaxHipsOffsetLength = METERS_TO_CENTIMETERS * maxLength;
|
||||
_maxHipsOffsetLength = METERS_TO_CENTIMETERS * maxLength;
|
||||
}
|
||||
|
||||
RotationConstraint* AnimInverseKinematics::getConstraint(int index) {
|
||||
|
|
|
@ -85,7 +85,6 @@ 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 };
|
||||
|
|
|
@ -307,18 +307,30 @@ void Rig::clearIKJointLimitHistory() {
|
|||
}
|
||||
}
|
||||
|
||||
void Rig::setMaxHipsOffsetLength(float maxLength) {
|
||||
void Rig::updateMaxHipsOffsetLength(float maxLength, float deltaTime) {
|
||||
|
||||
_desiredMaxHipsOffsetLength = maxLength;
|
||||
|
||||
// OUTOFBODY_HACK: smoothly update update _hipsOffsetLength, otherwise we risk introducing oscillation in the hips offset.
|
||||
const float MAX_HIPS_OFFSET_TIMESCALE = 0.33f;
|
||||
float tau = deltaTime / MAX_HIPS_OFFSET_TIMESCALE;
|
||||
_maxHipsOffsetLength = (1.0f - tau) * _maxHipsOffsetLength + tau * _desiredMaxHipsOffsetLength;
|
||||
|
||||
if (_animNode) {
|
||||
_animNode->traverse([&](AnimNode::Pointer node) {
|
||||
auto ikNode = std::dynamic_pointer_cast<AnimInverseKinematics>(node);
|
||||
if (ikNode) {
|
||||
ikNode->setMaxHipsOffsetLength(maxLength);
|
||||
ikNode->setMaxHipsOffsetLength(_maxHipsOffsetLength);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
float Rig::getMaxHipsOffsetLength() const {
|
||||
return _maxHipsOffsetLength;
|
||||
}
|
||||
|
||||
void Rig::setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority) {
|
||||
if (isIndexValid(index)) {
|
||||
if (valid) {
|
||||
|
|
|
@ -104,7 +104,8 @@ public:
|
|||
void clearJointAnimationPriority(int index);
|
||||
|
||||
void clearIKJointLimitHistory();
|
||||
void setMaxHipsOffsetLength(float maxLength);
|
||||
void updateMaxHipsOffsetLength(float maxLength, float deltaTime);
|
||||
float getMaxHipsOffsetLength() const;
|
||||
|
||||
// geometry space
|
||||
void setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority);
|
||||
|
@ -319,6 +320,9 @@ protected:
|
|||
bool _truncateIKTargets { false };
|
||||
bool _enableDebugDrawIKTargets { false };
|
||||
|
||||
float _maxHipsOffsetLength { 1.0f };
|
||||
float _desiredMaxHipsOffsetLength { 1.0f };
|
||||
|
||||
private:
|
||||
QMap<int, StateHandler> _stateHandlers;
|
||||
int _nextStateHandlerId { 0 };
|
||||
|
|
Loading…
Reference in a new issue