mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 21:43:03 +02:00
Merge pull request #5798 from AndrewMeadows/minor-ik-tuning
minor tuning of IK behavior
This commit is contained in:
commit
7a843b3610
1 changed files with 7 additions and 27 deletions
|
@ -149,28 +149,6 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
||||||
|
|
||||||
glm::vec3 tip = absolutePoses[tipIndex].trans;
|
glm::vec3 tip = absolutePoses[tipIndex].trans;
|
||||||
float error = glm::length(targetPose.trans - tip);
|
float error = glm::length(targetPose.trans - tip);
|
||||||
if (error < ACCEPTABLE_RELATIVE_ERROR) {
|
|
||||||
if (largestError < error) {
|
|
||||||
largestError = error;
|
|
||||||
}
|
|
||||||
// this targetPose has been met
|
|
||||||
// finally set the relative rotation of the tip to agree with absolute target rotation
|
|
||||||
int parentIndex = _skeleton->getParentIndex(tipIndex);
|
|
||||||
if (parentIndex != -1) {
|
|
||||||
// compute tip's new parent-relative rotation
|
|
||||||
// Q = Qp * q --> q' = Qp^ * Q
|
|
||||||
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot) * targetPose.rot;
|
|
||||||
RotationConstraint* constraint = getConstraint(tipIndex);
|
|
||||||
if (constraint) {
|
|
||||||
constraint->apply(newRelativeRotation);
|
|
||||||
// TODO: ATM the final rotation target may fails but we need to provide
|
|
||||||
// feedback to the IK system so that it can adjust the bones up the skeleton
|
|
||||||
// to help this rotation target get met.
|
|
||||||
}
|
|
||||||
_relativePoses[tipIndex].rot = newRelativeRotation;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// descend toward root, rotating each joint to get tip closer to target
|
// descend toward root, rotating each joint to get tip closer to target
|
||||||
int index = _skeleton->getParentIndex(tipIndex);
|
int index = _skeleton->getParentIndex(tipIndex);
|
||||||
|
@ -191,6 +169,8 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
||||||
// NOTE: even when axisLength is not zero (e.g. lever-arm and pivot-arm are not quite aligned) it is
|
// NOTE: even when axisLength is not zero (e.g. lever-arm and pivot-arm are not quite aligned) it is
|
||||||
// still possible for the angle to be zero so we also check that to avoid unnecessary calculations.
|
// still possible for the angle to be zero so we also check that to avoid unnecessary calculations.
|
||||||
if (angle > EPSILON) {
|
if (angle > EPSILON) {
|
||||||
|
// reduce angle by half: slows convergence but adds stability to IK solution
|
||||||
|
angle = 0.5f * angle;
|
||||||
glm::quat deltaRotation = glm::angleAxis(angle, axis);
|
glm::quat deltaRotation = glm::angleAxis(angle, axis);
|
||||||
|
|
||||||
int parentIndex = _skeleton->getParentIndex(index);
|
int parentIndex = _skeleton->getParentIndex(index);
|
||||||
|
@ -268,7 +248,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
||||||
loadPoses(underPoses);
|
loadPoses(underPoses);
|
||||||
} else {
|
} else {
|
||||||
// relax toward underpose
|
// relax toward underpose
|
||||||
const float RELAXATION_TIMESCALE = 0.25f;
|
const float RELAXATION_TIMESCALE = 0.125f;
|
||||||
const float alpha = glm::clamp(dt / RELAXATION_TIMESCALE, 0.0f, 1.0f);
|
const float alpha = glm::clamp(dt / RELAXATION_TIMESCALE, 0.0f, 1.0f);
|
||||||
int numJoints = (int)_relativePoses.size();
|
int numJoints = (int)_relativePoses.size();
|
||||||
for (int i = 0; i < numJoints; ++i) {
|
for (int i = 0; i < numJoints; ++i) {
|
||||||
|
@ -342,7 +322,7 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
// compute corresponding absolute poses
|
// compute corresponding absolute poses
|
||||||
int numJoints = (int)_defaultRelativePoses.size();
|
int numJoints = (int)_defaultRelativePoses.size();
|
||||||
AnimPoseVec absolutePoses;
|
AnimPoseVec absolutePoses;
|
||||||
absolutePoses.reserve(numJoints);
|
absolutePoses.resize(numJoints);
|
||||||
for (int i = 0; i < numJoints; ++i) {
|
for (int i = 0; i < numJoints; ++i) {
|
||||||
int parentIndex = _skeleton->getParentIndex(i);
|
int parentIndex = _skeleton->getParentIndex(i);
|
||||||
if (parentIndex < 0) {
|
if (parentIndex < 0) {
|
||||||
|
@ -467,11 +447,11 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
} else if (baseName.startsWith("Shoulder", Qt::CaseInsensitive)) {
|
} else if (baseName.startsWith("Shoulder", Qt::CaseInsensitive)) {
|
||||||
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
|
||||||
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot);
|
||||||
const float MAX_SHOULDER_TWIST = PI / 8.0f;
|
const float MAX_SHOULDER_TWIST = PI / 20.0f;
|
||||||
stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST);
|
stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST);
|
||||||
|
|
||||||
std::vector<float> minDots;
|
std::vector<float> minDots;
|
||||||
const float MAX_SHOULDER_SWING = PI / 14.0f;
|
const float MAX_SHOULDER_SWING = PI / 20.0f;
|
||||||
minDots.push_back(cosf(MAX_SHOULDER_SWING));
|
minDots.push_back(cosf(MAX_SHOULDER_SWING));
|
||||||
stConstraint->setSwingLimits(minDots);
|
stConstraint->setSwingLimits(minDots);
|
||||||
|
|
||||||
|
@ -509,7 +489,7 @@ void AnimInverseKinematics::initConstraints() {
|
||||||
// we determine the max/min angles by rotating the swing limit lines from parent- to child-frame
|
// we determine the max/min angles by rotating the swing limit lines from parent- to child-frame
|
||||||
// then measure the angles to swing the yAxis into alignment
|
// then measure the angles to swing the yAxis into alignment
|
||||||
glm::vec3 hingeAxis = - mirror * zAxis;
|
glm::vec3 hingeAxis = - mirror * zAxis;
|
||||||
const float MIN_ELBOW_ANGLE = 0.0f;
|
const float MIN_ELBOW_ANGLE = 0.05f;
|
||||||
const float MAX_ELBOW_ANGLE = 11.0f * PI / 12.0f;
|
const float MAX_ELBOW_ANGLE = 11.0f * PI / 12.0f;
|
||||||
glm::quat invReferenceRotation = glm::inverse(referenceRotation);
|
glm::quat invReferenceRotation = glm::inverse(referenceRotation);
|
||||||
glm::vec3 minSwingAxis = invReferenceRotation * glm::angleAxis(MIN_ELBOW_ANGLE, hingeAxis) * yAxis;
|
glm::vec3 minSwingAxis = invReferenceRotation * glm::angleAxis(MIN_ELBOW_ANGLE, hingeAxis) * yAxis;
|
||||||
|
|
Loading…
Reference in a new issue