Added support for weights per target

This commit is contained in:
Anthony J. Thibault 2017-05-12 11:45:22 -07:00
parent 67fbb15faa
commit 1e276d113c
7 changed files with 51 additions and 16 deletions

View file

@ -57,6 +57,8 @@
"positionVar": "hipsPosition", "positionVar": "hipsPosition",
"rotationVar": "hipsRotation", "rotationVar": "hipsRotation",
"typeVar": "hipsType", "typeVar": "hipsType",
"weightVar": "hipsWeight",
"weight": 1.0,
"flexCoefficients": [1] "flexCoefficients": [1]
}, },
{ {
@ -64,20 +66,26 @@
"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] "weightVar": "rightHandWeight",
"weight": 1.0,
"flexCoefficients": [1, 0.5, 0.5, 0.25, 0.1, 0.05, 0.01, 0.0, 0.0]
}, },
{ {
"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] "weightVar": "leftHandWeight",
"weight": 1.0,
"flexCoefficients": [1, 0.5, 0.5, 0.25, 0.1, 0.05, 0.01, 0.0, 0.0]
}, },
{ {
"jointName": "RightFoot", "jointName": "RightFoot",
"positionVar": "rightFootPosition", "positionVar": "rightFootPosition",
"rotationVar": "rightFootRotation", "rotationVar": "rightFootRotation",
"typeVar": "rightFootType", "typeVar": "rightFootType",
"weightVar": "rightFootWeight",
"weight": 1.0,
"flexCoefficients": [1, 0.45, 0.45] "flexCoefficients": [1, 0.45, 0.45]
}, },
{ {
@ -85,6 +93,8 @@
"positionVar": "leftFootPosition", "positionVar": "leftFootPosition",
"rotationVar": "leftFootRotation", "rotationVar": "leftFootRotation",
"typeVar": "leftFootType", "typeVar": "leftFootType",
"weightVar": "leftFootWeight",
"weight": 1.0,
"flexCoefficients": [1, 0.45, 0.45] "flexCoefficients": [1, 0.45, 0.45]
}, },
{ {
@ -92,6 +102,8 @@
"positionVar": "spine2Position", "positionVar": "spine2Position",
"rotationVar": "spine2Rotation", "rotationVar": "spine2Rotation",
"typeVar": "spine2Type", "typeVar": "spine2Type",
"weightVar": "spine2Weight",
"weight": 1.0,
"flexCoefficients": [0.45, 0.45] "flexCoefficients": [0.45, 0.45]
}, },
{ {
@ -99,7 +111,9 @@
"positionVar": "headPosition", "positionVar": "headPosition",
"rotationVar": "headRotation", "rotationVar": "headRotation",
"typeVar": "headType", "typeVar": "headType",
"flexCoefficients": [1, 0.5, 0.25, 0.25, 0.25] "weightVar": "headWeight",
"weight": 4.0,
"flexCoefficients": [1, 0.5, 0.5, 0.5, 0.5]
} }
] ]
}, },

View file

