mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +02:00
Merge pull request #5881 from AndrewMeadows/ik-repairs-004
remove underpose attenuation from IK relaxation step
This commit is contained in:
commit
a9460b9b41
7 changed files with 34 additions and 35 deletions
|
@ -635,8 +635,6 @@ void SkeletonModel::computeBoundingShape() {
|
|||
}
|
||||
|
||||
void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha) {
|
||||
const int BALL_SUBDIVISIONS = 10;
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
|
||||
// draw a blue sphere at the capsule top point
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1727,9 +1727,7 @@ void Model::segregateMeshGroups() {
|
|||
// Run through all of the meshes, and place them into their segregated, but unsorted buckets
|
||||
int shapeID = 0;
|
||||
for (int i = 0; i < (int)networkMeshes.size(); i++) {
|
||||
const NetworkMesh& networkMesh = *(networkMeshes.at(i).get());
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
const MeshState& state = _meshStates.at(i);
|
||||
|
||||
// Create the render payloads
|
||||
int totalParts = mesh.parts.size();
|
||||
|
|
|
@ -193,7 +193,7 @@ public:
|
|||
|
||||
int getBlendshapeCoefficientsNum() const { return _blendshapeCoefficients.size(); }
|
||||
float getBlendshapeCoefficient(unsigned int index) const {
|
||||
return index >= _blendshapeCoefficients.size() ? 0.0f : _blendshapeCoefficients.at(index);
|
||||
return index >= (unsigned int)_blendshapeCoefficients.size() ? 0.0f : _blendshapeCoefficients.at(index);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
Loading…
Reference in a new issue