Merge pull request #5975 from AndrewMeadows/cleanup-legacy-constraints

remove cruft relating to old verlet avatar skeleton simulation
This commit is contained in:
Howard Stearns 2015-10-01 16:48:33 -07:00
commit 53e7d5fd7c
11 changed files with 32 additions and 522 deletions

View file

@ -320,7 +320,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position)
float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
_rig->applyJointRotationDelta(jointIndex,
rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector),
true, PALM_PRIORITY);
PALM_PRIORITY);
}
void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {

View file

@ -181,7 +181,6 @@ void AnimationHandle::applyFrame(float frameIndex) {
ceilFrame.rotations.at(i),
frameFraction),
_priority,
false,
_mix);
}
}

View file

@ -13,16 +13,11 @@
#include <QThreadPool>
#include <AngularConstraint.h>
#include <SharedUtil.h>
#include "JointState.h"
JointState::~JointState() {
if (_constraint) {
delete _constraint;
_constraint = NULL;
}
}
void JointState::copyState(const JointState& other) {
@ -35,18 +30,12 @@ void JointState::copyState(const JointState& other) {
_distanceToParent = other._distanceToParent;
_animationPriority = other._animationPriority;
_visibleTransform = other._visibleTransform;
_visibleRotation = extractRotation(_visibleTransform);
_visibleRotationInConstrainedFrame = other._visibleRotationInConstrainedFrame;
// DO NOT copy _constraint
_name = other._name;
_isFree = other._isFree;
_parentIndex = other._parentIndex;
_defaultRotation = other._defaultRotation;
_inverseDefaultRotation = other._inverseDefaultRotation;
_translation = other._translation;
_rotationMin = other._rotationMin;
_rotationMax = other._rotationMax;
_preRotation = other._preRotation;
_postRotation = other._postRotation;
_preTransform = other._preTransform;
@ -61,8 +50,6 @@ JointState::JointState(const FBXJoint& joint) {
_translation = joint.translation;
_defaultRotation = joint.rotation;
_inverseDefaultRotation = joint.inverseDefaultRotation;
_rotationMin = joint.rotationMin;
_rotationMax = joint.rotationMax;
_preRotation = joint.preRotation;
_postRotation = joint.postRotation;
_preTransform = joint.preTransform;
@ -71,15 +58,6 @@ JointState::JointState(const FBXJoint& joint) {
}
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 {
@ -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 {
return getRotation() * _inverseBindRotation;
}
@ -128,10 +99,6 @@ glm::quat JointState::getRotationInParentFrame() const {
return _preRotation * _rotationInConstrainedFrame * _postRotation;
}
glm::quat JointState::getVisibleRotationInParentFrame() const {
return _preRotation * _visibleRotationInConstrainedFrame * _postRotation;
}
void JointState::restoreRotation(float fraction, float priority) {
if (priority == _animationPriority || _animationPriority == 0.0f) {
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
if (priority >= _animationPriority) {
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_inverseBindRotation);
if (constrain && _constraint) {
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
}
setRotationInConstrainedFrameInternal(targetRotation);
_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
if (priority >= _animationPriority) {
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^
glm::quat targetRotation = glm::inverse(parentRotation * _preRotation) * rotationInModelFrame * glm::inverse(_postRotation);
if (constrain && _constraint) {
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
}
_rotationInConstrainedFrame = glm::normalize(targetRotation);
_transformChanged = true;
_animationPriority = priority;
@ -174,26 +135,15 @@ void JointState::clearTransformTranslation() {
_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::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) {
void JointState::applyRotationDelta(const glm::quat& delta, float priority) {
// NOTE: delta is in model-frame
if (priority < _animationPriority || delta == glm::quat()) {
return;
}
_animationPriority = priority;
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);
}
@ -209,36 +159,17 @@ void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
targetRotation = safeMix(targetRotation, _defaultRotation, mixFactor);
}
if (_constraint) {
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
}
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 {
// R = Rp * Rpre * r * Rpost
// Rp = R * (Rpre * r * Rpost)^
return getRotation() * glm::inverse(_preRotation * _rotationInConstrainedFrame * _postRotation);
}
glm::quat JointState::computeVisibleParentRotation() const {
return _visibleRotation * glm::inverse(_preRotation * _visibleRotationInConstrainedFrame * _postRotation);
}
void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain, float mix) {
void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, float mix) {
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);
setRotationInConstrainedFrameInternal(rotation);
_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 {
glm::quat defaultRotation = _defaultRotation;
return glm::abs(rotation.x - defaultRotation.x) < tolerance &&
@ -277,9 +202,3 @@ glm::quat JointState::getDefaultRotationInParentFrame() const {
const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const {
return _translation;
}
void JointState::slaveVisibleTransform() {
_visibleTransform = _transform;
_visibleRotation = getRotation();
_visibleRotationInConstrainedFrame = _rotationInConstrainedFrame;
}

View file

@ -22,8 +22,6 @@
const float DEFAULT_PRIORITY = 3.0f;
class AngularConstraint;
class JointState {
public:
JointState() {}
@ -39,11 +37,6 @@ public:
// 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; }
glm::quat getVisibleRotation() const { return _visibleRotation; }
glm::vec3 getVisiblePosition() const { return extractTranslation(_visibleTransform); }
const glm::mat4& getTransform() const { return _transform; }
void resetTransformChanged() { _transformChanged = false; }
bool getTransformChanged() const { return _transformChanged; }
@ -55,14 +48,13 @@ public:
glm::quat getRotationInBindFrame() const;
glm::quat getRotationInParentFrame() const;
glm::quat getVisibleRotationInParentFrame() const;
const glm::vec3& getPositionInParentFrame() const { return _positionInParentFrame; }
float getDistanceToParent() const { return _distanceToParent; }
int getParentIndex() const { return _parentIndex; }
/// \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.
/// 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 priority priority level of this animation blend
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.
/// \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
/// computes and sets new _rotationInConstrainedFrame
/// 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
/// computes and sets new _rotationInConstrainedFrame to match rotationInModelFrame
/// 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 setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation);
void setRotationInConstrainedFrame(glm::quat targetRotation, float priority, float mix = 1.0f);
const glm::quat& getRotationInConstrainedFrame() const { return _rotationInConstrainedFrame; }
const glm::quat& getVisibleRotationInConstrainedFrame() const { return _visibleRotationInConstrainedFrame; }
bool rotationIsDefault(const glm::quat& rotation, float tolerance = EPSILON) const;
@ -100,15 +89,11 @@ public:
void clearTransformTranslation();
void slaveVisibleTransform();
/// \return parent model-frame rotation
// (used to keep _rotation consistent when modifying _rotationInWorldFrame directly)
glm::quat computeParentRotation() const;
glm::quat computeVisibleParentRotation() const;
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::mat4& getPreTransform() const { return _preTransform; }
@ -132,24 +117,17 @@ private:
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 _distanceToParent {0.0f};
AngularConstraint* _constraint{nullptr}; // JointState owns its AngularConstraint
glm::mat4 _transform; // joint- to model-frame
glm::quat _rotation; // joint- to model-frame
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 _inverseDefaultRotation;
glm::vec3 _translation;
QString _name;
int _parentIndex;
bool _isFree;
glm::vec3 _rotationMin;
glm::vec3 _rotationMax;
glm::quat _preRotation;
glm::quat _postRotation;
glm::mat4 _preTransform;

View file

@ -224,14 +224,6 @@ void Rig::initJointStates(QVector<JointState> states, glm::mat4 rootTransform,
_rightShoulderJointIndex = rightShoulderJointIndex;
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....
@ -293,15 +285,6 @@ bool Rig::getJointStateRotation(int index, glm::quat& rotation) const {
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) {
if (index != -1 && index < _jointStates.size()) {
JointState& state = _jointStates[index];
@ -392,25 +375,6 @@ bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm:
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 {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return glm::mat4();
@ -418,13 +382,6 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
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) {
glm::vec3 front = worldRotation * IDENTITY_FRONT;
@ -596,7 +553,7 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
// copy poses into jointStates
const float PRIORITY = 1.0f;
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 {
@ -719,7 +676,7 @@ bool Rig::setJointPosition(int jointIndex, const glm::vec3& position, const glm:
1.0f / (combinedWeight + 1.0f));
}
}
state.applyRotationDelta(combinedDelta, true, priority);
state.applyRotationDelta(combinedDelta, priority);
glm::quat actualDelta = state.getRotation() * glm::inverse(oldCombinedRotation);
endPosition = actualDelta * jointVector + jointPosition;
if (useRotation) {
@ -838,11 +795,9 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q
// Apply the rotation delta.
glm::quat oldNextRotation = nextState.getRotation();
float mixFactor = 0.05f;
nextState.applyRotationDelta(deltaRotation, mixFactor, priority);
nextState.applyRotationDelta(deltaRotation, priority);
// measure the result of the rotation which may have been modified by
// blending and constraints
// measure the result of the rotation which may have been modified by blending
glm::quat actualDelta = nextState.getRotation() * glm::inverse(oldNextRotation);
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);
// 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) {
@ -889,13 +844,13 @@ float Rig::getLimbLength(int jointIndex, const QVector<int>& freeLineage,
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;
if (jointIndex == -1 || _jointStates.isEmpty()) {
return endRotation;
}
JointState& state = _jointStates[jointIndex];
state.setRotationInBindFrame(rotation, priority, constrain);
state.setRotationInBindFrame(rotation, priority);
endRotation = state.getRotationInBindFrame();
return endRotation;
}
@ -907,13 +862,13 @@ glm::vec3 Rig::getJointDefaultTranslationInConstrainedFrame(int jointIndex) {
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;
if (jointIndex == -1 || _jointStates.isEmpty()) {
return endRotation;
}
JointState& state = _jointStates[jointIndex];
state.setRotationInConstrainedFrame(targetRotation, priority, constrain, mix);
state.setRotationInConstrainedFrame(targetRotation, priority, mix);
endRotation = state.getRotationInConstrainedFrame();
return endRotation;
}
@ -926,30 +881,17 @@ bool Rig::getJointRotationInConstrainedFrame(int jointIndex, glm::quat& quatOut)
return true;
}
void Rig::updateVisibleJointStates() {
for (int i = 0; i < _jointStates.size(); i++) {
_jointStates[i].slaveVisibleTransform();
}
}
void Rig::clearJointStatePriorities() {
for (int i = 0; i < _jointStates.size(); i++) {
_jointStates[i].setAnimationPriority(0.0f);
}
}
void Rig::setJointVisibleTransform(int jointIndex, glm::mat4 newTransform) {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return;
}
_jointStates[jointIndex].setVisibleTransform(newTransform);
}
void Rig::applyJointRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority) {
void Rig::applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority) {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return;
}
_jointStates[jointIndex].applyRotationDelta(delta, constrain, priority);
_jointStates[jointIndex].applyRotationDelta(delta, priority);
}
glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {

View file

@ -129,7 +129,7 @@ public:
void clearJointTransformTranslation(int jointIndex);
void reset(const QVector<FBXJoint>& fbxJoints);
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
bool getVisibleJointState(int index, glm::quat& rotation) const;
void clearJointState(int index);
@ -165,10 +165,10 @@ public:
float getLimbLength(int jointIndex, const QVector<int>& freeLineage,
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::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;
glm::quat getJointDefaultRotationInParentFrame(int jointIndex);
void updateVisibleJointStates();

View file

@ -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

View file

@ -68,7 +68,6 @@ Model::Model(RigPointer rig, QObject* parent) :
_scaledToFit(false),
_snapModelToRegistrationPoint(false),
_snappedToRegistrationPoint(false),
_showTrueJointTransforms(true),
_cauterizeBones(false),
_pupilDilation(0.0f),
_url(HTTP_INVALID_COM),
@ -998,10 +997,6 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
return _rig->getJointStateRotation(index, rotation);
}
bool Model::getVisibleJointState(int index, glm::quat& rotation) const {
return _rig->getVisibleJointState(index, rotation);
}
void Model::clearJointState(int index) {
_rig->clearJointState(index);
}
@ -1083,14 +1078,6 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const
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 {
if (QThread::currentThread() != thread()) {
QStringList result;
@ -1294,33 +1281,17 @@ void Model::updateClusterMatrices() {
for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
if (_showTrueJointTransforms) {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
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;
}
}
} 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;
// 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;
}
}
}
@ -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,
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
// to false to rebuild out mesh groups.
if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) {

View file

@ -221,26 +221,17 @@ protected:
/// \return whether or not the joint state is "valid" (that is, non-default)
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
void clearJointState(int index);
/// Returns the index of the last free ancestor of the indexed joint, or -1 if not found.
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 position[out] position of joint in model-frame
/// \return true if joint exists
bool getJointPosition(int jointIndex, glm::vec3& position) const;
void setShowTrueJointTransforms(bool show) { _showTrueJointTransforms = show; }
QSharedPointer<NetworkGeometry> _geometry;
void setGeometry(const QSharedPointer<NetworkGeometry>& newGeometry);
@ -259,8 +250,6 @@ protected:
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
bool _showTrueJointTransforms;
class MeshState {
public:
QVector<glm::mat4> clusterMatrices;

View file

@ -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;
}

View file

@ -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