mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 04:57:23 +02:00
Merge pull request #5944 from AndrewMeadows/ik-repairs-007
fix bug: IK attenuates fast underpose animations
This commit is contained in:
commit
739545794f
4 changed files with 43 additions and 28 deletions
|
@ -26,13 +26,14 @@
|
||||||
{
|
{
|
||||||
"jointName": "Neck",
|
"jointName": "Neck",
|
||||||
"positionVar": "neckPosition",
|
"positionVar": "neckPosition",
|
||||||
"rotationVar": "neckRotation"
|
"rotationVar": "neckRotation",
|
||||||
|
"typeVar": "headAndNeckType"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "Head",
|
"jointName": "Head",
|
||||||
"positionVar": "headPosition",
|
"positionVar": "headPosition",
|
||||||
"rotationVar": "headRotation",
|
"rotationVar": "headRotation",
|
||||||
"typeVar": "headType"
|
"typeVar": "headAndNeckType"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -89,7 +89,7 @@ static int findRootJointInSkeleton(AnimSkeleton::ConstPointer skeleton, int inde
|
||||||
return rootIndex;
|
return rootIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets) {
|
void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets, const AnimPoseVec& underPoses) {
|
||||||
// build a list of valid targets from _targetVarVec and animVars
|
// build a list of valid targets from _targetVarVec and animVars
|
||||||
_maxTargetIndex = -1;
|
_maxTargetIndex = -1;
|
||||||
bool removeUnfoundJoints = false;
|
bool removeUnfoundJoints = false;
|
||||||
|
@ -107,7 +107,7 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IKTarget target;
|
IKTarget target;
|
||||||
AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, _relativePoses);
|
AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses);
|
||||||
target.pose.trans = animVars.lookup(targetVar.positionVar, defaultPose.trans);
|
target.pose.trans = animVars.lookup(targetVar.positionVar, defaultPose.trans);
|
||||||
target.pose.rot = animVars.lookup(targetVar.rotationVar, defaultPose.rot);
|
target.pose.rot = animVars.lookup(targetVar.rotationVar, defaultPose.rot);
|
||||||
target.setType(animVars.lookup(targetVar.typeVar, QString("")));
|
target.setType(animVars.lookup(targetVar.typeVar, QString("")));
|
||||||
|
@ -154,7 +154,6 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
do {
|
do {
|
||||||
int lowestMovedIndex = _relativePoses.size();
|
int lowestMovedIndex = _relativePoses.size();
|
||||||
for (auto& target: targets) {
|
for (auto& target: targets) {
|
||||||
int tipIndex = target.index;
|
|
||||||
if (target.type == IKTarget::Type::RotationOnly) {
|
if (target.type == IKTarget::Type::RotationOnly) {
|
||||||
// the final rotation will be enforced after the iterations
|
// the final rotation will be enforced after the iterations
|
||||||
continue;
|
continue;
|
||||||
|
@ -162,6 +161,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
AnimPose targetPose = target.pose;
|
AnimPose targetPose = target.pose;
|
||||||
|
|
||||||
// cache tip absolute transform
|
// cache tip absolute transform
|
||||||
|
int tipIndex = target.index;
|
||||||
glm::vec3 tipPosition = absolutePoses[tipIndex].trans;
|
glm::vec3 tipPosition = absolutePoses[tipIndex].trans;
|
||||||
glm::quat tipRotation = absolutePoses[tipIndex].rot;
|
glm::quat tipRotation = absolutePoses[tipIndex].rot;
|
||||||
|
|
||||||
|
@ -288,6 +288,17 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
}
|
}
|
||||||
} while (numLoops < MAX_IK_LOOPS);
|
} while (numLoops < MAX_IK_LOOPS);
|
||||||
|
|
||||||
|
/* KEEP: example code for measuring endeffector error of IK solution
|
||||||
|
for (uint32_t i = 0; i < targets.size(); ++i) {
|
||||||
|
auto& target = targets[i];
|
||||||
|
if (target.type == IKTarget::Type::RotationOnly) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
glm::vec3 tipPosition = absolutePoses[target.index].trans;
|
||||||
|
std::cout << i << " IK error = " << glm::distance(tipPosition, target.pose.trans) << std::endl; // adebug
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// 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.index;
|
int tipIndex = target.index;
|
||||||
|
@ -312,25 +323,8 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
|
||||||
|
|
||||||
//virtual
|
//virtual
|
||||||
const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVars, float dt, AnimNode::Triggers& triggersOut) {
|
const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVars, float dt, AnimNode::Triggers& triggersOut) {
|
||||||
if (!_relativePoses.empty()) {
|
// don't call this function, call overlay() instead
|
||||||
// build a list of targets from _targetVarVec
|
assert(false);
|
||||||
std::vector<IKTarget> targets;
|
|
||||||
computeTargets(animVars, targets);
|
|
||||||
|
|
||||||
if (targets.empty()) {
|
|
||||||
// no IK targets but still need to enforce constraints
|
|
||||||
std::map<int, RotationConstraint*>::iterator constraintItr = _constraints.begin();
|
|
||||||
while (constraintItr != _constraints.end()) {
|
|
||||||
int index = constraintItr->first;
|
|
||||||
glm::quat rotation = _relativePoses[index].rot;
|
|
||||||
constraintItr->second->apply(rotation);
|
|
||||||
_relativePoses[index].rot = rotation;
|
|
||||||
++constraintItr;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
solveWithCyclicCoordinateDescent(targets);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _relativePoses;
|
return _relativePoses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +350,27 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return evaluate(animVars, dt, triggersOut);
|
|
||||||
|
if (!_relativePoses.empty()) {
|
||||||
|
// build a list of targets from _targetVarVec
|
||||||
|
std::vector<IKTarget> targets;
|
||||||
|
computeTargets(animVars, targets, underPoses);
|
||||||
|
|
||||||
|
if (targets.empty()) {
|
||||||
|
// no IK targets but still need to enforce constraints
|
||||||
|
std::map<int, RotationConstraint*>::iterator constraintItr = _constraints.begin();
|
||||||
|
while (constraintItr != _constraints.end()) {
|
||||||
|
int index = constraintItr->first;
|
||||||
|
glm::quat rotation = _relativePoses[index].rot;
|
||||||
|
constraintItr->second->apply(rotation);
|
||||||
|
_relativePoses[index].rot = rotation;
|
||||||
|
++constraintItr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
solveWithCyclicCoordinateDescent(targets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _relativePoses;
|
||||||
}
|
}
|
||||||
|
|
||||||
RotationConstraint* AnimInverseKinematics::getConstraint(int index) {
|
RotationConstraint* AnimInverseKinematics::getConstraint(int index) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ protected:
|
||||||
void setType(const QString& typeVar) { type = ((typeVar == "RotationOnly") ? Type::RotationOnly : Type::RotationAndPosition); }
|
void setType(const QString& typeVar) { type = ((typeVar == "RotationOnly") ? Type::RotationOnly : Type::RotationAndPosition); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets);
|
void computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets, const AnimPoseVec& underPoses);
|
||||||
void solveWithCyclicCoordinateDescent(const std::vector<IKTarget>& targets);
|
void solveWithCyclicCoordinateDescent(const std::vector<IKTarget>& targets);
|
||||||
virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton);
|
virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton);
|
||||||
|
|
||||||
|
|
|
@ -1088,7 +1088,7 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) {
|
||||||
|
|
||||||
_animVars.set("headPosition", headPos);
|
_animVars.set("headPosition", headPos);
|
||||||
_animVars.set("headRotation", headRot);
|
_animVars.set("headRotation", headRot);
|
||||||
_animVars.set("headType", QString("RotationAndPosition"));
|
_animVars.set("headAndNeckType", QString("RotationAndPosition"));
|
||||||
_animVars.set("neckPosition", neckPos);
|
_animVars.set("neckPosition", neckPos);
|
||||||
_animVars.set("neckRotation", neckRot);
|
_animVars.set("neckRotation", neckRot);
|
||||||
|
|
||||||
|
@ -1101,7 +1101,7 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) {
|
||||||
|
|
||||||
_animVars.unset("headPosition");
|
_animVars.unset("headPosition");
|
||||||
_animVars.set("headRotation", realLocalHeadOrientation);
|
_animVars.set("headRotation", realLocalHeadOrientation);
|
||||||
_animVars.set("headType", QString("RotationOnly"));
|
_animVars.set("headAndNeckType", QString("RotationOnly"));
|
||||||
_animVars.unset("neckPosition");
|
_animVars.unset("neckPosition");
|
||||||
_animVars.unset("neckRotation");
|
_animVars.unset("neckRotation");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue