mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-07 03:32:42 +02:00
Merge pull request #1066 from vircadia/fix/crash-avi-ik
Fix AnimInverseKinematics crash
This commit is contained in:
commit
3f97b4da13
3 changed files with 38 additions and 35 deletions
|
@ -22,6 +22,7 @@
|
|||
#include "AnimationLogging.h"
|
||||
#include "CubicHermiteSpline.h"
|
||||
#include "AnimUtil.h"
|
||||
#include "AnimSkeleton.h"
|
||||
|
||||
static const int MAX_TARGET_MARKERS = 30;
|
||||
static const float JOINT_CHAIN_INTERP_TIME = 0.5f;
|
||||
|
@ -66,7 +67,7 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, cons
|
|||
poleVectorVar(poleVectorVarIn),
|
||||
weight(weightIn),
|
||||
numFlexCoefficients(flexCoefficientsIn.size()),
|
||||
jointIndex(-1)
|
||||
jointIndex(AnimSkeleton::INVALID_JOINT_INDEX)
|
||||
{
|
||||
numFlexCoefficients = std::min(numFlexCoefficients, (size_t)MAX_FLEX_COEFFICIENTS);
|
||||
for (size_t i = 0; i < numFlexCoefficients; i++) {
|
||||
|
@ -172,14 +173,14 @@ bool debounceJointWarnings() {
|
|||
|
||||
void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets, const AnimPoseVec& underPoses) {
|
||||
|
||||
_hipsTargetIndex = -1;
|
||||
_hipsTargetIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
|
||||
targets.reserve(_targetVarVec.size());
|
||||
|
||||
for (auto& targetVar : _targetVarVec) {
|
||||
|
||||
// update targetVar jointIndex cache
|
||||
if (targetVar.jointIndex == -1) {
|
||||
if (targetVar.jointIndex == AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
int jointIndex = _skeleton->nameToJointIndex(targetVar.jointName);
|
||||
if (jointIndex >= 0) {
|
||||
// this targetVar has a valid joint --> cache the indices
|
||||
|
@ -190,7 +191,7 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
|
|||
}
|
||||
|
||||
IKTarget target;
|
||||
if (targetVar.jointIndex != -1) {
|
||||
if (targetVar.jointIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
target.setType(animVars.lookup(targetVar.typeVar, (int)IKTarget::Type::RotationAndPosition));
|
||||
target.setIndex(targetVar.jointIndex);
|
||||
if (target.getType() != IKTarget::Type::Unknown) {
|
||||
|
@ -329,7 +330,7 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
|||
// update the absolutePoses
|
||||
for (int i = 0; i < (int)_relativePoses.size(); ++i) {
|
||||
auto parentIndex = _skeleton->getParentIndex((int)i);
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
absolutePoses[i] = absolutePoses[parentIndex] * _relativePoses[i];
|
||||
}
|
||||
}
|
||||
|
@ -351,12 +352,12 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector<
|
|||
// finally set the relative rotation of each tip to agree with absolute target rotation
|
||||
for (auto& target: targets) {
|
||||
int tipIndex = target.getIndex();
|
||||
int parentIndex = (tipIndex >= 0) ? _skeleton->getParentIndex(tipIndex) : -1;
|
||||
int parentIndex = (tipIndex >= 0) ? _skeleton->getParentIndex(tipIndex) : AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
int chainIndex = targetToChainMap[tipIndex];
|
||||
bool needsInterpolation = _prevJointChainInfoVec[chainIndex].timer > 0.0f;
|
||||
float alpha = needsInterpolation ? getInterpolationAlpha(_prevJointChainInfoVec[chainIndex].timer) : 0.0f;
|
||||
// update rotationOnly targets that don't lie on the ik chain of other ik targets.
|
||||
if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() &&
|
||||
if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX && !_rotationAccumulators[tipIndex].isDirty() &&
|
||||
(target.getType() == IKTarget::Type::RotationOnly || target.getType() == IKTarget::Type::Unknown)) {
|
||||
if (target.getType() == IKTarget::Type::RotationOnly) {
|
||||
const glm::quat& targetRotation = target.getRotation();
|
||||
|
@ -434,11 +435,11 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
|
|||
|
||||
int tipIndex = target.getIndex();
|
||||
int pivotIndex = _skeleton->getParentIndex(tipIndex);
|
||||
if (pivotIndex == -1 || pivotIndex == _hipsIndex) {
|
||||
if (pivotIndex == AnimSkeleton::INVALID_JOINT_INDEX || pivotIndex == _hipsIndex) {
|
||||
return;
|
||||
}
|
||||
int pivotsParentIndex = _skeleton->getParentIndex(pivotIndex);
|
||||
if (pivotsParentIndex == -1) {
|
||||
if (pivotsParentIndex == AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
// TODO?: handle case where tip's parent is root?
|
||||
return;
|
||||
}
|
||||
|
@ -485,7 +486,7 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
|
|||
chainDepth++;
|
||||
|
||||
// descend toward root, pivoting each joint to get tip closer to target position
|
||||
while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) {
|
||||
while (pivotIndex != _hipsIndex && pivotsParentIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
|
||||
assert(chainDepth < jointChainInfoOut.jointInfoVec.size());
|
||||
|
||||
|
@ -579,12 +580,12 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
|
|||
if (target.getPoleVectorEnabled()) {
|
||||
int topJointIndex = target.getIndex();
|
||||
int midJointIndex = _skeleton->getParentIndex(topJointIndex);
|
||||
if (midJointIndex != -1) {
|
||||
if (midJointIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
int baseJointIndex = _skeleton->getParentIndex(midJointIndex);
|
||||
if (baseJointIndex != -1) {
|
||||
if (baseJointIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
int baseParentJointIndex = _skeleton->getParentIndex(baseJointIndex);
|
||||
AnimPose topPose, midPose, basePose;
|
||||
int topChainIndex = -1, baseChainIndex = -1;
|
||||
int topChainIndex = AnimSkeleton::INVALID_JOINT_INDEX, baseChainIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
const size_t MAX_CHAIN_DEPTH = 30;
|
||||
AnimPose postAbsPoses[MAX_CHAIN_DEPTH];
|
||||
AnimPose accum = absolutePoses[_hipsIndex];
|
||||
|
@ -756,7 +757,7 @@ void AnimInverseKinematics::computeAndCacheSplineJointInfosForIKTarget(const Ani
|
|||
|
||||
int index = target.getIndex();
|
||||
int endIndex = _skeleton->getParentIndex(_hipsIndex);
|
||||
while (index != endIndex) {
|
||||
while (index != endIndex && index != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
AnimPose defaultPose = _skeleton->getAbsoluteDefaultPose(index);
|
||||
|
||||
float ratio = glm::dot(defaultPose.trans() - basePose.trans(), baseToTipNormal) / baseToTipLength;
|
||||
|
@ -1460,7 +1461,7 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele
|
|||
|
||||
// invalidate all targetVars
|
||||
for (auto& targetVar: _targetVarVec) {
|
||||
targetVar.jointIndex = -1;
|
||||
targetVar.jointIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
}
|
||||
|
||||
for (auto& accumulator: _rotationAccumulators) {
|
||||
|
@ -1480,18 +1481,18 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele
|
|||
if (_hipsIndex >= 0) {
|
||||
_hipsParentIndex = _skeleton->getParentIndex(_hipsIndex);
|
||||
} else {
|
||||
_hipsParentIndex = -1;
|
||||
_hipsParentIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
}
|
||||
|
||||
_leftHandIndex = _skeleton->nameToJointIndex("LeftHand");
|
||||
_rightHandIndex = _skeleton->nameToJointIndex("RightHand");
|
||||
} else {
|
||||
clearConstraints();
|
||||
_headIndex = -1;
|
||||
_hipsIndex = -1;
|
||||
_hipsParentIndex = -1;
|
||||
_leftHandIndex = -1;
|
||||
_rightHandIndex = -1;
|
||||
_headIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
_hipsIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
_hipsParentIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
_leftHandIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
_rightHandIndex = AnimSkeleton::INVALID_JOINT_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1531,7 +1532,7 @@ void AnimInverseKinematics::debugDrawRelativePoses(const AnimContext& context) c
|
|||
|
||||
// draw line to parent
|
||||
int parentIndex = _skeleton->getParentIndex(i);
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
glm::vec3 parentPos = transformPoint(geomToWorldMatrix, poses[parentIndex].trans());
|
||||
DebugDraw::getInstance().drawRay(pos, parentPos, GRAY);
|
||||
}
|
||||
|
@ -1580,7 +1581,7 @@ void AnimInverseKinematics::debugDrawIKChain(const JointChainInfo& jointChainInf
|
|||
DebugDraw::getInstance().drawRay(pos, pos + AXIS_LENGTH * zAxis, BLUE);
|
||||
|
||||
// draw line to parent
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
glm::vec3 parentPos = transformPoint(geomToWorldMatrix, poses[parentIndex].trans());
|
||||
glm::vec4 color = GRAY;
|
||||
|
||||
|
@ -1629,13 +1630,13 @@ void AnimInverseKinematics::debugDrawConstraints(const AnimContext& context) con
|
|||
|
||||
// draw line to parent
|
||||
int parentIndex = _skeleton->getParentIndex(i);
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
glm::vec3 parentPos = transformPoint(geomToWorldMatrix, poses[parentIndex].trans());
|
||||
DebugDraw::getInstance().drawRay(pos, parentPos, GRAY);
|
||||
}
|
||||
|
||||
glm::quat parentAbsRot;
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) {
|
||||
parentAbsRot = poses[parentIndex].rot();
|
||||
}
|
||||
|
||||
|
@ -1733,7 +1734,7 @@ void AnimInverseKinematics::preconditionRelativePosesToAvoidLimbLock(const AnimC
|
|||
const float MIN_AXIS_LENGTH = 1.0e-4f;
|
||||
|
||||
for (auto& target : targets) {
|
||||
if (target.getIndex() != -1 && target.getType() == IKTarget::Type::RotationAndPosition) {
|
||||
if (target.getIndex() != AnimSkeleton::INVALID_JOINT_INDEX && target.getType() == IKTarget::Type::RotationAndPosition) {
|
||||
for (int i = 0; i < NUM_LIMBS; i++) {
|
||||
if (limbs[i].first == target.getIndex()) {
|
||||
int tipIndex = limbs[i].first;
|
||||
|
|
|
@ -66,7 +66,7 @@ int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
|
|||
if (_jointIndicesByName.end() != itr) {
|
||||
return itr.value();
|
||||
}
|
||||
return -1;
|
||||
return INVALID_JOINT_INDEX;
|
||||
}
|
||||
|
||||
int AnimSkeleton::getNumJoints() const {
|
||||
|
@ -80,7 +80,7 @@ int AnimSkeleton::getChainDepth(int jointIndex) const {
|
|||
do {
|
||||
chainDepth++;
|
||||
index = _parentIndices[index];
|
||||
} while (index != -1);
|
||||
} while (index != INVALID_JOINT_INDEX);
|
||||
return chainDepth;
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -108,7 +108,7 @@ const AnimPose& AnimSkeleton::getPostRotationPose(int jointIndex) const {
|
|||
std::vector<int> AnimSkeleton::getChildrenOfJoint(int jointIndex) const {
|
||||
// Children and grandchildren, etc.
|
||||
std::vector<int> result;
|
||||
if (jointIndex != -1) {
|
||||
if (jointIndex != INVALID_JOINT_INDEX) {
|
||||
for (int i = jointIndex + 1; i < (int)_parentIndices.size(); i++) {
|
||||
if (_parentIndices[i] == jointIndex || (std::find(result.begin(), result.end(), _parentIndices[i]) != result.end())) {
|
||||
result.push_back(i);
|
||||
|
@ -135,7 +135,7 @@ void AnimSkeleton::convertRelativePosesToAbsolute(AnimPoseVec& poses) const {
|
|||
int lastIndex = std::min((int)poses.size(), _jointsSize);
|
||||
for (int i = 0; i < lastIndex; ++i) {
|
||||
int parentIndex = _parentIndices[i];
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != INVALID_JOINT_INDEX) {
|
||||
poses[i] = poses[parentIndex] * poses[i];
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ void AnimSkeleton::convertAbsolutePosesToRelative(AnimPoseVec& poses) const {
|
|||
int lastIndex = std::min((int)poses.size(), _jointsSize);
|
||||
for (int i = lastIndex - 1; i >= 0; --i) {
|
||||
int parentIndex = _parentIndices[i];
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != INVALID_JOINT_INDEX) {
|
||||
poses[i] = poses[parentIndex].inverse() * poses[i];
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ void AnimSkeleton::convertRelativeRotationsToAbsolute(std::vector<glm::quat>& ro
|
|||
int lastIndex = std::min((int)rotations.size(), _jointsSize);
|
||||
for (int i = 0; i < lastIndex; ++i) {
|
||||
int parentIndex = _parentIndices[i];
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != INVALID_JOINT_INDEX) {
|
||||
rotations[i] = rotations[parentIndex] * rotations[i];
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ void AnimSkeleton::convertAbsoluteRotationsToRelative(std::vector<glm::quat>& ro
|
|||
int lastIndex = std::min((int)rotations.size(), _jointsSize);
|
||||
for (int i = lastIndex - 1; i >= 0; --i) {
|
||||
int parentIndex = _parentIndices[i];
|
||||
if (parentIndex != -1) {
|
||||
if (parentIndex != INVALID_JOINT_INDEX) {
|
||||
rotations[i] = glm::inverse(rotations[parentIndex]) * rotations[i];
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<HFMJoint>& joints,
|
|||
// so we can restore them after a future mirror operation
|
||||
_nonMirroredIndices.push_back(i);
|
||||
}
|
||||
int mirrorJointIndex = -1;
|
||||
int mirrorJointIndex = INVALID_JOINT_INDEX;
|
||||
if (_joints[i].name.startsWith("Left")) {
|
||||
QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right");
|
||||
mirrorJointIndex = nameToJointIndex(mirrorJointName);
|
||||
|
@ -350,7 +350,7 @@ std::vector<int> AnimSkeleton::lookUpJointIndices(const std::vector<QString>& jo
|
|||
result.reserve(jointNames.size());
|
||||
for (auto& name : jointNames) {
|
||||
int index = nameToJointIndex(name);
|
||||
if (index == -1) {
|
||||
if (index == INVALID_JOINT_INDEX) {
|
||||
qWarning(animation) << "AnimSkeleton::lookUpJointIndices(): could not find bone with name " << name;
|
||||
}
|
||||
result.push_back(index);
|
||||
|
|
|
@ -30,6 +30,8 @@ public:
|
|||
const QString& getJointName(int jointIndex) const;
|
||||
int getNumJoints() const;
|
||||
int getChainDepth(int jointIndex) const;
|
||||
|
||||
static const int INVALID_JOINT_INDEX { -1 };
|
||||
|
||||
// the default poses are the orientations of the joints on frame 0.
|
||||
const AnimPose& getRelativeDefaultPose(int jointIndex) const;
|
||||
|
|
Loading…
Reference in a new issue