mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 14:03:55 +02:00
fix animation attenuation from IK relaxation step
This commit is contained in:
parent
2edffaf91a
commit
d25ba8946e
4 changed files with 33 additions and 30 deletions
|
@ -33,8 +33,10 @@ void AnimInverseKinematics::loadPoses(const AnimPoseVec& poses) {
|
|||
assert(_skeleton && ((poses.size() == 0) || (_skeleton->getNumJoints() == (int)poses.size())));
|
||||
if (_skeleton->getNumJoints() == (int)poses.size()) {
|
||||
_relativePoses = poses;
|
||||
_accumulators.resize(_relativePoses.size());
|
||||
} else {
|
||||
_relativePoses.clear();
|
||||
_accumulators.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,8 +135,8 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(std::vector<IKTarge
|
|||
computeAbsolutePoses(absolutePoses);
|
||||
|
||||
// clear the accumulators before we start the IK solver
|
||||
for (auto& accumulatorPair: _accumulators) {
|
||||
accumulatorPair.second.clear();
|
||||
for (auto& accumulator: _accumulators) {
|
||||
accumulator.clearAndClean();
|
||||
}
|
||||
|
||||
float largestError = 0.0f;
|
||||
|
@ -221,11 +223,11 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(std::vector<IKTarge
|
|||
++numLoops;
|
||||
|
||||
// harvest accumulated rotations and apply the average
|
||||
for (auto& accumulatorPair: _accumulators) {
|
||||
RotationAccumulator& accumulator = accumulatorPair.second;
|
||||
if (accumulator.size() > 0) {
|
||||
_relativePoses[accumulatorPair.first].rot = accumulator.getAverage();
|
||||
accumulator.clear();
|
||||
const int numJoints = (int)_accumulators.size();
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
if (_accumulators[i].size() > 0) {
|
||||
_relativePoses[i].rot = _accumulators[i].getAverage();
|
||||
_accumulators[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,7 +301,11 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
|||
int numJoints = (int)_relativePoses.size();
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
float dotSign = copysignf(1.0f, glm::dot(_relativePoses[i].rot, underPoses[i].rot));
|
||||
_relativePoses[i].rot = glm::normalize(glm::lerp(_relativePoses[i].rot, dotSign * underPoses[i].rot, blend));
|
||||
if (_accumulators[i].isDirty()) {
|
||||
_relativePoses[i].rot = glm::normalize(glm::lerp(_relativePoses[i].rot, dotSign * underPoses[i].rot, blend));
|
||||
} else {
|
||||
_relativePoses[i].rot = underPoses[i].rot;
|
||||
}
|
||||
}
|
||||
}
|
||||
return evaluate(animVars, dt, triggersOut);
|
||||
|
@ -642,18 +648,3 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele
|
|||
clearConstraints();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimInverseKinematics::relaxTowardDefaults(float dt) {
|
||||
// NOTE: for now we just use a single relaxation timescale for all joints, but in the future
|
||||
// we could vary the timescale on a per-joint basis or do other fancy things.
|
||||
|
||||
// for each joint: lerp towards the default pose
|
||||
const float RELAXATION_TIMESCALE = 0.25f;
|
||||
const float alpha = glm::clamp(dt / RELAXATION_TIMESCALE, 0.0f, 1.0f);
|
||||
int numJoints = (int)_relativePoses.size();
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
float dotSign = copysignf(1.0f, glm::dot(_relativePoses[i].rot, _defaultRelativePoses[i].rot));
|
||||
_relativePoses[i].rot = glm::normalize(glm::lerp(_relativePoses[i].rot, dotSign * _defaultRelativePoses[i].rot, alpha));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,6 @@ protected:
|
|||
// for AnimDebugDraw rendering
|
||||
virtual const AnimPoseVec& getPosesInternal() const override { return _relativePoses; }
|
||||
|
||||
void relaxTowardDefaults(float dt);
|
||||
|
||||
RotationConstraint* getConstraint(int index);
|
||||
void clearConstraints();
|
||||
void initConstraints();
|
||||
|
@ -72,7 +70,7 @@ protected:
|
|||
};
|
||||
|
||||
std::map<int, RotationConstraint*> _constraints;
|
||||
std::map<int, RotationAccumulator> _accumulators; // class-member to exploit temporal coherency
|
||||
std::vector<RotationAccumulator> _accumulators;
|
||||
std::vector<IKTargetVar> _targetVarVec;
|
||||
AnimPoseVec _defaultRelativePoses; // poses of the relaxed state
|
||||
AnimPoseVec _relativePoses; // current relative poses
|
||||
|
|
|
@ -11,17 +11,23 @@
|
|||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
void RotationAccumulator::add(glm::quat rotation) {
|
||||
void RotationAccumulator::add(const glm::quat& rotation) {
|
||||
// make sure both quaternions are on the same hyper-hemisphere before we add them linearly (lerp)
|
||||
_rotationSum += copysignf(1.0f, glm::dot(_rotationSum, rotation)) * rotation;
|
||||
++_numRotations;
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
glm::quat RotationAccumulator::getAverage() {
|
||||
return (_numRotations > 0) ? glm::normalize(_rotationSum) : glm::quat();
|
||||
}
|
||||
|
||||
void RotationAccumulator::clear() {
|
||||
void RotationAccumulator::clear() {
|
||||
_rotationSum *= 0.0f;
|
||||
_numRotations = 0;
|
||||
}
|
||||
|
||||
void RotationAccumulator::clearAndClean() {
|
||||
clear();
|
||||
_isDirty = false;
|
||||
}
|
||||
|
|
|
@ -14,19 +14,27 @@
|
|||
|
||||
class RotationAccumulator {
|
||||
public:
|
||||
RotationAccumulator() : _rotationSum(0.0f, 0.0f, 0.0f, 0.0f), _numRotations(0) { }
|
||||
RotationAccumulator() : _rotationSum(0.0f, 0.0f, 0.0f, 0.0f), _numRotations(0), _isDirty(false) { }
|
||||
|
||||
int size() const { return _numRotations; }
|
||||
|
||||
void add(glm::quat rotation);
|
||||
void add(const glm::quat& rotation);
|
||||
|
||||
glm::quat getAverage();
|
||||
|
||||
/// \return true if any rotations were accumulated
|
||||
bool isDirty() const { return _isDirty; }
|
||||
|
||||
/// \brief clear accumulated rotation but don't change _isDirty
|
||||
void clear();
|
||||
|
||||
/// \brief clear accumulated rotation and set _isDirty to false
|
||||
void clearAndClean();
|
||||
|
||||
private:
|
||||
glm::quat _rotationSum;
|
||||
int _numRotations;
|
||||
bool _isDirty;
|
||||
};
|
||||
|
||||
#endif // hifi_RotationAccumulator_h
|
||||
|
|
Loading…
Reference in a new issue