mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 16:14:35 +02:00
sizes and order of IKTargetVarVec and IKTargetVec are now the same.
Also, A change in how the bone name to bone index lookup occurs exposed a bug in Rig::computeAvatarBoundingCapsule(), basically it was not actually preforming IK, and the ik targets were in the wrong coordinate frame. So when IK was actually performed it would give bad results. This bug is now fixed.
This commit is contained in:
parent
75e1a4a1e6
commit
237872e477
4 changed files with 32 additions and 48 deletions
|
@ -150,24 +150,26 @@ void AnimInverseKinematics::setTargetVars(const QString& jointName, const QStrin
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets, const AnimPoseVec& underPoses) {
|
void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets, const AnimPoseVec& underPoses) {
|
||||||
// build a list of valid targets from _targetVarVec and animVars
|
|
||||||
_maxTargetIndex = -1;
|
|
||||||
_hipsTargetIndex = -1;
|
_hipsTargetIndex = -1;
|
||||||
bool removeUnfoundJoints = false;
|
|
||||||
|
targets.reserve(_targetVarVec.size());
|
||||||
|
|
||||||
for (auto& targetVar : _targetVarVec) {
|
for (auto& targetVar : _targetVarVec) {
|
||||||
|
|
||||||
|
// update targetVar jointIndex cache
|
||||||
if (targetVar.jointIndex == -1) {
|
if (targetVar.jointIndex == -1) {
|
||||||
// this targetVar hasn't been validated yet...
|
|
||||||
int jointIndex = _skeleton->nameToJointIndex(targetVar.jointName);
|
int jointIndex = _skeleton->nameToJointIndex(targetVar.jointName);
|
||||||
if (jointIndex >= 0) {
|
if (jointIndex >= 0) {
|
||||||
// this targetVar has a valid joint --> cache the indices
|
// this targetVar has a valid joint --> cache the indices
|
||||||
targetVar.jointIndex = jointIndex;
|
targetVar.jointIndex = jointIndex;
|
||||||
} else {
|
} else {
|
||||||
qCWarning(animation) << "AnimInverseKinematics could not find jointName" << targetVar.jointName << "in skeleton";
|
qCWarning(animation) << "AnimInverseKinematics could not find jointName" << targetVar.jointName << "in skeleton";
|
||||||
removeUnfoundJoints = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
IKTarget target;
|
|
||||||
|
IKTarget target;
|
||||||
|
if (targetVar.jointIndex != -1) {
|
||||||
target.setType(animVars.lookup(targetVar.typeVar, (int)IKTarget::Type::RotationAndPosition));
|
target.setType(animVars.lookup(targetVar.typeVar, (int)IKTarget::Type::RotationAndPosition));
|
||||||
if (target.getType() != IKTarget::Type::Unknown) {
|
if (target.getType() != IKTarget::Type::Unknown) {
|
||||||
AnimPose absPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses);
|
AnimPose absPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses);
|
||||||
|
@ -189,35 +191,16 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
|
||||||
glm::vec3 poleReferenceVector = animVars.lookupRigToGeometryVector(targetVar.poleReferenceVectorVar, Vectors::UNIT_Z);
|
glm::vec3 poleReferenceVector = animVars.lookupRigToGeometryVector(targetVar.poleReferenceVectorVar, Vectors::UNIT_Z);
|
||||||
target.setPoleReferenceVector(glm::normalize(poleReferenceVector));
|
target.setPoleReferenceVector(glm::normalize(poleReferenceVector));
|
||||||
|
|
||||||
targets.push_back(target);
|
|
||||||
|
|
||||||
if (targetVar.jointIndex > _maxTargetIndex) {
|
|
||||||
_maxTargetIndex = targetVar.jointIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// record the index of the hips ik target.
|
// record the index of the hips ik target.
|
||||||
if (target.getIndex() == _hipsIndex) {
|
if (target.getIndex() == _hipsIndex) {
|
||||||
_hipsTargetIndex = (int)targets.size() - 1;
|
_hipsTargetIndex = (int)targets.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
target.setType((int)IKTarget::Type::Unknown);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (removeUnfoundJoints) {
|
targets.push_back(target);
|
||||||
int numVars = (int)_targetVarVec.size();
|
|
||||||
int i = 0;
|
|
||||||
while (i < numVars) {
|
|
||||||
if (_targetVarVec[i].jointIndex == -1) {
|
|
||||||
if (numVars > 1) {
|
|
||||||
// swap i for last element
|
|
||||||
_targetVarVec[i] = _targetVarVec[numVars - 1];
|
|
||||||
}
|
|
||||||
_targetVarVec.pop_back();
|
|
||||||
--numVars;
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,10 +241,15 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
||||||
|
|
||||||
// solve all targets
|
// solve all targets
|
||||||
for (size_t i = 0; i < targets.size(); i++) {
|
for (size_t i = 0; i < targets.size(); i++) {
|
||||||
if (targets[i].getType() == IKTarget::Type::Spline) {
|
switch (targets[i].getType()) {
|
||||||
|
case IKTarget::Type::Unknown:
|
||||||
|
break;
|
||||||
|
case IKTarget::Type::Spline:
|
||||||
solveTargetWithSpline(context, targets[i], absolutePoses, debug, jointChainInfoVec[i]);
|
solveTargetWithSpline(context, targets[i], absolutePoses, debug, jointChainInfoVec[i]);
|
||||||
} else {
|
break;
|
||||||
|
default:
|
||||||
solveTargetWithCCD(context, targets[i], absolutePoses, debug, jointChainInfoVec[i]);
|
solveTargetWithCCD(context, targets[i], absolutePoses, debug, jointChainInfoVec[i]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +305,7 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
||||||
// finally set the relative rotation of each tip to agree with absolute target rotation
|
// finally set the relative rotation of each tip to agree with absolute target rotation
|
||||||
for (auto& target: targets) {
|
for (auto& target: targets) {
|
||||||
int tipIndex = target.getIndex();
|
int tipIndex = target.getIndex();
|
||||||
int parentIndex = _skeleton->getParentIndex(tipIndex);
|
int parentIndex = (tipIndex >= 0) ? _skeleton->getParentIndex(tipIndex) : -1;
|
||||||
|
|
||||||
// update rotationOnly targets that don't lie on the ik chain of other ik targets.
|
// update rotationOnly targets that don't lie on the ik chain of other ik targets.
|
||||||
if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() && target.getType() == IKTarget::Type::RotationOnly) {
|
if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() && target.getType() == IKTarget::Type::RotationOnly) {
|
||||||
|
@ -1430,8 +1418,6 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele
|
||||||
targetVar.jointIndex = -1;
|
targetVar.jointIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_maxTargetIndex = -1;
|
|
||||||
|
|
||||||
for (auto& accumulator: _rotationAccumulators) {
|
for (auto& accumulator: _rotationAccumulators) {
|
||||||
accumulator.clearAndClean();
|
accumulator.clearAndClean();
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,10 +156,6 @@ protected:
|
||||||
int _leftHandIndex { -1 };
|
int _leftHandIndex { -1 };
|
||||||
int _rightHandIndex { -1 };
|
int _rightHandIndex { -1 };
|
||||||
|
|
||||||
// _maxTargetIndex is tracked to help optimize the recalculation of absolute poses
|
|
||||||
// during the the cyclic coordinate descent algorithm
|
|
||||||
int _maxTargetIndex { 0 };
|
|
||||||
|
|
||||||
float _maxErrorOnLastSolve { FLT_MAX };
|
float _maxErrorOnLastSolve { FLT_MAX };
|
||||||
bool _previousEnableDebugIKTargets { false };
|
bool _previousEnableDebugIKTargets { false };
|
||||||
SolutionSource _solutionSource { SolutionSource::RelaxToUnderPoses };
|
SolutionSource _solutionSource { SolutionSource::RelaxToUnderPoses };
|
||||||
|
|
|
@ -57,7 +57,7 @@ private:
|
||||||
bool _poleVectorEnabled { false };
|
bool _poleVectorEnabled { false };
|
||||||
int _index { -1 };
|
int _index { -1 };
|
||||||
Type _type { Type::RotationAndPosition };
|
Type _type { Type::RotationAndPosition };
|
||||||
float _weight;
|
float _weight { 0.0f };
|
||||||
float _flexCoefficients[MAX_FLEX_COEFFICIENTS];
|
float _flexCoefficients[MAX_FLEX_COEFFICIENTS];
|
||||||
size_t _numFlexCoefficients;
|
size_t _numFlexCoefficients;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1707,36 +1707,38 @@ void Rig::computeAvatarBoundingCapsule(
|
||||||
|
|
||||||
AnimPose geometryToRig = _modelOffset * _geometryOffset;
|
AnimPose geometryToRig = _modelOffset * _geometryOffset;
|
||||||
|
|
||||||
AnimPose hips(glm::vec3(1), glm::quat(), glm::vec3());
|
glm::vec3 hipsPosition(0.0f);
|
||||||
int hipsIndex = indexOfJoint("Hips");
|
int hipsIndex = indexOfJoint("Hips");
|
||||||
if (hipsIndex >= 0) {
|
if (hipsIndex >= 0) {
|
||||||
hips = geometryToRig * _animSkeleton->getAbsoluteBindPose(hipsIndex);
|
hipsPosition = transformPoint(_geometryToRigTransform, _animSkeleton->getAbsoluteDefaultPose(hipsIndex).trans());
|
||||||
}
|
}
|
||||||
AnimVariantMap animVars;
|
AnimVariantMap animVars;
|
||||||
|
animVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
||||||
glm::quat handRotation = glm::angleAxis(PI, Vectors::UNIT_X);
|
glm::quat handRotation = glm::angleAxis(PI, Vectors::UNIT_X);
|
||||||
animVars.set("leftHandPosition", hips.trans());
|
animVars.set("leftHandPosition", hipsPosition);
|
||||||
animVars.set("leftHandRotation", handRotation);
|
animVars.set("leftHandRotation", handRotation);
|
||||||
animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
|
animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
animVars.set("rightHandPosition", hips.trans());
|
animVars.set("rightHandPosition", hipsPosition);
|
||||||
animVars.set("rightHandRotation", handRotation);
|
animVars.set("rightHandRotation", handRotation);
|
||||||
animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
|
animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
|
|
||||||
int rightFootIndex = indexOfJoint("RightFoot");
|
int rightFootIndex = indexOfJoint("RightFoot");
|
||||||
int leftFootIndex = indexOfJoint("LeftFoot");
|
int leftFootIndex = indexOfJoint("LeftFoot");
|
||||||
if (rightFootIndex != -1 && leftFootIndex != -1) {
|
if (rightFootIndex != -1 && leftFootIndex != -1) {
|
||||||
glm::vec3 foot = Vectors::ZERO;
|
glm::vec3 geomFootPosition = glm::vec3(0.0f, _animSkeleton->getAbsoluteDefaultPose(rightFootIndex).trans().y, 0.0f);
|
||||||
|
glm::vec3 footPosition = transformPoint(_geometryToRigTransform, geomFootPosition);
|
||||||
glm::quat footRotation = glm::angleAxis(0.5f * PI, Vectors::UNIT_X);
|
glm::quat footRotation = glm::angleAxis(0.5f * PI, Vectors::UNIT_X);
|
||||||
animVars.set("leftFootPosition", foot);
|
animVars.set("leftFootPosition", footPosition);
|
||||||
animVars.set("leftFootRotation", footRotation);
|
animVars.set("leftFootRotation", footRotation);
|
||||||
animVars.set("leftFootType", (int)IKTarget::Type::RotationAndPosition);
|
animVars.set("leftFootType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
animVars.set("rightFootPosition", foot);
|
animVars.set("rightFootPosition", footPosition);
|
||||||
animVars.set("rightFootRotation", footRotation);
|
animVars.set("rightFootRotation", footRotation);
|
||||||
animVars.set("rightFootType", (int)IKTarget::Type::RotationAndPosition);
|
animVars.set("rightFootType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// call overlay twice: once to verify AnimPoseVec joints and again to do the IK
|
// call overlay twice: once to verify AnimPoseVec joints and again to do the IK
|
||||||
AnimNode::Triggers triggersOut;
|
AnimNode::Triggers triggersOut;
|
||||||
AnimContext context(false, false, false, glm::mat4(), glm::mat4());
|
AnimContext context(false, false, false, _geometryToRigTransform, _rigToGeometryTransform);
|
||||||
float dt = 1.0f; // the value of this does not matter
|
float dt = 1.0f; // the value of this does not matter
|
||||||
ikNode.overlay(animVars, context, dt, triggersOut, _animSkeleton->getRelativeBindPoses());
|
ikNode.overlay(animVars, context, dt, triggersOut, _animSkeleton->getRelativeBindPoses());
|
||||||
AnimPoseVec finalPoses = ikNode.overlay(animVars, context, dt, triggersOut, _animSkeleton->getRelativeBindPoses());
|
AnimPoseVec finalPoses = ikNode.overlay(animVars, context, dt, triggersOut, _animSkeleton->getRelativeBindPoses());
|
||||||
|
|
Loading…
Reference in a new issue