mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 10:07:58 +02:00
WIP: initial implementation of flexCoefficients
This commit is contained in:
parent
263e4de951
commit
67fbb15faa
7 changed files with 107 additions and 39 deletions
|
@ -56,43 +56,50 @@
|
||||||
"jointName": "Hips",
|
"jointName": "Hips",
|
||||||
"positionVar": "hipsPosition",
|
"positionVar": "hipsPosition",
|
||||||
"rotationVar": "hipsRotation",
|
"rotationVar": "hipsRotation",
|
||||||
"typeVar": "hipsType"
|
"typeVar": "hipsType",
|
||||||
|
"flexCoefficients": [1]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "RightHand",
|
"jointName": "RightHand",
|
||||||
"positionVar": "rightHandPosition",
|
"positionVar": "rightHandPosition",
|
||||||
"rotationVar": "rightHandRotation",
|
"rotationVar": "rightHandRotation",
|
||||||
"typeVar": "rightHandType"
|
"typeVar": "rightHandType",
|
||||||
|
"flexCoefficients": [1, 0.5, 0.5, 0.5, 0.25, 0.1, 0.1, 0.1, 0.1]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "LeftHand",
|
"jointName": "LeftHand",
|
||||||
"positionVar": "leftHandPosition",
|
"positionVar": "leftHandPosition",
|
||||||
"rotationVar": "leftHandRotation",
|
"rotationVar": "leftHandRotation",
|
||||||
"typeVar": "leftHandType"
|
"typeVar": "leftHandType",
|
||||||
|
"flexCoefficients": [1, 0.5, 0.5, 0.5, 0.25, 0.1, 0.1, 0.1, 0.1]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "RightFoot",
|
"jointName": "RightFoot",
|
||||||
"positionVar": "rightFootPosition",
|
"positionVar": "rightFootPosition",
|
||||||
"rotationVar": "rightFootRotation",
|
"rotationVar": "rightFootRotation",
|
||||||
"typeVar": "rightFootType"
|
"typeVar": "rightFootType",
|
||||||
|
"flexCoefficients": [1, 0.45, 0.45]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "LeftFoot",
|
"jointName": "LeftFoot",
|
||||||
"positionVar": "leftFootPosition",
|
"positionVar": "leftFootPosition",
|
||||||
"rotationVar": "leftFootRotation",
|
"rotationVar": "leftFootRotation",
|
||||||
"typeVar": "leftFootType"
|
"typeVar": "leftFootType",
|
||||||
|
"flexCoefficients": [1, 0.45, 0.45]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "Spine2",
|
"jointName": "Spine2",
|
||||||
"positionVar": "spine2Position",
|
"positionVar": "spine2Position",
|
||||||
"rotationVar": "spine2Rotation",
|
"rotationVar": "spine2Rotation",
|
||||||
"typeVar": "spine2Type"
|
"typeVar": "spine2Type",
|
||||||
|
"flexCoefficients": [0.45, 0.45]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"jointName": "Head",
|
"jointName": "Head",
|
||||||
"positionVar": "headPosition",
|
"positionVar": "headPosition",
|
||||||
"rotationVar": "headRotation",
|
"rotationVar": "headRotation",
|
||||||
"typeVar": "headType"
|
"typeVar": "headType",
|
||||||
|
"flexCoefficients": [1, 0.5, 0.25, 0.25, 0.25]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -21,6 +21,35 @@
|
||||||
#include "SwingTwistConstraint.h"
|
#include "SwingTwistConstraint.h"
|
||||||
#include "AnimationLogging.h"
|
#include "AnimationLogging.h"
|
||||||
|
|
||||||
|
AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn,
|
||||||
|
const QString& typeVarIn, const std::vector<float>& flexCoefficientsIn) :
|
||||||
|
positionVar(positionVarIn),
|
||||||
|
rotationVar(rotationVarIn),
|
||||||
|
typeVar(typeVarIn),
|
||||||
|
jointName(jointNameIn),
|
||||||
|
numFlexCoefficients(flexCoefficientsIn.size()),
|
||||||
|
jointIndex(-1)
|
||||||
|
{
|
||||||
|
numFlexCoefficients = std::min(numFlexCoefficients, MAX_FLEX_COEFFICIENTS);
|
||||||
|
for (size_t i = 0; i < numFlexCoefficients; i++) {
|
||||||
|
flexCoefficients[i] = flexCoefficientsIn[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimInverseKinematics::IKTargetVar::IKTargetVar(const IKTargetVar& orig) :
|
||||||
|
positionVar(orig.positionVar),
|
||||||
|
rotationVar(orig.rotationVar),
|
||||||
|
typeVar(orig.typeVar),
|
||||||
|
jointName(orig.jointName),
|
||||||
|
numFlexCoefficients(orig.numFlexCoefficients),
|
||||||
|
jointIndex(orig.jointIndex)
|
||||||
|
{
|
||||||
|
numFlexCoefficients = std::min(numFlexCoefficients, MAX_FLEX_COEFFICIENTS);
|
||||||
|
for (size_t i = 0; i < numFlexCoefficients; i++) {
|
||||||
|
flexCoefficients[i] = orig.flexCoefficients[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AnimInverseKinematics::AnimInverseKinematics(const QString& id) : AnimNode(AnimNode::Type::InverseKinematics, id) {
|
AnimInverseKinematics::AnimInverseKinematics(const QString& id) : AnimNode(AnimNode::Type::InverseKinematics, id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,26 +89,22 @@ void AnimInverseKinematics::computeAbsolutePoses(AnimPoseVec& absolutePoses) con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimInverseKinematics::setTargetVars(
|
void AnimInverseKinematics::setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar,
|
||||||
const QString& jointName,
|
const QString& typeVar, const std::vector<float>& flexCoefficients) {
|
||||||
const QString& positionVar,
|
IKTargetVar targetVar(jointName, positionVar, rotationVar, typeVar, flexCoefficients);
|
||||||
const QString& rotationVar,
|
|
||||||
const QString& typeVar) {
|
|
||||||
// if there are dups, last one wins.
|
// if there are dups, last one wins.
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto& targetVar: _targetVarVec) {
|
for (auto& targetVarIter: _targetVarVec) {
|
||||||
if (targetVar.jointName == jointName) {
|
if (targetVarIter.jointName == jointName) {
|
||||||
// update existing targetVar
|
targetVarIter = targetVar;
|
||||||
targetVar.positionVar = positionVar;
|
|
||||||
targetVar.rotationVar = rotationVar;
|
|
||||||
targetVar.typeVar = typeVar;
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
// create a new entry
|
// create a new entry
|
||||||
_targetVarVec.push_back(IKTargetVar(jointName, positionVar, rotationVar, typeVar));
|
_targetVarVec.push_back(targetVar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +135,10 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
|
||||||
|
|
||||||
target.setPose(rotation, translation);
|
target.setPose(rotation, translation);
|
||||||
target.setIndex(targetVar.jointIndex);
|
target.setIndex(targetVar.jointIndex);
|
||||||
|
target.setFlexCoefficients(targetVar.numFlexCoefficients, targetVar.flexCoefficients);
|
||||||
|
|
||||||
targets.push_back(target);
|
targets.push_back(target);
|
||||||
|
|
||||||
if (targetVar.jointIndex > _maxTargetIndex) {
|
if (targetVar.jointIndex > _maxTargetIndex) {
|
||||||
_maxTargetIndex = targetVar.jointIndex;
|
_maxTargetIndex = targetVar.jointIndex;
|
||||||
}
|
}
|
||||||
|
@ -271,6 +299,8 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
|
||||||
// cache tip absolute position
|
// cache tip absolute position
|
||||||
glm::vec3 tipPosition = absolutePoses[tipIndex].trans();
|
glm::vec3 tipPosition = absolutePoses[tipIndex].trans();
|
||||||
|
|
||||||
|
int chainDepth = 1;
|
||||||
|
|
||||||
// descend toward root, pivoting each joint to get tip closer to target position
|
// descend toward root, pivoting each joint to get tip closer to target position
|
||||||
while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) {
|
while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) {
|
||||||
// compute the two lines that should be aligned
|
// compute the two lines that should be aligned
|
||||||
|
@ -312,9 +342,8 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
|
||||||
float angle = acosf(cosAngle);
|
float angle = acosf(cosAngle);
|
||||||
const float MIN_ADJUSTMENT_ANGLE = 1.0e-4f;
|
const float MIN_ADJUSTMENT_ANGLE = 1.0e-4f;
|
||||||
if (angle > MIN_ADJUSTMENT_ANGLE) {
|
if (angle > MIN_ADJUSTMENT_ANGLE) {
|
||||||
// reduce angle by a fraction (for stability)
|
// reduce angle by a flexCoefficient
|
||||||
const float STABILITY_FRACTION = 0.5f;
|
angle *= target.getFlexCoefficient(chainDepth);
|
||||||
angle *= STABILITY_FRACTION;
|
|
||||||
deltaRotation = glm::angleAxis(angle, axis);
|
deltaRotation = glm::angleAxis(angle, axis);
|
||||||
|
|
||||||
// The swing will re-orient the tip but there will tend to be be a non-zero delta between the tip's
|
// The swing will re-orient the tip but there will tend to be be a non-zero delta between the tip's
|
||||||
|
@ -385,6 +414,8 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
|
||||||
|
|
||||||
pivotIndex = pivotsParentIndex;
|
pivotIndex = pivotsParentIndex;
|
||||||
pivotsParentIndex = _skeleton->getParentIndex(pivotIndex);
|
pivotsParentIndex = _skeleton->getParentIndex(pivotIndex);
|
||||||
|
|
||||||
|
chainDepth++;
|
||||||
}
|
}
|
||||||
return lowestMovedIndex;
|
return lowestMovedIndex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ public:
|
||||||
void loadPoses(const AnimPoseVec& poses);
|
void loadPoses(const AnimPoseVec& poses);
|
||||||
void computeAbsolutePoses(AnimPoseVec& absolutePoses) const;
|
void computeAbsolutePoses(AnimPoseVec& absolutePoses) const;
|
||||||
|
|
||||||
void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, const QString& typeVar);
|
void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar,
|
||||||
|
const QString& typeVar, const std::vector<float>& flexCoefficients);
|
||||||
|
|
||||||
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimNode::Triggers& triggersOut) override;
|
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimNode::Triggers& triggersOut) override;
|
||||||
virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override;
|
virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override;
|
||||||
|
@ -77,22 +78,18 @@ protected:
|
||||||
AnimInverseKinematics(const AnimInverseKinematics&) = delete;
|
AnimInverseKinematics(const AnimInverseKinematics&) = delete;
|
||||||
AnimInverseKinematics& operator=(const AnimInverseKinematics&) = delete;
|
AnimInverseKinematics& operator=(const AnimInverseKinematics&) = delete;
|
||||||
|
|
||||||
|
static const size_t MAX_FLEX_COEFFICIENTS = 10;
|
||||||
struct IKTargetVar {
|
struct IKTargetVar {
|
||||||
IKTargetVar(const QString& jointNameIn,
|
IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn,
|
||||||
const QString& positionVarIn,
|
const QString& typeVarIn, const std::vector<float>& flexCoefficientsIn);
|
||||||
const QString& rotationVarIn,
|
IKTargetVar(const IKTargetVar& orig);
|
||||||
const QString& typeVarIn) :
|
|
||||||
positionVar(positionVarIn),
|
|
||||||
rotationVar(rotationVarIn),
|
|
||||||
typeVar(typeVarIn),
|
|
||||||
jointName(jointNameIn),
|
|
||||||
jointIndex(-1)
|
|
||||||
{}
|
|
||||||
|
|
||||||
QString positionVar;
|
QString positionVar;
|
||||||
QString rotationVar;
|
QString rotationVar;
|
||||||
QString typeVar;
|
QString typeVar;
|
||||||
QString jointName;
|
QString jointName;
|
||||||
|
float flexCoefficients[MAX_FLEX_COEFFICIENTS];
|
||||||
|
size_t numFlexCoefficients;
|
||||||
int jointIndex; // cached joint index
|
int jointIndex; // cached joint index
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -471,7 +471,18 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS
|
||||||
READ_STRING(rotationVar, targetObj, id, jsonUrl, nullptr);
|
READ_STRING(rotationVar, targetObj, id, jsonUrl, nullptr);
|
||||||
READ_OPTIONAL_STRING(typeVar, targetObj);
|
READ_OPTIONAL_STRING(typeVar, targetObj);
|
||||||
|
|
||||||
node->setTargetVars(jointName, positionVar, rotationVar, typeVar);
|
auto flexCoefficientsValue = targetObj.value("flexCoefficients");
|
||||||
|
if (!flexCoefficientsValue.isArray()) {
|
||||||
|
qCCritical(animation) << "AnimNodeLoader, bad or missing flexCoefficients array in \"targets\", id =" << id << ", url =" << jsonUrl.toDisplayString();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto flexCoefficientsArray = flexCoefficientsValue.toArray();
|
||||||
|
std::vector<float> flexCoefficients;
|
||||||
|
for (const auto& value : flexCoefficientsArray) {
|
||||||
|
flexCoefficients.push_back((float)value.toDouble());
|
||||||
|
}
|
||||||
|
|
||||||
|
node->setTargetVars(jointName, positionVar, rotationVar, typeVar, flexCoefficients);
|
||||||
};
|
};
|
||||||
|
|
||||||
READ_OPTIONAL_STRING(solutionSource, jsonObj);
|
READ_OPTIONAL_STRING(solutionSource, jsonObj);
|
||||||
|
|
|
@ -14,6 +14,22 @@ void IKTarget::setPose(const glm::quat& rotation, const glm::vec3& translation)
|
||||||
_pose.trans() = translation;
|
_pose.trans() = translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IKTarget::setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn) {
|
||||||
|
_numFlexCoefficients = std::min(numFlexCoefficientsIn, MAX_FLEX_COEFFICIENTS);
|
||||||
|
for (size_t i = 0; i < _numFlexCoefficients; i++) {
|
||||||
|
_flexCoefficients[i] = flexCoefficientsIn[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float IKTarget::getFlexCoefficient(int chainDepth) const {
|
||||||
|
const float DEFAULT_FLEX_COEFFICIENT = 0.5f;
|
||||||
|
if (chainDepth >= 0 && chainDepth < _numFlexCoefficients) {
|
||||||
|
return _flexCoefficients[chainDepth];
|
||||||
|
} else {
|
||||||
|
return DEFAULT_FLEX_COEFFICIENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IKTarget::setType(int type) {
|
void IKTarget::setType(int type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case (int)Type::RotationAndPosition:
|
case (int)Type::RotationAndPosition:
|
||||||
|
|
|
@ -35,15 +35,19 @@ public:
|
||||||
void setPose(const glm::quat& rotation, const glm::vec3& translation);
|
void setPose(const glm::quat& rotation, const glm::vec3& translation);
|
||||||
void setIndex(int index) { _index = index; }
|
void setIndex(int index) { _index = index; }
|
||||||
void setType(int);
|
void setType(int);
|
||||||
|
void setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn);
|
||||||
|
float getFlexCoefficient(int chainDepth) const;
|
||||||
|
|
||||||
// HACK: give HmdHead targets more "weight" during IK algorithm
|
// HACK: give HmdHead targets more "weight" during IK algorithm
|
||||||
float getWeight() const { return _type == Type::HmdHead ? HACK_HMD_TARGET_WEIGHT : 1.0f; }
|
float getWeight() const { return _type == Type::HmdHead ? HACK_HMD_TARGET_WEIGHT : 1.0f; }
|
||||||
|
|
||||||
|
static const size_t MAX_FLEX_COEFFICIENTS = 10;
|
||||||
private:
|
private:
|
||||||
AnimPose _pose;
|
AnimPose _pose;
|
||||||
int _index{-1};
|
int _index{-1};
|
||||||
Type _type{Type::RotationAndPosition};
|
Type _type{Type::RotationAndPosition};
|
||||||
|
float _flexCoefficients[MAX_FLEX_COEFFICIENTS];
|
||||||
|
size_t _numFlexCoefficients;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_IKTarget_h
|
#endif // hifi_IKTarget_h
|
||||||
|
|
|
@ -1400,22 +1400,24 @@ void Rig::computeAvatarBoundingCapsule(
|
||||||
|
|
||||||
AnimInverseKinematics ikNode("boundingShape");
|
AnimInverseKinematics ikNode("boundingShape");
|
||||||
ikNode.setSkeleton(_animSkeleton);
|
ikNode.setSkeleton(_animSkeleton);
|
||||||
|
|
||||||
|
// AJT: FIX ME!!!!! ensure that empty weights vector does something reasonable....
|
||||||
ikNode.setTargetVars("LeftHand",
|
ikNode.setTargetVars("LeftHand",
|
||||||
"leftHandPosition",
|
"leftHandPosition",
|
||||||
"leftHandRotation",
|
"leftHandRotation",
|
||||||
"leftHandType");
|
"leftHandType", {});
|
||||||
ikNode.setTargetVars("RightHand",
|
ikNode.setTargetVars("RightHand",
|
||||||
"rightHandPosition",
|
"rightHandPosition",
|
||||||
"rightHandRotation",
|
"rightHandRotation",
|
||||||
"rightHandType");
|
"rightHandType", {});
|
||||||
ikNode.setTargetVars("LeftFoot",
|
ikNode.setTargetVars("LeftFoot",
|
||||||
"leftFootPosition",
|
"leftFootPosition",
|
||||||
"leftFootRotation",
|
"leftFootRotation",
|
||||||
"leftFootType");
|
"leftFootType", {});
|
||||||
ikNode.setTargetVars("RightFoot",
|
ikNode.setTargetVars("RightFoot",
|
||||||
"rightFootPosition",
|
"rightFootPosition",
|
||||||
"rightFootRotation",
|
"rightFootRotation",
|
||||||
"rightFootType");
|
"rightFootType", {});
|
||||||
|
|
||||||
AnimPose geometryToRig = _modelOffset * _geometryOffset;
|
AnimPose geometryToRig = _modelOffset * _geometryOffset;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue