mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 17:00:13 +02:00
remove cruft from old verlet avatar simulation
This commit is contained in:
parent
966945d08c
commit
09ac01a5e7
11 changed files with 32 additions and 522 deletions
|
@ -320,7 +320,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position)
|
||||||
float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
|
float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
|
||||||
_rig->applyJointRotationDelta(jointIndex,
|
_rig->applyJointRotationDelta(jointIndex,
|
||||||
rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector),
|
rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector),
|
||||||
true, PALM_PRIORITY);
|
PALM_PRIORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
||||||
|
|
|
@ -181,7 +181,6 @@ void AnimationHandle::applyFrame(float frameIndex) {
|
||||||
ceilFrame.rotations.at(i),
|
ceilFrame.rotations.at(i),
|
||||||
frameFraction),
|
frameFraction),
|
||||||
_priority,
|
_priority,
|
||||||
false,
|
|
||||||
_mix);
|
_mix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,16 +13,11 @@
|
||||||
|
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
|
||||||
#include <AngularConstraint.h>
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "JointState.h"
|
#include "JointState.h"
|
||||||
|
|
||||||
JointState::~JointState() {
|
JointState::~JointState() {
|
||||||
if (_constraint) {
|
|
||||||
delete _constraint;
|
|
||||||
_constraint = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::copyState(const JointState& other) {
|
void JointState::copyState(const JointState& other) {
|
||||||
|
@ -35,18 +30,12 @@ void JointState::copyState(const JointState& other) {
|
||||||
_distanceToParent = other._distanceToParent;
|
_distanceToParent = other._distanceToParent;
|
||||||
_animationPriority = other._animationPriority;
|
_animationPriority = other._animationPriority;
|
||||||
|
|
||||||
_visibleTransform = other._visibleTransform;
|
|
||||||
_visibleRotation = extractRotation(_visibleTransform);
|
|
||||||
_visibleRotationInConstrainedFrame = other._visibleRotationInConstrainedFrame;
|
|
||||||
// DO NOT copy _constraint
|
|
||||||
_name = other._name;
|
_name = other._name;
|
||||||
_isFree = other._isFree;
|
_isFree = other._isFree;
|
||||||
_parentIndex = other._parentIndex;
|
_parentIndex = other._parentIndex;
|
||||||
_defaultRotation = other._defaultRotation;
|
_defaultRotation = other._defaultRotation;
|
||||||
_inverseDefaultRotation = other._inverseDefaultRotation;
|
_inverseDefaultRotation = other._inverseDefaultRotation;
|
||||||
_translation = other._translation;
|
_translation = other._translation;
|
||||||
_rotationMin = other._rotationMin;
|
|
||||||
_rotationMax = other._rotationMax;
|
|
||||||
_preRotation = other._preRotation;
|
_preRotation = other._preRotation;
|
||||||
_postRotation = other._postRotation;
|
_postRotation = other._postRotation;
|
||||||
_preTransform = other._preTransform;
|
_preTransform = other._preTransform;
|
||||||
|
@ -61,8 +50,6 @@ JointState::JointState(const FBXJoint& joint) {
|
||||||
_translation = joint.translation;
|
_translation = joint.translation;
|
||||||
_defaultRotation = joint.rotation;
|
_defaultRotation = joint.rotation;
|
||||||
_inverseDefaultRotation = joint.inverseDefaultRotation;
|
_inverseDefaultRotation = joint.inverseDefaultRotation;
|
||||||
_rotationMin = joint.rotationMin;
|
|
||||||
_rotationMax = joint.rotationMax;
|
|
||||||
_preRotation = joint.preRotation;
|
_preRotation = joint.preRotation;
|
||||||
_postRotation = joint.postRotation;
|
_postRotation = joint.postRotation;
|
||||||
_preTransform = joint.preTransform;
|
_preTransform = joint.preTransform;
|
||||||
|
@ -71,15 +58,6 @@ JointState::JointState(const FBXJoint& joint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::buildConstraint() {
|
void JointState::buildConstraint() {
|
||||||
if (_constraint) {
|
|
||||||
delete _constraint;
|
|
||||||
_constraint = NULL;
|
|
||||||
}
|
|
||||||
if (glm::distance2(glm::vec3(-PI), _rotationMin) > EPSILON ||
|
|
||||||
glm::distance2(glm::vec3(PI), _rotationMax) > EPSILON ) {
|
|
||||||
// this joint has rotation constraints
|
|
||||||
_constraint = AngularConstraint::newAngularConstraint(_rotationMin, _rotationMax);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat JointState::getRotation() const {
|
glm::quat JointState::getRotation() const {
|
||||||
|
@ -113,13 +91,6 @@ void JointState::computeTransform(const glm::mat4& parentTransform, bool parentT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::computeVisibleTransform(const glm::mat4& parentTransform) {
|
|
||||||
glm::quat rotationInParentFrame = _preRotation * _visibleRotationInConstrainedFrame * _postRotation;
|
|
||||||
glm::mat4 transformInParentFrame = _preTransform * glm::mat4_cast(rotationInParentFrame) * _postTransform;
|
|
||||||
_visibleTransform = parentTransform * glm::translate(_translation) * transformInParentFrame;
|
|
||||||
_visibleRotation = extractRotation(_visibleTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::quat JointState::getRotationInBindFrame() const {
|
glm::quat JointState::getRotationInBindFrame() const {
|
||||||
return getRotation() * _inverseBindRotation;
|
return getRotation() * _inverseBindRotation;
|
||||||
}
|
}
|
||||||
|
@ -128,10 +99,6 @@ glm::quat JointState::getRotationInParentFrame() const {
|
||||||
return _preRotation * _rotationInConstrainedFrame * _postRotation;
|
return _preRotation * _rotationInConstrainedFrame * _postRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat JointState::getVisibleRotationInParentFrame() const {
|
|
||||||
return _preRotation * _visibleRotationInConstrainedFrame * _postRotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JointState::restoreRotation(float fraction, float priority) {
|
void JointState::restoreRotation(float fraction, float priority) {
|
||||||
if (priority == _animationPriority || _animationPriority == 0.0f) {
|
if (priority == _animationPriority || _animationPriority == 0.0f) {
|
||||||
setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _defaultRotation, fraction));
|
setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _defaultRotation, fraction));
|
||||||
|
@ -139,19 +106,16 @@ void JointState::restoreRotation(float fraction, float priority) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain) {
|
void JointState::setRotationInBindFrame(const glm::quat& rotation, float priority) {
|
||||||
// rotation is from bind- to model-frame
|
// rotation is from bind- to model-frame
|
||||||
if (priority >= _animationPriority) {
|
if (priority >= _animationPriority) {
|
||||||
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_inverseBindRotation);
|
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_inverseBindRotation);
|
||||||
if (constrain && _constraint) {
|
|
||||||
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
|
|
||||||
}
|
|
||||||
setRotationInConstrainedFrameInternal(targetRotation);
|
setRotationInConstrainedFrameInternal(targetRotation);
|
||||||
_animationPriority = priority;
|
_animationPriority = priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::setRotationInModelFrame(const glm::quat& rotationInModelFrame, float priority, bool constrain) {
|
void JointState::setRotationInModelFrame(const glm::quat& rotationInModelFrame, float priority) {
|
||||||
// rotation is from bind- to model-frame
|
// rotation is from bind- to model-frame
|
||||||
if (priority >= _animationPriority) {
|
if (priority >= _animationPriority) {
|
||||||
glm::quat parentRotation = computeParentRotation();
|
glm::quat parentRotation = computeParentRotation();
|
||||||
|
@ -160,9 +124,6 @@ void JointState::setRotationInModelFrame(const glm::quat& rotationInModelFrame,
|
||||||
// R' = Rp * Rpre * r' * Rpost
|
// R' = Rp * Rpre * r' * Rpost
|
||||||
// r' = (Rp * Rpre)^ * R' * Rpost^
|
// r' = (Rp * Rpre)^ * R' * Rpost^
|
||||||
glm::quat targetRotation = glm::inverse(parentRotation * _preRotation) * rotationInModelFrame * glm::inverse(_postRotation);
|
glm::quat targetRotation = glm::inverse(parentRotation * _preRotation) * rotationInModelFrame * glm::inverse(_postRotation);
|
||||||
if (constrain && _constraint) {
|
|
||||||
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
|
|
||||||
}
|
|
||||||
_rotationInConstrainedFrame = glm::normalize(targetRotation);
|
_rotationInConstrainedFrame = glm::normalize(targetRotation);
|
||||||
_transformChanged = true;
|
_transformChanged = true;
|
||||||
_animationPriority = priority;
|
_animationPriority = priority;
|
||||||
|
@ -174,26 +135,15 @@ void JointState::clearTransformTranslation() {
|
||||||
_transform[3][1] = 0.0f;
|
_transform[3][1] = 0.0f;
|
||||||
_transform[3][2] = 0.0f;
|
_transform[3][2] = 0.0f;
|
||||||
_transformChanged = true;
|
_transformChanged = true;
|
||||||
_visibleTransform[3][0] = 0.0f;
|
|
||||||
_visibleTransform[3][1] = 0.0f;
|
|
||||||
_visibleTransform[3][2] = 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) {
|
void JointState::applyRotationDelta(const glm::quat& delta, float priority) {
|
||||||
// NOTE: delta is in model-frame
|
// NOTE: delta is in model-frame
|
||||||
if (priority < _animationPriority || delta == glm::quat()) {
|
if (priority < _animationPriority || delta == glm::quat()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_animationPriority = priority;
|
_animationPriority = priority;
|
||||||
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation();
|
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation();
|
||||||
if (!constrain || _constraint == NULL) {
|
|
||||||
// no constraints
|
|
||||||
_rotationInConstrainedFrame = targetRotation;
|
|
||||||
_transformChanged = true;
|
|
||||||
|
|
||||||
_rotation = delta * getRotation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setRotationInConstrainedFrameInternal(targetRotation);
|
setRotationInConstrainedFrameInternal(targetRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,36 +159,17 @@ void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float
|
||||||
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
|
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
|
||||||
targetRotation = safeMix(targetRotation, _defaultRotation, mixFactor);
|
targetRotation = safeMix(targetRotation, _defaultRotation, mixFactor);
|
||||||
}
|
}
|
||||||
if (_constraint) {
|
|
||||||
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
|
|
||||||
}
|
|
||||||
setRotationInConstrainedFrameInternal(targetRotation);
|
setRotationInConstrainedFrameInternal(targetRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor) {
|
|
||||||
// NOTE: delta is in model-frame
|
|
||||||
glm::quat targetRotation = _visibleRotationInConstrainedFrame * glm::inverse(_visibleRotation) * delta * _visibleRotation;
|
|
||||||
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
|
|
||||||
targetRotation = safeMix(targetRotation, _rotationInConstrainedFrame, mixFactor);
|
|
||||||
}
|
|
||||||
setVisibleRotationInConstrainedFrame(targetRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::quat JointState::computeParentRotation() const {
|
glm::quat JointState::computeParentRotation() const {
|
||||||
// R = Rp * Rpre * r * Rpost
|
// R = Rp * Rpre * r * Rpost
|
||||||
// Rp = R * (Rpre * r * Rpost)^
|
// Rp = R * (Rpre * r * Rpost)^
|
||||||
return getRotation() * glm::inverse(_preRotation * _rotationInConstrainedFrame * _postRotation);
|
return getRotation() * glm::inverse(_preRotation * _rotationInConstrainedFrame * _postRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat JointState::computeVisibleParentRotation() const {
|
void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, float mix) {
|
||||||
return _visibleRotation * glm::inverse(_preRotation * _visibleRotationInConstrainedFrame * _postRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain, float mix) {
|
|
||||||
if (priority >= _animationPriority || _animationPriority == 0.0f) {
|
if (priority >= _animationPriority || _animationPriority == 0.0f) {
|
||||||
if (constrain && _constraint) {
|
|
||||||
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
|
|
||||||
}
|
|
||||||
auto rotation = (mix == 1.0f) ? targetRotation : safeMix(getRotationInConstrainedFrame(), targetRotation, mix);
|
auto rotation = (mix == 1.0f) ? targetRotation : safeMix(getRotationInConstrainedFrame(), targetRotation, mix);
|
||||||
setRotationInConstrainedFrameInternal(rotation);
|
setRotationInConstrainedFrameInternal(rotation);
|
||||||
_animationPriority = priority;
|
_animationPriority = priority;
|
||||||
|
@ -255,12 +186,6 @@ void JointState::setRotationInConstrainedFrameInternal(const glm::quat& targetRo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation) {
|
|
||||||
glm::quat parentRotation = computeVisibleParentRotation();
|
|
||||||
_visibleRotationInConstrainedFrame = targetRotation;
|
|
||||||
_visibleRotation = parentRotation * _preRotation * _visibleRotationInConstrainedFrame * _postRotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) const {
|
bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) const {
|
||||||
glm::quat defaultRotation = _defaultRotation;
|
glm::quat defaultRotation = _defaultRotation;
|
||||||
return glm::abs(rotation.x - defaultRotation.x) < tolerance &&
|
return glm::abs(rotation.x - defaultRotation.x) < tolerance &&
|
||||||
|
@ -277,9 +202,3 @@ glm::quat JointState::getDefaultRotationInParentFrame() const {
|
||||||
const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const {
|
const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const {
|
||||||
return _translation;
|
return _translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::slaveVisibleTransform() {
|
|
||||||
_visibleTransform = _transform;
|
|
||||||
_visibleRotation = getRotation();
|
|
||||||
_visibleRotationInConstrainedFrame = _rotationInConstrainedFrame;
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
|
|
||||||
const float DEFAULT_PRIORITY = 3.0f;
|
const float DEFAULT_PRIORITY = 3.0f;
|
||||||
|
|
||||||
class AngularConstraint;
|
|
||||||
|
|
||||||
class JointState {
|
class JointState {
|
||||||
public:
|
public:
|
||||||
JointState() {}
|
JointState() {}
|
||||||
|
@ -39,11 +37,6 @@ public:
|
||||||
// but _rotation will be asynchronously extracted
|
// but _rotation will be asynchronously extracted
|
||||||
void computeTransform(const glm::mat4& parentTransform, bool parentTransformChanged = true, bool synchronousRotationCompute = false);
|
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; }
|
|
||||||
glm::quat getVisibleRotation() const { return _visibleRotation; }
|
|
||||||
glm::vec3 getVisiblePosition() const { return extractTranslation(_visibleTransform); }
|
|
||||||
|
|
||||||
const glm::mat4& getTransform() const { return _transform; }
|
const glm::mat4& getTransform() const { return _transform; }
|
||||||
void resetTransformChanged() { _transformChanged = false; }
|
void resetTransformChanged() { _transformChanged = false; }
|
||||||
bool getTransformChanged() const { return _transformChanged; }
|
bool getTransformChanged() const { return _transformChanged; }
|
||||||
|
@ -55,14 +48,13 @@ public:
|
||||||
glm::quat getRotationInBindFrame() const;
|
glm::quat getRotationInBindFrame() const;
|
||||||
|
|
||||||
glm::quat getRotationInParentFrame() const;
|
glm::quat getRotationInParentFrame() const;
|
||||||
glm::quat getVisibleRotationInParentFrame() const;
|
|
||||||
const glm::vec3& getPositionInParentFrame() const { return _positionInParentFrame; }
|
const glm::vec3& getPositionInParentFrame() const { return _positionInParentFrame; }
|
||||||
float getDistanceToParent() const { return _distanceToParent; }
|
float getDistanceToParent() const { return _distanceToParent; }
|
||||||
|
|
||||||
int getParentIndex() const { return _parentIndex; }
|
int getParentIndex() const { return _parentIndex; }
|
||||||
|
|
||||||
/// \param delta is in the model-frame
|
/// \param delta is in the model-frame
|
||||||
void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f);
|
void applyRotationDelta(const glm::quat& delta, float priority = 1.0f);
|
||||||
|
|
||||||
/// Applies delta rotation to joint but mixes a little bit of the default pose as well.
|
/// Applies delta rotation to joint but mixes a little bit of the default pose as well.
|
||||||
/// This helps keep an IK solution stable.
|
/// This helps keep an IK solution stable.
|
||||||
|
@ -70,7 +62,6 @@ public:
|
||||||
/// \param mixFactor fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all)
|
/// \param mixFactor fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all)
|
||||||
/// \param priority priority level of this animation blend
|
/// \param priority priority level of this animation blend
|
||||||
void mixRotationDelta(const glm::quat& delta, float mixFactor, float priority = 1.0f);
|
void mixRotationDelta(const glm::quat& delta, float mixFactor, float priority = 1.0f);
|
||||||
void mixVisibleRotationDelta(const glm::quat& delta, float mixFactor);
|
|
||||||
|
|
||||||
/// Blends a fraciton of default pose into joint rotation.
|
/// Blends a fraciton of default pose into joint rotation.
|
||||||
/// \param fraction fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all)
|
/// \param fraction fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all)
|
||||||
|
@ -80,17 +71,15 @@ public:
|
||||||
/// \param rotation is from bind- to model-frame
|
/// \param rotation is from bind- to model-frame
|
||||||
/// computes and sets new _rotationInConstrainedFrame
|
/// computes and sets new _rotationInConstrainedFrame
|
||||||
/// NOTE: the JointState's model-frame transform/rotation are NOT updated!
|
/// NOTE: the JointState's model-frame transform/rotation are NOT updated!
|
||||||
void setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain = false);
|
void setRotationInBindFrame(const glm::quat& rotation, float priority);
|
||||||
|
|
||||||
/// \param rotationInModelRame is in model-frame
|
/// \param rotationInModelRame is in model-frame
|
||||||
/// computes and sets new _rotationInConstrainedFrame to match rotationInModelFrame
|
/// computes and sets new _rotationInConstrainedFrame to match rotationInModelFrame
|
||||||
/// NOTE: the JointState's model-frame transform/rotation are NOT updated!
|
/// NOTE: the JointState's model-frame transform/rotation are NOT updated!
|
||||||
void setRotationInModelFrame(const glm::quat& rotationInModelFrame, float priority, bool constrain);
|
void setRotationInModelFrame(const glm::quat& rotationInModelFrame, float priority);
|
||||||
|
|
||||||
void setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain = false, float mix = 1.0f);
|
void setRotationInConstrainedFrame(glm::quat targetRotation, float priority, float mix = 1.0f);
|
||||||
void setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation);
|
|
||||||
const glm::quat& getRotationInConstrainedFrame() const { return _rotationInConstrainedFrame; }
|
const glm::quat& getRotationInConstrainedFrame() const { return _rotationInConstrainedFrame; }
|
||||||
const glm::quat& getVisibleRotationInConstrainedFrame() const { return _visibleRotationInConstrainedFrame; }
|
|
||||||
|
|
||||||
bool rotationIsDefault(const glm::quat& rotation, float tolerance = EPSILON) const;
|
bool rotationIsDefault(const glm::quat& rotation, float tolerance = EPSILON) const;
|
||||||
|
|
||||||
|
@ -100,15 +89,11 @@ public:
|
||||||
|
|
||||||
void clearTransformTranslation();
|
void clearTransformTranslation();
|
||||||
|
|
||||||
void slaveVisibleTransform();
|
|
||||||
|
|
||||||
/// \return parent model-frame rotation
|
/// \return parent model-frame rotation
|
||||||
// (used to keep _rotation consistent when modifying _rotationInWorldFrame directly)
|
// (used to keep _rotation consistent when modifying _rotationInWorldFrame directly)
|
||||||
glm::quat computeParentRotation() const;
|
glm::quat computeParentRotation() const;
|
||||||
glm::quat computeVisibleParentRotation() const;
|
|
||||||
|
|
||||||
void setTransform(const glm::mat4& transform) { _transform = transform; }
|
void setTransform(const glm::mat4& transform) { _transform = transform; }
|
||||||
void setVisibleTransform(const glm::mat4& transform) { _visibleTransform = transform; }
|
|
||||||
|
|
||||||
const glm::vec3& getTranslation() const { return _translation; }
|
const glm::vec3& getTranslation() const { return _translation; }
|
||||||
const glm::mat4& getPreTransform() const { return _preTransform; }
|
const glm::mat4& getPreTransform() const { return _preTransform; }
|
||||||
|
@ -132,24 +117,17 @@ private:
|
||||||
glm::vec3 _positionInParentFrame {0.0f}; // only changes when the Model is scaled
|
glm::vec3 _positionInParentFrame {0.0f}; // only changes when the Model is scaled
|
||||||
float _animationPriority {0.0f}; // the priority of the animation affecting this joint
|
float _animationPriority {0.0f}; // the priority of the animation affecting this joint
|
||||||
float _distanceToParent {0.0f};
|
float _distanceToParent {0.0f};
|
||||||
AngularConstraint* _constraint{nullptr}; // JointState owns its AngularConstraint
|
|
||||||
|
|
||||||
glm::mat4 _transform; // joint- to model-frame
|
glm::mat4 _transform; // joint- to model-frame
|
||||||
glm::quat _rotation; // joint- to model-frame
|
glm::quat _rotation; // joint- to model-frame
|
||||||
glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied
|
glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied
|
||||||
|
|
||||||
glm::mat4 _visibleTransform;
|
|
||||||
glm::quat _visibleRotation;
|
|
||||||
glm::quat _visibleRotationInConstrainedFrame;
|
|
||||||
|
|
||||||
glm::quat _defaultRotation; // Not necessarilly bind rotation. See FBXJoint transform/bindTransform
|
glm::quat _defaultRotation; // Not necessarilly bind rotation. See FBXJoint transform/bindTransform
|
||||||
glm::quat _inverseDefaultRotation;
|
glm::quat _inverseDefaultRotation;
|
||||||
glm::vec3 _translation;
|
glm::vec3 _translation;
|
||||||
QString _name;
|
QString _name;
|
||||||
int _parentIndex;
|
int _parentIndex;
|
||||||
bool _isFree;
|
bool _isFree;
|
||||||
glm::vec3 _rotationMin;
|
|
||||||
glm::vec3 _rotationMax;
|
|
||||||
glm::quat _preRotation;
|
glm::quat _preRotation;
|
||||||
glm::quat _postRotation;
|
glm::quat _postRotation;
|
||||||
glm::mat4 _preTransform;
|
glm::mat4 _preTransform;
|
||||||
|
|
|
@ -224,14 +224,6 @@ void Rig::initJointStates(QVector<JointState> states, glm::mat4 rootTransform,
|
||||||
_rightShoulderJointIndex = rightShoulderJointIndex;
|
_rightShoulderJointIndex = rightShoulderJointIndex;
|
||||||
|
|
||||||
initJointTransforms(rootTransform);
|
initJointTransforms(rootTransform);
|
||||||
|
|
||||||
int numStates = _jointStates.size();
|
|
||||||
for (int i = 0; i < numStates; ++i) {
|
|
||||||
_jointStates[i].buildConstraint();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
|
||||||
_jointStates[i].slaveVisibleTransform();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We could build and cache a dictionary, too....
|
// We could build and cache a dictionary, too....
|
||||||
|
@ -293,15 +285,6 @@ bool Rig::getJointStateRotation(int index, glm::quat& rotation) const {
|
||||||
return !state.rotationIsDefault(rotation);
|
return !state.rotationIsDefault(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Rig::getVisibleJointState(int index, glm::quat& rotation) const {
|
|
||||||
if (index == -1 || index >= _jointStates.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const JointState& state = _jointStates.at(index);
|
|
||||||
rotation = state.getVisibleRotationInConstrainedFrame();
|
|
||||||
return !state.rotationIsDefault(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rig::clearJointState(int index) {
|
void Rig::clearJointState(int index) {
|
||||||
if (index != -1 && index < _jointStates.size()) {
|
if (index != -1 && index < _jointStates.size()) {
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
|
@ -392,25 +375,6 @@ bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Rig::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position,
|
|
||||||
glm::vec3 translation, glm::quat rotation) const {
|
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// position is in world-frame
|
|
||||||
position = translation + rotation * _jointStates[jointIndex].getVisiblePosition();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Rig::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& result, glm::quat rotation) const {
|
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
result = rotation * _jointStates[jointIndex].getVisibleRotation();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 Rig::getJointTransform(int jointIndex) const {
|
glm::mat4 Rig::getJointTransform(int jointIndex) const {
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
||||||
return glm::mat4();
|
return glm::mat4();
|
||||||
|
@ -418,13 +382,6 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
|
||||||
return _jointStates[jointIndex].getTransform();
|
return _jointStates[jointIndex].getTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const {
|
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
|
||||||
return glm::mat4();
|
|
||||||
}
|
|
||||||
return _jointStates[jointIndex].getVisibleTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation) {
|
void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation) {
|
||||||
|
|
||||||
glm::vec3 front = worldRotation * IDENTITY_FRONT;
|
glm::vec3 front = worldRotation * IDENTITY_FRONT;
|
||||||
|
@ -596,7 +553,7 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
|
||||||
// copy poses into jointStates
|
// copy poses into jointStates
|
||||||
const float PRIORITY = 1.0f;
|
const float PRIORITY = 1.0f;
|
||||||
for (size_t i = 0; i < poses.size(); i++) {
|
for (size_t i = 0; i < poses.size(); i++) {
|
||||||
setJointRotationInConstrainedFrame((int)i, glm::inverse(_animSkeleton->getRelativeBindPose(i).rot) * poses[i].rot, PRIORITY, false, 1.0f);
|
setJointRotationInConstrainedFrame((int)i, glm::inverse(_animSkeleton->getRelativeBindPose(i).rot) * poses[i].rot, PRIORITY, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -719,7 +676,7 @@ bool Rig::setJointPosition(int jointIndex, const glm::vec3& position, const glm:
|
||||||
1.0f / (combinedWeight + 1.0f));
|
1.0f / (combinedWeight + 1.0f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.applyRotationDelta(combinedDelta, true, priority);
|
state.applyRotationDelta(combinedDelta, priority);
|
||||||
glm::quat actualDelta = state.getRotation() * glm::inverse(oldCombinedRotation);
|
glm::quat actualDelta = state.getRotation() * glm::inverse(oldCombinedRotation);
|
||||||
endPosition = actualDelta * jointVector + jointPosition;
|
endPosition = actualDelta * jointVector + jointPosition;
|
||||||
if (useRotation) {
|
if (useRotation) {
|
||||||
|
@ -838,11 +795,9 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q
|
||||||
|
|
||||||
// Apply the rotation delta.
|
// Apply the rotation delta.
|
||||||
glm::quat oldNextRotation = nextState.getRotation();
|
glm::quat oldNextRotation = nextState.getRotation();
|
||||||
float mixFactor = 0.05f;
|
nextState.applyRotationDelta(deltaRotation, priority);
|
||||||
nextState.applyRotationDelta(deltaRotation, mixFactor, priority);
|
|
||||||
|
|
||||||
// measure the result of the rotation which may have been modified by
|
// measure the result of the rotation which may have been modified by blending
|
||||||
// blending and constraints
|
|
||||||
glm::quat actualDelta = nextState.getRotation() * glm::inverse(oldNextRotation);
|
glm::quat actualDelta = nextState.getRotation() * glm::inverse(oldNextRotation);
|
||||||
endPosition = pivot + actualDelta * leverArm;
|
endPosition = pivot + actualDelta * leverArm;
|
||||||
}
|
}
|
||||||
|
@ -861,7 +816,7 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q
|
||||||
} while (numIterations < MAX_ITERATION_COUNT && distanceToGo > ACCEPTABLE_IK_ERROR);
|
} while (numIterations < MAX_ITERATION_COUNT && distanceToGo > ACCEPTABLE_IK_ERROR);
|
||||||
|
|
||||||
// set final rotation of the end joint
|
// set final rotation of the end joint
|
||||||
endState.setRotationInModelFrame(targetRotation, priority, true);
|
endState.setRotationInModelFrame(targetRotation, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Rig::restoreJointPosition(int jointIndex, float fraction, float priority, const QVector<int>& freeLineage) {
|
bool Rig::restoreJointPosition(int jointIndex, float fraction, float priority, const QVector<int>& freeLineage) {
|
||||||
|
@ -889,13 +844,13 @@ float Rig::getLimbLength(int jointIndex, const QVector<int>& freeLineage,
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat Rig::setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority, bool constrain) {
|
glm::quat Rig::setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority) {
|
||||||
glm::quat endRotation;
|
glm::quat endRotation;
|
||||||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||||
return endRotation;
|
return endRotation;
|
||||||
}
|
}
|
||||||
JointState& state = _jointStates[jointIndex];
|
JointState& state = _jointStates[jointIndex];
|
||||||
state.setRotationInBindFrame(rotation, priority, constrain);
|
state.setRotationInBindFrame(rotation, priority);
|
||||||
endRotation = state.getRotationInBindFrame();
|
endRotation = state.getRotationInBindFrame();
|
||||||
return endRotation;
|
return endRotation;
|
||||||
}
|
}
|
||||||
|
@ -907,13 +862,13 @@ glm::vec3 Rig::getJointDefaultTranslationInConstrainedFrame(int jointIndex) {
|
||||||
return _jointStates[jointIndex].getDefaultTranslationInConstrainedFrame();
|
return _jointStates[jointIndex].getDefaultTranslationInConstrainedFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, bool constrain, float mix) {
|
glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, float mix) {
|
||||||
glm::quat endRotation;
|
glm::quat endRotation;
|
||||||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||||
return endRotation;
|
return endRotation;
|
||||||
}
|
}
|
||||||
JointState& state = _jointStates[jointIndex];
|
JointState& state = _jointStates[jointIndex];
|
||||||
state.setRotationInConstrainedFrame(targetRotation, priority, constrain, mix);
|
state.setRotationInConstrainedFrame(targetRotation, priority, mix);
|
||||||
endRotation = state.getRotationInConstrainedFrame();
|
endRotation = state.getRotationInConstrainedFrame();
|
||||||
return endRotation;
|
return endRotation;
|
||||||
}
|
}
|
||||||
|
@ -926,30 +881,17 @@ bool Rig::getJointRotationInConstrainedFrame(int jointIndex, glm::quat& quatOut)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::updateVisibleJointStates() {
|
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
|
||||||
_jointStates[i].slaveVisibleTransform();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rig::clearJointStatePriorities() {
|
void Rig::clearJointStatePriorities() {
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
for (int i = 0; i < _jointStates.size(); i++) {
|
||||||
_jointStates[i].setAnimationPriority(0.0f);
|
_jointStates[i].setAnimationPriority(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::setJointVisibleTransform(int jointIndex, glm::mat4 newTransform) {
|
void Rig::applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority) {
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_jointStates[jointIndex].setVisibleTransform(newTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rig::applyJointRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority) {
|
|
||||||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_jointStates[jointIndex].applyRotationDelta(delta, constrain, priority);
|
_jointStates[jointIndex].applyRotationDelta(delta, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
|
glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
|
||||||
|
|
|
@ -129,7 +129,7 @@ public:
|
||||||
void clearJointTransformTranslation(int jointIndex);
|
void clearJointTransformTranslation(int jointIndex);
|
||||||
void reset(const QVector<FBXJoint>& fbxJoints);
|
void reset(const QVector<FBXJoint>& fbxJoints);
|
||||||
bool getJointStateRotation(int index, glm::quat& rotation) const;
|
bool getJointStateRotation(int index, glm::quat& rotation) const;
|
||||||
void applyJointRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority);
|
void applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority);
|
||||||
JointState getJointState(int jointIndex) const; // XXX
|
JointState getJointState(int jointIndex) const; // XXX
|
||||||
bool getVisibleJointState(int index, glm::quat& rotation) const;
|
bool getVisibleJointState(int index, glm::quat& rotation) const;
|
||||||
void clearJointState(int index);
|
void clearJointState(int index);
|
||||||
|
@ -165,10 +165,10 @@ public:
|
||||||
float getLimbLength(int jointIndex, const QVector<int>& freeLineage,
|
float getLimbLength(int jointIndex, const QVector<int>& freeLineage,
|
||||||
const glm::vec3 scale, const QVector<FBXJoint>& fbxJoints) const;
|
const glm::vec3 scale, const QVector<FBXJoint>& fbxJoints) const;
|
||||||
|
|
||||||
glm::quat setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority, bool constrain = false);
|
glm::quat setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority);
|
||||||
glm::vec3 getJointDefaultTranslationInConstrainedFrame(int jointIndex);
|
glm::vec3 getJointDefaultTranslationInConstrainedFrame(int jointIndex);
|
||||||
glm::quat setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation,
|
glm::quat setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation,
|
||||||
float priority, bool constrain = false, float mix = 1.0f);
|
float priority, float mix = 1.0f);
|
||||||
bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const;
|
bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const;
|
||||||
glm::quat getJointDefaultRotationInParentFrame(int jointIndex);
|
glm::quat getJointDefaultRotationInParentFrame(int jointIndex);
|
||||||
void updateVisibleJointStates();
|
void updateVisibleJointStates();
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
//
|
|
||||||
// Constraint.h
|
|
||||||
// libraries/physics/src
|
|
||||||
//
|
|
||||||
// Created by Andrew Meadows 2014.07.24
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_Constraint_h
|
|
||||||
#define hifi_Constraint_h
|
|
||||||
|
|
||||||
class Constraint {
|
|
||||||
public:
|
|
||||||
Constraint() {}
|
|
||||||
virtual ~Constraint() {}
|
|
||||||
|
|
||||||
/// Enforce contraint by moving relevant points.
|
|
||||||
/// \return max distance of point movement
|
|
||||||
virtual float enforce() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_Constraint_h
|
|
|
@ -68,7 +68,6 @@ Model::Model(RigPointer rig, QObject* parent) :
|
||||||
_scaledToFit(false),
|
_scaledToFit(false),
|
||||||
_snapModelToRegistrationPoint(false),
|
_snapModelToRegistrationPoint(false),
|
||||||
_snappedToRegistrationPoint(false),
|
_snappedToRegistrationPoint(false),
|
||||||
_showTrueJointTransforms(true),
|
|
||||||
_cauterizeBones(false),
|
_cauterizeBones(false),
|
||||||
_pupilDilation(0.0f),
|
_pupilDilation(0.0f),
|
||||||
_url(HTTP_INVALID_COM),
|
_url(HTTP_INVALID_COM),
|
||||||
|
@ -998,10 +997,6 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
|
||||||
return _rig->getJointStateRotation(index, rotation);
|
return _rig->getJointStateRotation(index, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::getVisibleJointState(int index, glm::quat& rotation) const {
|
|
||||||
return _rig->getVisibleJointState(index, rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::clearJointState(int index) {
|
void Model::clearJointState(int index) {
|
||||||
_rig->clearJointState(index);
|
_rig->clearJointState(index);
|
||||||
}
|
}
|
||||||
|
@ -1083,14 +1078,6 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const
|
||||||
return _rig->getJointCombinedRotation(jointIndex, rotation, _rotation);
|
return _rig->getJointCombinedRotation(jointIndex, rotation, _rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const {
|
|
||||||
return _rig->getVisibleJointPositionInWorldFrame(jointIndex, position, _translation, _rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Model::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const {
|
|
||||||
return _rig->getVisibleJointRotationInWorldFrame(jointIndex, rotation, _rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList Model::getJointNames() const {
|
QStringList Model::getJointNames() const {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
@ -1294,33 +1281,17 @@ void Model::updateClusterMatrices() {
|
||||||
for (int i = 0; i < _meshStates.size(); i++) {
|
for (int i = 0; i < _meshStates.size(); i++) {
|
||||||
MeshState& state = _meshStates[i];
|
MeshState& state = _meshStates[i];
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
if (_showTrueJointTransforms) {
|
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
|
||||||
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
|
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
||||||
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
|
||||||
|
|
||||||
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
||||||
if (!_cauterizeBoneSet.empty()) {
|
if (!_cauterizeBoneSet.empty()) {
|
||||||
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
|
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
|
||||||
jointMatrix = cauterizeMatrix;
|
jointMatrix = cauterizeMatrix;
|
||||||
}
|
|
||||||
state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
|
||||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
|
||||||
auto jointMatrix = _rig->getJointVisibleTransform(cluster.jointIndex); // differs from above only in using get...VisibleTransform
|
|
||||||
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
|
||||||
|
|
||||||
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
|
||||||
if (!_cauterizeBoneSet.empty()) {
|
|
||||||
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
|
|
||||||
jointMatrix = cauterizeMatrix;
|
|
||||||
}
|
|
||||||
state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
|
||||||
}
|
}
|
||||||
|
state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1533,13 +1504,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shape
|
||||||
pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe,
|
pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe,
|
||||||
args, locations);
|
args, locations);
|
||||||
|
|
||||||
{
|
|
||||||
if (!_showTrueJointTransforms) {
|
|
||||||
PerformanceTimer perfTimer("_rig->updateVisibleJointStates()");
|
|
||||||
_rig->updateVisibleJointStates();
|
|
||||||
} // else no need to update visible transforms
|
|
||||||
}
|
|
||||||
|
|
||||||
// if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown
|
// if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown
|
||||||
// to false to rebuild out mesh groups.
|
// to false to rebuild out mesh groups.
|
||||||
if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) {
|
if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) {
|
||||||
|
|
|
@ -221,26 +221,17 @@ protected:
|
||||||
/// \return whether or not the joint state is "valid" (that is, non-default)
|
/// \return whether or not the joint state is "valid" (that is, non-default)
|
||||||
bool getJointState(int index, glm::quat& rotation) const;
|
bool getJointState(int index, glm::quat& rotation) const;
|
||||||
|
|
||||||
/// Fetches the visible joint state at the specified index.
|
|
||||||
/// \return whether or not the joint state is "valid" (that is, non-default)
|
|
||||||
bool getVisibleJointState(int index, glm::quat& rotation) const;
|
|
||||||
|
|
||||||
/// Clear the joint states
|
/// Clear the joint states
|
||||||
void clearJointState(int index);
|
void clearJointState(int index);
|
||||||
|
|
||||||
/// Returns the index of the last free ancestor of the indexed joint, or -1 if not found.
|
/// Returns the index of the last free ancestor of the indexed joint, or -1 if not found.
|
||||||
int getLastFreeJointIndex(int jointIndex) const;
|
int getLastFreeJointIndex(int jointIndex) const;
|
||||||
|
|
||||||
bool getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const;
|
|
||||||
bool getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const;
|
|
||||||
|
|
||||||
/// \param jointIndex index of joint in model structure
|
/// \param jointIndex index of joint in model structure
|
||||||
/// \param position[out] position of joint in model-frame
|
/// \param position[out] position of joint in model-frame
|
||||||
/// \return true if joint exists
|
/// \return true if joint exists
|
||||||
bool getJointPosition(int jointIndex, glm::vec3& position) const;
|
bool getJointPosition(int jointIndex, glm::vec3& position) const;
|
||||||
|
|
||||||
void setShowTrueJointTransforms(bool show) { _showTrueJointTransforms = show; }
|
|
||||||
|
|
||||||
QSharedPointer<NetworkGeometry> _geometry;
|
QSharedPointer<NetworkGeometry> _geometry;
|
||||||
void setGeometry(const QSharedPointer<NetworkGeometry>& newGeometry);
|
void setGeometry(const QSharedPointer<NetworkGeometry>& newGeometry);
|
||||||
|
|
||||||
|
@ -259,8 +250,6 @@ protected:
|
||||||
bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point
|
bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point
|
||||||
glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to
|
glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to
|
||||||
|
|
||||||
bool _showTrueJointTransforms;
|
|
||||||
|
|
||||||
class MeshState {
|
class MeshState {
|
||||||
public:
|
public:
|
||||||
QVector<glm::mat4> clusterMatrices;
|
QVector<glm::mat4> clusterMatrices;
|
||||||
|
|
|
@ -1,202 +0,0 @@
|
||||||
//
|
|
||||||
// AngularConstraint.cpp
|
|
||||||
// interface/src/renderer
|
|
||||||
//
|
|
||||||
// Created by Andrew Meadows on 2014.05.30
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <glm/gtx/norm.hpp>
|
|
||||||
|
|
||||||
#include "AngularConstraint.h"
|
|
||||||
#include "GLMHelpers.h"
|
|
||||||
#include "NumericalConstants.h"
|
|
||||||
|
|
||||||
// helper function
|
|
||||||
/// \param angle radian angle to be clamped within angleMin and angleMax
|
|
||||||
/// \param angleMin minimum value
|
|
||||||
/// \param angleMax maximum value
|
|
||||||
/// \return value between minAngle and maxAngle closest to angle
|
|
||||||
float clampAngle(float angle, float angleMin, float angleMax) {
|
|
||||||
float minDistance = angle - angleMin;
|
|
||||||
float maxDistance = angle - angleMax;
|
|
||||||
if (maxDistance > 0.0f) {
|
|
||||||
minDistance = glm::min(minDistance, angleMin + TWO_PI - angle);
|
|
||||||
angle = (minDistance < maxDistance) ? angleMin : angleMax;
|
|
||||||
} else if (minDistance < 0.0f) {
|
|
||||||
maxDistance = glm::max(maxDistance, angleMax - TWO_PI - angle);
|
|
||||||
angle = (minDistance > maxDistance) ? angleMin : angleMax;
|
|
||||||
}
|
|
||||||
return angle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
AngularConstraint* AngularConstraint::newAngularConstraint(const glm::vec3& minAngles, const glm::vec3& maxAngles) {
|
|
||||||
float minDistance2 = glm::distance2(minAngles, glm::vec3(-PI, -PI, -PI));
|
|
||||||
float maxDistance2 = glm::distance2(maxAngles, glm::vec3(PI, PI, PI));
|
|
||||||
if (minDistance2 < EPSILON && maxDistance2 < EPSILON) {
|
|
||||||
// no constraint
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// count the zero length elements
|
|
||||||
glm::vec3 rangeAngles = maxAngles - minAngles;
|
|
||||||
int pivotIndex = -1;
|
|
||||||
int numZeroes = 0;
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
if (rangeAngles[i] < EPSILON) {
|
|
||||||
++numZeroes;
|
|
||||||
} else {
|
|
||||||
pivotIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (numZeroes == 2) {
|
|
||||||
// this is a hinge
|
|
||||||
int forwardIndex = (pivotIndex + 1) % 3;
|
|
||||||
glm::vec3 forwardAxis(0.0f);
|
|
||||||
forwardAxis[forwardIndex] = 1.0f;
|
|
||||||
glm::vec3 rotationAxis(0.0f);
|
|
||||||
rotationAxis[pivotIndex] = 1.0f;
|
|
||||||
return new HingeConstraint(forwardAxis, rotationAxis, minAngles[pivotIndex], maxAngles[pivotIndex]);
|
|
||||||
} else if (numZeroes == 0) {
|
|
||||||
// approximate the angular limits with a cone roller
|
|
||||||
// we assume the roll is about z
|
|
||||||
glm::vec3 middleAngles = 0.5f * (maxAngles + minAngles);
|
|
||||||
glm::quat yaw = glm::angleAxis(middleAngles[1], glm::vec3(0.0f, 1.0f, 0.0f));
|
|
||||||
glm::quat pitch = glm::angleAxis(middleAngles[0], glm::vec3(1.0f, 0.0f, 0.0f));
|
|
||||||
glm::vec3 coneAxis = pitch * yaw * glm::vec3(0.0f, 0.0f, 1.0f);
|
|
||||||
// the coneAngle is half the average range of the two non-roll rotations
|
|
||||||
glm::vec3 range = maxAngles - minAngles;
|
|
||||||
float coneAngle = 0.25f * (range[0] + range[1]);
|
|
||||||
return new ConeRollerConstraint(coneAngle, coneAxis, minAngles.z, maxAngles.z);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AngularConstraint::softClamp(glm::quat& targetRotation, const glm::quat& oldRotation, float mixFraction) {
|
|
||||||
glm::quat clampedTarget = targetRotation;
|
|
||||||
bool clamped = clamp(clampedTarget);
|
|
||||||
if (clamped) {
|
|
||||||
// check if oldRotation is also clamped
|
|
||||||
glm::quat clampedOld = oldRotation;
|
|
||||||
bool clamped2 = clamp(clampedOld);
|
|
||||||
if (clamped2) {
|
|
||||||
// oldRotation is already beyond the constraint
|
|
||||||
// we clamp again midway between targetRotation and clamped oldPosition
|
|
||||||
clampedTarget = glm::shortMix(clampedOld, targetRotation, mixFraction);
|
|
||||||
// and then clamp that
|
|
||||||
clamp(clampedTarget);
|
|
||||||
}
|
|
||||||
// finally we mix targetRotation with the clampedTarget
|
|
||||||
targetRotation = glm::shortMix(clampedTarget, targetRotation, mixFraction);
|
|
||||||
}
|
|
||||||
return clamped;
|
|
||||||
}
|
|
||||||
|
|
||||||
HingeConstraint::HingeConstraint(const glm::vec3& forwardAxis, const glm::vec3& rotationAxis, float minAngle, float maxAngle)
|
|
||||||
: _minAngle(minAngle), _maxAngle(maxAngle) {
|
|
||||||
assert(_minAngle < _maxAngle);
|
|
||||||
// we accept the rotationAxis direction
|
|
||||||
assert(glm::length(rotationAxis) > EPSILON);
|
|
||||||
_rotationAxis = glm::normalize(rotationAxis);
|
|
||||||
// but we compute the final _forwardAxis
|
|
||||||
glm::vec3 otherAxis = glm::cross(_rotationAxis, forwardAxis);
|
|
||||||
assert(glm::length(otherAxis) > EPSILON);
|
|
||||||
_forwardAxis = glm::normalize(glm::cross(otherAxis, _rotationAxis));
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
bool HingeConstraint::clamp(glm::quat& rotation) const {
|
|
||||||
glm::vec3 forward = rotation * _forwardAxis;
|
|
||||||
forward -= glm::dot(forward, _rotationAxis) * _rotationAxis;
|
|
||||||
float length = glm::length(forward);
|
|
||||||
if (length < EPSILON) {
|
|
||||||
// infinite number of solutions ==> choose the middle of the contrained range
|
|
||||||
rotation = glm::angleAxis(0.5f * (_minAngle + _maxAngle), _rotationAxis);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
forward /= length;
|
|
||||||
float sign = (glm::dot(glm::cross(_forwardAxis, forward), _rotationAxis) > 0.0f ? 1.0f : -1.0f);
|
|
||||||
//float angle = sign * acos(glm::dot(forward, _forwardAxis) / length);
|
|
||||||
float angle = sign * acosf(glm::dot(forward, _forwardAxis));
|
|
||||||
glm::quat newRotation = glm::angleAxis(clampAngle(angle, _minAngle, _maxAngle), _rotationAxis);
|
|
||||||
if (fabsf(1.0f - glm::dot(newRotation, rotation)) > EPSILON * EPSILON) {
|
|
||||||
rotation = newRotation;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HingeConstraint::softClamp(glm::quat& targetRotation, const glm::quat& oldRotation, float mixFraction) {
|
|
||||||
// the hinge works best without a soft clamp
|
|
||||||
return clamp(targetRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConeRollerConstraint::ConeRollerConstraint(float coneAngle, const glm::vec3& coneAxis, float minRoll, float maxRoll)
|
|
||||||
: _coneAngle(coneAngle), _minRoll(minRoll), _maxRoll(maxRoll) {
|
|
||||||
assert(_maxRoll >= _minRoll);
|
|
||||||
float axisLength = glm::length(coneAxis);
|
|
||||||
assert(axisLength > EPSILON);
|
|
||||||
_coneAxis = coneAxis / axisLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
bool ConeRollerConstraint::clamp(glm::quat& rotation) const {
|
|
||||||
bool applied = false;
|
|
||||||
glm::vec3 rotatedAxis = rotation * _coneAxis;
|
|
||||||
glm::vec3 perpAxis = glm::cross(rotatedAxis, _coneAxis);
|
|
||||||
float perpAxisLength = glm::length(perpAxis);
|
|
||||||
if (perpAxisLength > EPSILON) {
|
|
||||||
perpAxis /= perpAxisLength;
|
|
||||||
// enforce the cone
|
|
||||||
float angle = acosf(glm::dot(rotatedAxis, _coneAxis));
|
|
||||||
if (angle > _coneAngle) {
|
|
||||||
rotation = glm::angleAxis(angle - _coneAngle, perpAxis) * rotation;
|
|
||||||
rotatedAxis = rotation * _coneAxis;
|
|
||||||
applied = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// the rotation is 100% roll
|
|
||||||
// there is no obvious perp axis so we must pick one
|
|
||||||
perpAxis = rotatedAxis;
|
|
||||||
// find the first non-zero element:
|
|
||||||
float iValue = 0.0f;
|
|
||||||
int i = 0;
|
|
||||||
for (i = 0; i < 3; ++i) {
|
|
||||||
if (fabsf(perpAxis[i]) > EPSILON) {
|
|
||||||
iValue = perpAxis[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(i != 3);
|
|
||||||
// swap or negate the next element
|
|
||||||
int j = (i + 1) % 3;
|
|
||||||
float jValue = perpAxis[j];
|
|
||||||
if (fabsf(jValue - iValue) > EPSILON) {
|
|
||||||
perpAxis[i] = jValue;
|
|
||||||
perpAxis[j] = iValue;
|
|
||||||
} else {
|
|
||||||
perpAxis[i] = -iValue;
|
|
||||||
}
|
|
||||||
perpAxis = glm::cross(perpAxis, rotatedAxis);
|
|
||||||
perpAxisLength = glm::length(perpAxis);
|
|
||||||
assert(perpAxisLength > EPSILON);
|
|
||||||
perpAxis /= perpAxisLength;
|
|
||||||
}
|
|
||||||
// measure the roll
|
|
||||||
// NOTE: perpAxis is perpendicular to both _coneAxis and rotatedConeAxis, so we can
|
|
||||||
// rotate it again and we'll end up with an something that has only been rolled.
|
|
||||||
glm::vec3 rolledPerpAxis = rotation * perpAxis;
|
|
||||||
float sign = glm::dot(rotatedAxis, glm::cross(perpAxis, rolledPerpAxis)) > 0.0f ? 1.0f : -1.0f;
|
|
||||||
float roll = sign * angleBetween(rolledPerpAxis, perpAxis);
|
|
||||||
if (roll < _minRoll || roll > _maxRoll) {
|
|
||||||
float clampedRoll = clampAngle(roll, _minRoll, _maxRoll);
|
|
||||||
rotation = glm::normalize(glm::angleAxis(clampedRoll - roll, rotatedAxis) * rotation);
|
|
||||||
applied = true;
|
|
||||||
}
|
|
||||||
return applied;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
//
|
|
||||||
// AngularConstraint.h
|
|
||||||
// interface/src/renderer
|
|
||||||
//
|
|
||||||
// Created by Andrew Meadows on 2014.05.30
|
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_AngularConstraint_h
|
|
||||||
#define hifi_AngularConstraint_h
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
class AngularConstraint {
|
|
||||||
public:
|
|
||||||
/// \param minAngles minumum euler angles for the constraint
|
|
||||||
/// \param maxAngles minumum euler angles for the constraint
|
|
||||||
/// \return pointer to new AngularConstraint of the right type or NULL if none could be made
|
|
||||||
static AngularConstraint* newAngularConstraint(const glm::vec3& minAngles, const glm::vec3& maxAngles);
|
|
||||||
|
|
||||||
AngularConstraint() {}
|
|
||||||
virtual ~AngularConstraint() {}
|
|
||||||
virtual bool clamp(glm::quat& rotation) const = 0;
|
|
||||||
virtual bool softClamp(glm::quat& targetRotation, const glm::quat& oldRotation, float mixFraction);
|
|
||||||
protected:
|
|
||||||
};
|
|
||||||
|
|
||||||
class HingeConstraint : public AngularConstraint {
|
|
||||||
public:
|
|
||||||
HingeConstraint(const glm::vec3& forwardAxis, const glm::vec3& rotationAxis, float minAngle, float maxAngle);
|
|
||||||
virtual bool clamp(glm::quat& rotation) const;
|
|
||||||
virtual bool softClamp(glm::quat& targetRotation, const glm::quat& oldRotation, float mixFraction);
|
|
||||||
protected:
|
|
||||||
glm::vec3 _forwardAxis;
|
|
||||||
glm::vec3 _rotationAxis;
|
|
||||||
float _minAngle;
|
|
||||||
float _maxAngle;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConeRollerConstraint : public AngularConstraint {
|
|
||||||
public:
|
|
||||||
ConeRollerConstraint(float coneAngle, const glm::vec3& coneAxis, float minRoll, float maxRoll);
|
|
||||||
virtual bool clamp(glm::quat& rotation) const;
|
|
||||||
private:
|
|
||||||
float _coneAngle;
|
|
||||||
glm::vec3 _coneAxis;
|
|
||||||
float _minRoll;
|
|
||||||
float _maxRoll;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_AngularConstraint_h
|
|
Loading…
Reference in a new issue