@ -22,10 +22,12 @@
#include "AnimationLogging.h" #include "AnimationLogging.h"
AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn, AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn,
const QString& typeVarIn, const std::vector<float>& flexCoefficientsIn) : const QString& typeVarIn, const QString& weightVarIn, float weightIn, const std::vector<float>& flexCoefficientsIn) :
positionVar(positionVarIn), positionVar(positionVarIn),
rotationVar(rotationVarIn), rotationVar(rotationVarIn),
typeVar(typeVarIn), typeVar(typeVarIn),
weightVar(weightVarIn),
weight(weightIn),
jointName(jointNameIn), jointName(jointNameIn),
numFlexCoefficients(flexCoefficientsIn.size()), numFlexCoefficients(flexCoefficientsIn.size()),
jointIndex(-1) jointIndex(-1)
@ -40,6 +42,8 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const IKTargetVar& orig) :
positionVar(orig.positionVar), positionVar(orig.positionVar),
rotationVar(orig.rotationVar), rotationVar(orig.rotationVar),
typeVar(orig.typeVar), typeVar(orig.typeVar),
weightVar(orig.weightVar),
weight(orig.weight),
jointName(orig.jointName), jointName(orig.jointName),
numFlexCoefficients(orig.numFlexCoefficients), numFlexCoefficients(orig.numFlexCoefficients),
jointIndex(orig.jointIndex) jointIndex(orig.jointIndex)
@ -90,8 +94,8 @@ void AnimInverseKinematics::computeAbsolutePoses(AnimPoseVec& absolutePoses) con
} }
void AnimInverseKinematics::setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, void AnimInverseKinematics::setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar,
const QString& typeVar, const std::vector<float>& flexCoefficients) { const QString& typeVar, const QString& weightVar, float weight, const std::vector<float>& flexCoefficients) {
IKTargetVar targetVar(jointName, positionVar, rotationVar, typeVar, flexCoefficients); IKTargetVar targetVar(jointName, positionVar, rotationVar, typeVar, weightVar, weight, flexCoefficients);
// if there are dups, last one wins. // if there are dups, last one wins.
bool found = false; bool found = false;
@ -132,9 +136,11 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses); AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses);
glm::quat rotation = animVars.lookupRigToGeometry(targetVar.rotationVar, defaultPose.rot()); glm::quat rotation = animVars.lookupRigToGeometry(targetVar.rotationVar, defaultPose.rot());
glm::vec3 translation = animVars.lookupRigToGeometry(targetVar.positionVar, defaultPose.trans()); glm::vec3 translation = animVars.lookupRigToGeometry(targetVar.positionVar, defaultPose.trans());
float weight = animVars.lookup(targetVar.weightVar, targetVar.weight);
target.setPose(rotation, translation); target.setPose(rotation, translation);
target.setIndex(targetVar.jointIndex); target.setIndex(targetVar.jointIndex);
target.setWeight(weight);
target.setFlexCoefficients(targetVar.numFlexCoefficients, targetVar.flexCoefficients); target.setFlexCoefficients(targetVar.numFlexCoefficients, targetVar.flexCoefficients);
targets.push_back(target); targets.push_back(target);
@ -837,7 +843,7 @@ void AnimInverseKinematics::initConstraints() {
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 / 20.0f; const float MAX_SHOULDER_SWING = PI / 16.0f;
minDots.push_back(cosf(MAX_SHOULDER_SWING)); minDots.push_back(cosf(MAX_SHOULDER_SWING));
stConstraint->setSwingLimits(minDots); stConstraint->setSwingLimits(minDots);

View file

@ -33,7 +33,7 @@ public:
void computeAbsolutePoses(AnimPoseVec& absolutePoses) const; void computeAbsolutePoses(AnimPoseVec& absolutePoses) const;
void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar,
const QString& typeVar, const std::vector<float>& flexCoefficients); const QString& typeVar, const QString& weightVar, float weight, 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;
@ -81,13 +81,15 @@ protected:
static const size_t MAX_FLEX_COEFFICIENTS = 10; static const size_t MAX_FLEX_COEFFICIENTS = 10;
struct IKTargetVar { struct IKTargetVar {
IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn, IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn,
const QString& typeVarIn, const std::vector<float>& flexCoefficientsIn); const QString& typeVarIn, const QString& weightVarIn, float weightIn, const std::vector<float>& flexCoefficientsIn);
IKTargetVar(const IKTargetVar& orig); IKTargetVar(const IKTargetVar& orig);
QString positionVar; QString positionVar;
QString rotationVar; QString rotationVar;
QString typeVar; QString typeVar;
QString weightVar;
QString jointName; QString jointName;
float weight;
float flexCoefficients[MAX_FLEX_COEFFICIENTS]; float flexCoefficients[MAX_FLEX_COEFFICIENTS];
size_t numFlexCoefficients; size_t numFlexCoefficients;
int jointIndex; // cached joint index int jointIndex; // cached joint index

View file

@ -173,6 +173,13 @@ static NodeProcessFunc animNodeTypeToProcessFunc(AnimNode::Type type) {
} \ } \
float NAME = (float)NAME##_VAL.toDouble() float NAME = (float)NAME##_VAL.toDouble()
#define READ_OPTIONAL_FLOAT(NAME, JSON_OBJ, DEFAULT) \
auto NAME##_VAL = JSON_OBJ.value(#NAME); \
float NAME = (float)DEFAULT; \
if (NAME##_VAL.isDouble()) { \
NAME = (float)NAME##_VAL.toDouble(); \
} \
do {} while (0)
static AnimNode::Pointer loadNode(const QJsonObject& jsonObj, const QUrl& jsonUrl) { static AnimNode::Pointer loadNode(const QJsonObject& jsonObj, const QUrl& jsonUrl) {
auto idVal = jsonObj.value("id"); auto idVal = jsonObj.value("id");
@ -470,6 +477,8 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS
READ_STRING(positionVar, targetObj, id, jsonUrl, nullptr); READ_STRING(positionVar, targetObj, id, jsonUrl, nullptr);
READ_STRING(rotationVar, targetObj, id, jsonUrl, nullptr); READ_STRING(rotationVar, targetObj, id, jsonUrl, nullptr);
READ_OPTIONAL_STRING(typeVar, targetObj); READ_OPTIONAL_STRING(typeVar, targetObj);
READ_OPTIONAL_STRING(weightVar, targetObj);
READ_OPTIONAL_FLOAT(weight, targetObj, 1.0f);
auto flexCoefficientsValue = targetObj.value("flexCoefficients"); auto flexCoefficientsValue = targetObj.value("flexCoefficients");
if (!flexCoefficientsValue.isArray()) { if (!flexCoefficientsValue.isArray()) {
@ -482,7 +491,7 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS
flexCoefficients.push_back((float)value.toDouble()); flexCoefficients.push_back((float)value.toDouble());
} }
node->setTargetVars(jointName, positionVar, rotationVar, typeVar, flexCoefficients); node->setTargetVars(jointName, positionVar, rotationVar, typeVar, weightVar, weight, flexCoefficients);
}; };
READ_OPTIONAL_STRING(solutionSource, jsonObj); READ_OPTIONAL_STRING(solutionSource, jsonObj);

