Merge pull request #3220 from Atlante45/avatar_simulate_optimisation

Avatar simulate optimisation
This commit is contained in:
Philip Rosedale 2014-07-29 20:20:32 -07:00
commit 743200a38c
5 changed files with 65 additions and 24 deletions

View file

@ -52,7 +52,8 @@ const float PALM_PRIORITY = 3.0f;
void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
setTranslation(_owningAvatar->getPosition());
setRotation(_owningAvatar->getOrientation() * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)));
static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
setRotation(_owningAvatar->getOrientation() * refOrientation);
const float MODEL_SCALE = 0.0006f;
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale() * MODEL_SCALE);

View file

@ -11,14 +11,17 @@
#include <glm/gtx/norm.hpp>
#include <QThreadPool>
#include <AngularConstraint.h>
//#include <GeometryUtil.h>
#include <SharedUtil.h>
#include "JointState.h"
JointState::JointState() :
_animationPriority(0.0f),
_transformChanged(true),
_rotationIsValid(false),
_positionInParentFrame(0.0f),
_distanceToParent(0.0f),
_fbxJoint(NULL),
@ -26,7 +29,9 @@ JointState::JointState() :
}
JointState::JointState(const JointState& other) : _constraint(NULL) {
_transformChanged = other._transformChanged;
_transform = other._transform;
_rotationIsValid = other._rotationIsValid;
_rotation = other._rotation;
_rotationInConstrainedFrame = other._rotationInConstrainedFrame;
_positionInParentFrame = other._positionInParentFrame;
@ -45,9 +50,21 @@ JointState::~JointState() {
}
}
glm::quat JointState::getRotation() const {
if (!_rotationIsValid) {
const_cast<JointState*>(this)->_rotation = extractRotation(_transform);
const_cast<JointState*>(this)->_rotationIsValid = true;
}
return _rotation;
}
void JointState::setFBXJoint(const FBXJoint* joint) {
assert(joint != NULL);
_rotationInConstrainedFrame = joint->rotation;
_transformChanged = true;
_rotationIsValid = false;
// NOTE: JointState does not own the FBXJoint to which it points.
_fbxJoint = joint;
if (_constraint) {
@ -70,8 +87,10 @@ void JointState::updateConstraint() {
void JointState::copyState(const JointState& state) {
_animationPriority = state._animationPriority;
_transformChanged = state._transformChanged;
_transform = state._transform;
_rotation = extractRotation(_transform);
_rotationIsValid = state._rotationIsValid;
_rotation = state._rotation;
_rotationInConstrainedFrame = state._rotationInConstrainedFrame;
_positionInParentFrame = state._positionInParentFrame;
_distanceToParent = state._distanceToParent;
@ -88,11 +107,20 @@ void JointState::initTransform(const glm::mat4& parentTransform) {
_distanceToParent = glm::length(_positionInParentFrame);
}
void JointState::computeTransform(const glm::mat4& parentTransform) {
void JointState::computeTransform(const glm::mat4& parentTransform, bool parentTransformChanged, bool synchronousRotationCompute) {
if (!parentTransformChanged && !_transformChanged) {
return;
}
glm::quat rotationInParentFrame = _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation;
glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform;
_transform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame;
_rotation = extractRotation(_transform);
glm::mat4 newTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame;
if (newTransform != _transform) {
_transform = newTransform;
_transformChanged = true;
_rotationIsValid = false;
}
}
void JointState::computeVisibleTransform(const glm::mat4& parentTransform) {
@ -103,7 +131,7 @@ void JointState::computeVisibleTransform(const glm::mat4& parentTransform) {
}
glm::quat JointState::getRotationInBindFrame() const {
return _rotation * _fbxJoint->inverseBindRotation;
return getRotation() * _fbxJoint->inverseBindRotation;
}
glm::quat JointState::getRotationInParentFrame() const {
@ -126,7 +154,7 @@ void JointState::setRotationInBindFrame(const glm::quat& rotation, float priorit
// rotation is from bind- to model-frame
assert(_fbxJoint != NULL);
if (priority >= _animationPriority) {
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
if (constrain && _constraint) {
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
}
@ -139,29 +167,32 @@ void JointState::clearTransformTranslation() {
_transform[3][0] = 0.0f;
_transform[3][1] = 0.0f;
_transform[3][2] = 0.0f;
_transformChanged = true;
_visibleTransform[3][0] = 0.0f;
_visibleTransform[3][1] = 0.0f;
_visibleTransform[3][2] = 0.0f;
}
void JointState::setRotation(const glm::quat& rotation, bool constrain, float priority) {
applyRotationDelta(rotation * glm::inverse(_rotation), true, priority);
applyRotationDelta(rotation * glm::inverse(getRotation()), true, priority);
}
void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) {
// NOTE: delta is in model-frame
assert(_fbxJoint != NULL);
if (priority < _animationPriority) {
if (priority < _animationPriority || delta.null) {
return;
}
_animationPriority = priority;
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation();
if (!constrain || _constraint == NULL) {
// no constraints
_rotationInConstrainedFrame = _rotationInConstrainedFrame * glm::inverse(_rotation) * delta * _rotation;
_rotation = delta * _rotation;
_rotationInConstrainedFrame = targetRotation;
_transformChanged = true;
_rotation = delta * getRotation();
return;
}
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(_rotation) * delta * _rotation;
setRotationInConstrainedFrame(targetRotation);
}
@ -174,7 +205,7 @@ void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float
return;
}
_animationPriority = priority;
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(_rotation) * delta * _rotation;
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation();
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor);
}
@ -198,7 +229,7 @@ void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor
glm::quat JointState::computeParentRotation() const {
// R = Rp * Rpre * r * Rpost
// Rp = R * (Rpre * r * Rpost)^
return _rotation * glm::inverse(_fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation);
return getRotation() * glm::inverse(_fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation);
}
glm::quat JointState::computeVisibleParentRotation() const {
@ -208,6 +239,7 @@ glm::quat JointState::computeVisibleParentRotation() const {
void JointState::setRotationInConstrainedFrame(const glm::quat& targetRotation) {
glm::quat parentRotation = computeParentRotation();
_rotationInConstrainedFrame = targetRotation;
_transformChanged = true;
// R' = Rp * Rpre * r' * Rpost
_rotation = parentRotation * _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation;
}
@ -233,6 +265,6 @@ const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const {
void JointState::slaveVisibleTransform() {
_visibleTransform = _transform;
_visibleRotation = _rotation;
_visibleRotation = getRotation();
_visibleRotationInConstrainedFrame = _rotationInConstrainedFrame;
}
}

View file

@ -33,7 +33,9 @@ public:
void copyState(const JointState& state);
void initTransform(const glm::mat4& parentTransform);
void computeTransform(const glm::mat4& parentTransform);
// if synchronousRotationCompute is true, then _transform is still computed synchronously,
// but _rotation will be asynchronously extracted
void computeTransform(const glm::mat4& parentTransform, bool parentTransformChanged = true, bool synchronousRotationCompute = false);
void computeVisibleTransform(const glm::mat4& parentTransform);
const glm::mat4& getVisibleTransform() const { return _visibleTransform; }
@ -41,8 +43,10 @@ public:
glm::vec3 getVisiblePosition() const { return extractTranslation(_visibleTransform); }
const glm::mat4& getTransform() const { return _transform; }
void resetTransformChanged() { _transformChanged = false; }
bool getTransformChanged() const { return _transformChanged; }
glm::quat getRotation() const { return _rotation; }
glm::quat getRotation() const;
glm::vec3 getPosition() const { return extractTranslation(_transform); }
/// \return rotation from bind to model frame
@ -104,7 +108,9 @@ private:
/// debug helper function
void loadBindRotation();
bool _transformChanged;
glm::mat4 _transform; // joint- to model-frame
bool _rotationIsValid;
glm::quat _rotation; // joint- to model-frame
glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied
glm::vec3 _positionInParentFrame; // only changes when the Model is scaled

View file

@ -922,7 +922,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) {
void Model::simulateInternal(float deltaTime) {
// NOTE: this is a recursive call that walks all attachments, and their attachments
// update the world space transforms for all joints
// update animations
foreach (const AnimationHandlePointer& handle, _runningAnimations) {
handle->simulate(deltaTime);
@ -931,8 +931,11 @@ void Model::simulateInternal(float deltaTime) {
for (int i = 0; i < _jointStates.size(); i++) {
updateJointState(i);
}
for (int i = 0; i < _jointStates.size(); i++) {
_jointStates[i].resetTransformChanged();
}
_shapesAreDirty = ! _shapes.isEmpty();
_shapesAreDirty = !_shapes.isEmpty();
// update the attachment transforms and simulate them
const FBXGeometry& geometry = _geometry->getFBXGeometry();
@ -994,7 +997,7 @@ void Model::updateJointState(int index) {
state.computeTransform(parentTransform);
} else {
const JointState& parentState = _jointStates.at(parentIndex);
state.computeTransform(parentState.getTransform());
state.computeTransform(parentState.getTransform(), parentState.getTransformChanged());
}
}

View file

@ -757,8 +757,7 @@ void setTranslation(glm::mat4& matrix, const glm::vec3& translation) {
glm::quat extractRotation(const glm::mat4& matrix, bool assumeOrthogonal) {
// uses the iterative polar decomposition algorithm described by Ken Shoemake at
// http://www.cs.wisc.edu/graphics/Courses/838-s2002/Papers/polar-decomp.pdf
// code adapted from Clyde, https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Matrix4f.java
// code adapted from Clyde, https://github.com/threerings/clyde/blob/master/core/src/main/java/com/threerings/math/Matrix4f.java
// start with the contents of the upper 3x3 portion of the matrix
glm::mat3 upper = glm::mat3(matrix);
if (!assumeOrthogonal) {