mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +02:00
Merge pull request #5975 from AndrewMeadows/cleanup-legacy-constraints
remove cruft relating to old verlet avatar skeleton simulation
This commit is contained in:
commit
53e7d5fd7c
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;
|
||||
_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) {
|
||||
|
|
|
@ -181,7 +181,6 @@ void AnimationHandle::applyFrame(float frameIndex) {
|
|||
ceilFrame.rotations.at(i),
|
||||
frameFraction),
|
||||
_priority,
|
||||
false,
|
||||
_mix);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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),
|
||||
_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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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