View file

@ -23,6 +23,7 @@ void IKTarget::setFlexCoefficients(size_t numFlexCoefficientsIn, const float* fl
float IKTarget::getFlexCoefficient(int chainDepth) const { float IKTarget::getFlexCoefficient(int chainDepth) const {
const float DEFAULT_FLEX_COEFFICIENT = 0.5f; const float DEFAULT_FLEX_COEFFICIENT = 0.5f;
if (chainDepth >= 0 && chainDepth < _numFlexCoefficients) { if (chainDepth >= 0 && chainDepth < _numFlexCoefficients) {
return _flexCoefficients[chainDepth]; return _flexCoefficients[chainDepth];
} else { } else {

View file

@ -38,14 +38,15 @@ public:
void setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn); void setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn);
float getFlexCoefficient(int chainDepth) const; float getFlexCoefficient(int chainDepth) const;
// HACK: give HmdHead targets more "weight" during IK algorithm void setWeight(float weight) { _weight = weight; }
float getWeight() const { return _type == Type::HmdHead ? HACK_HMD_TARGET_WEIGHT : 1.0f; } float getWeight() const { return _weight; }
static const size_t MAX_FLEX_COEFFICIENTS = 10; 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 _weight;
float _flexCoefficients[MAX_FLEX_COEFFICIENTS]; float _flexCoefficients[MAX_FLEX_COEFFICIENTS];
size_t _numFlexCoefficients; size_t _numFlexCoefficients;
}; };

View file

@ -1088,10 +1088,12 @@ void Rig::updateHeadAnimVars(const HeadParameters& params) {
// Since there is an explicit hips ik target, switch the head to use the more generic RotationAndPosition IK chain type. // Since there is an explicit hips ik target, switch the head to use the more generic RotationAndPosition IK chain type.
// this will allow the spine to bend more, ensuring that it can reach the head target position. // this will allow the spine to bend more, ensuring that it can reach the head target position.
_animVars.set("headType", (int)IKTarget::Type::RotationAndPosition); _animVars.set("headType", (int)IKTarget::Type::RotationAndPosition);
_animVars.unset("headWeight"); // use the default weight for this target.
} else { } else {
// When there is no hips IK target, use the HmdHead IK chain type. This will make the spine very stiff, // When there is no hips IK target, use the HmdHead IK chain type. This will make the spine very stiff,
// but because the IK _hipsOffset is enabled, the hips will naturally follow underneath the head. // but because the IK _hipsOffset is enabled, the hips will naturally follow underneath the head.
_animVars.set("headType", (int)IKTarget::Type::HmdHead); _animVars.set("headType", (int)IKTarget::Type::HmdHead);
_animVars.set("headWeight", 8.0f);
} }
} else { } else {
_animVars.unset("headPosition"); _animVars.unset("headPosition");
@ -1405,19 +1407,19 @@ void Rig::computeAvatarBoundingCapsule(
ikNode.setTargetVars("LeftHand", ikNode.setTargetVars("LeftHand",
"leftHandPosition", "leftHandPosition",
"leftHandRotation", "leftHandRotation",
"leftHandType", {}); "leftHandType", "leftHandWeight", 1.0f, {});
ikNode.setTargetVars("RightHand", ikNode.setTargetVars("RightHand",
"rightHandPosition", "rightHandPosition",
"rightHandRotation", "rightHandRotation",
"rightHandType", {}); "rightHandType", "rightHandWeight", 1.0f, {});
ikNode.setTargetVars("LeftFoot", ikNode.setTargetVars("LeftFoot",
"leftFootPosition", "leftFootPosition",
"leftFootRotation", "leftFootRotation",
"leftFootType", {}); "leftFootType", "leftFootWeight", 1.0f, {});
ikNode.setTargetVars("RightFoot", ikNode.setTargetVars("RightFoot",
"rightFootPosition", "rightFootPosition",
"rightFootRotation", "rightFootRotation",
"rightFootType", {}); "rightFootType", "rightFootWeight", 1.0f, {});
AnimPose geometryToRig = _modelOffset * _geometryOffset; AnimPose geometryToRig = _modelOffset * _geometryOffset;