get rid of _firstPersonSkeletonModel in MyAvatar. add flag in Rig for joints being dirty so Model knows when to recompute meshes

This commit is contained in:
Seth Alves 2015-07-23 15:14:10 -07:00
parent 4566d16402
commit 33c97a1833
9 changed files with 137 additions and 140 deletions

View file

@ -103,11 +103,8 @@ MyAvatar::MyAvatar(RigPointer rig) :
_realWorldFieldOfView("realWorldFieldOfView", _realWorldFieldOfView("realWorldFieldOfView",
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
_rig(rig), _rig(rig),
_firstPersonSkeletonModel(this, nullptr, rig),
_prevShouldDrawHead(true) _prevShouldDrawHead(true)
{ {
_firstPersonSkeletonModel.setIsFirstPerson(true);
ShapeCollider::initDispatchTable(); ShapeCollider::initDispatchTable();
for (int i = 0; i < MAX_DRIVE_KEYS; i++) { for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
_driveKeys[i] = 0.0f; _driveKeys[i] = 0.0f;
@ -141,7 +138,6 @@ QByteArray MyAvatar::toByteArray() {
void MyAvatar::reset() { void MyAvatar::reset() {
_skeletonModel.reset(); _skeletonModel.reset();
_firstPersonSkeletonModel.reset();
getHead()->reset(); getHead()->reset();
_targetVelocity = glm::vec3(0.0f); _targetVelocity = glm::vec3(0.0f);
@ -200,7 +196,6 @@ void MyAvatar::simulate(float deltaTime) {
{ {
PerformanceTimer perfTimer("skeleton"); PerformanceTimer perfTimer("skeleton");
_skeletonModel.simulate(deltaTime); _skeletonModel.simulate(deltaTime);
_firstPersonSkeletonModel.simulate(deltaTime);
} }
if (!_skeletonModel.hasSkeleton()) { if (!_skeletonModel.hasSkeleton()) {
@ -1028,15 +1023,8 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
if (_useFullAvatar) { if (_useFullAvatar) {
_skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene); _skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene);
const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst");
_firstPersonSkeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
_firstPersonSkeletonModel.setVisibleInScene(!_prevShouldDrawHead, scene);
} else { } else {
_skeletonModel.setVisibleInScene(true, scene); _skeletonModel.setVisibleInScene(true, scene);
_firstPersonSkeletonModel.setVisibleInScene(false, scene);
_firstPersonSkeletonModel.reset();
} }
} }
@ -1254,23 +1242,14 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
const bool shouldDrawHead = shouldRenderHead(renderArgs); const bool shouldDrawHead = shouldRenderHead(renderArgs);
_skeletonModel.initWhenReady(scene); _skeletonModel.initWhenReady(scene);
if (_useFullAvatar) {
_firstPersonSkeletonModel.initWhenReady(scene);
}
if (shouldDrawHead != _prevShouldDrawHead) { if (shouldDrawHead != _prevShouldDrawHead) {
if (_useFullAvatar) { if (_useFullAvatar) {
if (shouldDrawHead) {
_skeletonModel.setVisibleInScene(true, scene); _skeletonModel.setVisibleInScene(true, scene);
_firstPersonSkeletonModel.setVisibleInScene(false, scene); _rig->setFirstPerson(!shouldDrawHead);
} else {
_skeletonModel.setVisibleInScene(false, scene);
_firstPersonSkeletonModel.setVisibleInScene(true, scene);
}
} else { } else {
getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene); getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene);
} }
} }
_prevShouldDrawHead = shouldDrawHead; _prevShouldDrawHead = shouldDrawHead;
} }

View file

@ -287,8 +287,6 @@ private:
QString _fullAvatarModelName; QString _fullAvatarModelName;
RigPointer _rig; RigPointer _rig;
// used for rendering when in first person view or when in an HMD.
SkeletonModel _firstPersonSkeletonModel;
bool _prevShouldDrawHead; bool _prevShouldDrawHead;
}; };

View file

@ -40,8 +40,7 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer r
_standingFoot(NO_FOOT), _standingFoot(NO_FOOT),
_standingOffset(0.0f), _standingOffset(0.0f),
_clampedFootPosition(0.0f), _clampedFootPosition(0.0f),
_headClipDistance(DEFAULT_NEAR_CLIP), _headClipDistance(DEFAULT_NEAR_CLIP)
_isFirstPerson(false)
{ {
assert(_rig); assert(_rig);
assert(_owningAvatar); assert(_owningAvatar);
@ -54,7 +53,7 @@ SkeletonModel::~SkeletonModel() {
void SkeletonModel::initJointStates(QVector<JointState> states) { void SkeletonModel::initJointStates(QVector<JointState> states) {
const FBXGeometry& geometry = _geometry->getFBXGeometry(); const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
_boundingRadius = _rig->initJointStates(states, parentTransform); _boundingRadius = _rig->initJointStates(states, parentTransform, geometry.neckJointIndex);
// Determine the default eye position for avatar scale = 1.0 // Determine the default eye position for avatar scale = 1.0
int headJointIndex = _geometry->getFBXGeometry().headJointIndex; int headJointIndex = _geometry->getFBXGeometry().headJointIndex;
@ -98,6 +97,29 @@ void SkeletonModel::initJointStates(QVector<JointState> states) {
const float PALM_PRIORITY = DEFAULT_PRIORITY; const float PALM_PRIORITY = DEFAULT_PRIORITY;
const float LEAN_PRIORITY = DEFAULT_PRIORITY; const float LEAN_PRIORITY = DEFAULT_PRIORITY;
void SkeletonModel::updateClusterMatrices() {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
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);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
}
} else {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointVisibleTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
}
}
}
}
void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
setTranslation(_owningAvatar->getSkeletonPosition()); setTranslation(_owningAvatar->getSkeletonPosition());
static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
@ -154,8 +176,11 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
} }
} }
if (_isFirstPerson) { // if (_isFirstPerson) {
cauterizeHead(); // cauterizeHead();
// updateClusterMatrices();
// }
if (_rig->getJointsAreDirty()) {
updateClusterMatrices(); updateClusterMatrices();
} }
@ -828,56 +853,5 @@ bool SkeletonModel::hasSkeleton() {
return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false; return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false;
} }
void SkeletonModel::initHeadBones() {
_headBones.clear();
const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry();
const int neckJointIndex = fbxGeometry.neckJointIndex;
std::queue<int> q;
q.push(neckJointIndex);
_headBones.push_back(neckJointIndex);
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
while (q.size() > 0) {
int jointIndex = q.front();
for (int i = 0; i < fbxGeometry.joints.size(); i++) {
const FBXJoint& fbxJoint = fbxGeometry.joints[i];
if (jointIndex == fbxJoint.parentIndex) {
_headBones.push_back(i);
q.push(i);
}
}
q.pop();
}
}
void SkeletonModel::invalidateHeadBones() {
_headBones.clear();
}
void SkeletonModel::cauterizeHead() {
if (isActive()) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const int neckJointIndex = geometry.neckJointIndex;
if (neckJointIndex > 0 && neckJointIndex < _rig->getJointStateCount()) {
// lazy init of headBones
if (_headBones.size() == 0) {
initHeadBones();
}
// preserve the translation for the neck
// glm::vec4 trans = _jointStates[neckJointIndex].getTransform()[3];
glm::vec4 trans = _rig->getJointTransform(neckJointIndex)[3];
glm::vec4 zero(0, 0, 0, 0);
for (const int &i : _headBones) {
glm::mat4 newXform(zero, zero, zero, trans);
_rig->setJointTransform(i, newXform);
_rig->setJointVisibleTransform(i, newXform);
}
}
}
}
void SkeletonModel::onInvalidate() { void SkeletonModel::onInvalidate() {
invalidateHeadBones();
} }

View file

@ -112,9 +112,6 @@ public:
float getHeadClipDistance() const { return _headClipDistance; } float getHeadClipDistance() const { return _headClipDistance; }
void setIsFirstPerson(bool value) { _isFirstPerson = value; }
bool getIsFirstPerson() const { return _isFirstPerson; }
virtual void onInvalidate() override; virtual void onInvalidate() override;
signals: signals:
@ -138,6 +135,7 @@ protected:
void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, int index); void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, int index);
void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, int index); void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, int index);
void updateClusterMatrices();
void cauterizeHead(); void cauterizeHead();
void initHeadBones(); void initHeadBones();
void invalidateHeadBones(); void invalidateHeadBones();
@ -173,9 +171,6 @@ private:
glm::vec3 _clampedFootPosition; glm::vec3 _clampedFootPosition;
float _headClipDistance; // Near clip distance to use if no separate head model float _headClipDistance; // Near clip distance to use if no separate head model
bool _isFirstPerson;
std::vector<int> _headBones;
}; };
#endif // hifi_SkeletonModel_h #endif // hifi_SkeletonModel_h

View file

@ -176,8 +176,7 @@ void AnimationHandle::replaceMatchingPriorities(float newPriority) {
for (int i = 0; i < _jointMappings.size(); i++) { for (int i = 0; i < _jointMappings.size(); i++) {
int mapping = _jointMappings.at(i); int mapping = _jointMappings.at(i);
if (mapping != -1) { if (mapping != -1) {
JointState state = _rig->getJointState(mapping); if (_priority == _rig->getJointAnimatinoPriority(mapping)) {
if (_priority == state._animationPriority) {
_rig->setJointAnimatinoPriority(mapping, newPriority); _rig->setJointAnimatinoPriority(mapping, newPriority);
} }
} }
@ -188,8 +187,7 @@ void AnimationHandle::restoreJoints() {
for (int i = 0; i < _jointMappings.size(); i++) { for (int i = 0; i < _jointMappings.size(); i++) {
int mapping = _jointMappings.at(i); int mapping = _jointMappings.at(i);
if (mapping != -1) { if (mapping != -1) {
JointState state = _rig->getJointState(mapping); _rig->restoreJointRotation(mapping, 1.0f, _rig->getJointAnimatinoPriority(mapping));
_rig->restoreJointRotation(mapping, 1.0f, state._animationPriority);
} }
} }
} }

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <queue>
#include "AnimationHandle.h" #include "AnimationHandle.h"
#include "Rig.h" #include "Rig.h"
@ -48,9 +50,9 @@ void Rig::deleteAnimations() {
} }
} }
float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform, int neckJointIndex) {
float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform) {
_jointStates = states; _jointStates = states;
_neckJointIndex = neckJointIndex;
initJointTransforms(parentTransform); initJointTransforms(parentTransform);
int numStates = _jointStates.size(); int numStates = _jointStates.size();
@ -66,6 +68,8 @@ float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform
_jointStates[i].slaveVisibleTransform(); _jointStates[i].slaveVisibleTransform();
} }
initHeadBones();
return radius; return radius;
} }
@ -106,7 +110,8 @@ JointState Rig::getJointState(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return JointState(); return JointState();
} }
return _jointStates[jointIndex]; // return _jointStates[jointIndex];
return maybeCauterizeHead(jointIndex);
} }
bool Rig::getJointStateRotation(int index, glm::quat& rotation) const { bool Rig::getJointStateRotation(int index, glm::quat& rotation) const {
@ -144,6 +149,13 @@ void Rig::clearJointAnimationPriority(int index) {
} }
} }
float Rig::getJointAnimatinoPriority(int index) {
if (index != -1 && index < _jointStates.size()) {
return _jointStates[index]._animationPriority;
}
return 0.0f;
}
void Rig::setJointAnimatinoPriority(int index, float newPriority) { void Rig::setJointAnimatinoPriority(int index, float newPriority) {
if (index != -1 && index < _jointStates.size()) { if (index != -1 && index < _jointStates.size()) {
_jointStates[index]._animationPriority = newPriority; _jointStates[index]._animationPriority = newPriority;
@ -173,7 +185,8 @@ bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position,
return false; return false;
} }
// position is in world-frame // position is in world-frame
position = translation + rotation * _jointStates[jointIndex].getPosition(); // position = translation + rotation * _jointStates[jointIndex].getPosition();
position = translation + rotation * maybeCauterizeHead(jointIndex).getPosition();
return true; return true;
} }
@ -182,7 +195,7 @@ bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const {
return false; return false;
} }
// position is in model-frame // position is in model-frame
position = extractTranslation(_jointStates[jointIndex].getTransform()); position = extractTranslation(maybeCauterizeHead(jointIndex).getTransform());
return true; return true;
} }
@ -190,7 +203,7 @@ bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const
if (jointIndex == -1 || jointIndex >= _jointStates.size()) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false; return false;
} }
result = rotation * _jointStates[jointIndex].getRotation(); result = rotation * maybeCauterizeHead(jointIndex).getRotation();
return true; return true;
} }
@ -198,7 +211,7 @@ bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false; return false;
} }
rotation = _jointStates[jointIndex].getRotation(); rotation = maybeCauterizeHead(jointIndex).getRotation();
return true; return true;
} }
@ -206,7 +219,7 @@ bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm:
if (jointIndex == -1 || jointIndex >= _jointStates.size()) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false; return false;
} }
result = rotation * _jointStates[jointIndex].getRotation(); result = rotation * maybeCauterizeHead(jointIndex).getRotation();
return true; return true;
} }
@ -217,7 +230,7 @@ bool Rig::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& positio
return false; return false;
} }
// position is in world-frame // position is in world-frame
position = translation + rotation * _jointStates[jointIndex].getVisiblePosition(); position = translation + rotation * maybeCauterizeHead(jointIndex).getVisiblePosition();
return true; return true;
} }
@ -225,7 +238,7 @@ bool Rig::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& result,
if (jointIndex == -1 || jointIndex >= _jointStates.size()) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false; return false;
} }
result = rotation * _jointStates[jointIndex].getVisibleRotation(); result = rotation * maybeCauterizeHead(jointIndex).getVisibleRotation();
return true; return true;
} }
@ -233,14 +246,14 @@ 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();
} }
return _jointStates[jointIndex].getTransform(); return maybeCauterizeHead(jointIndex).getTransform();
} }
glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const { glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return glm::mat4(); return glm::mat4();
} }
return _jointStates[jointIndex].getVisibleTransform(); return maybeCauterizeHead(jointIndex).getVisibleTransform();
} }
void Rig::simulateInternal(float deltaTime, glm::mat4 parentTransform) { void Rig::simulateInternal(float deltaTime, glm::mat4 parentTransform) {
@ -492,7 +505,7 @@ glm::vec3 Rig::getJointDefaultTranslationInConstrainedFrame(int jointIndex) {
if (jointIndex == -1 || _jointStates.isEmpty()) { if (jointIndex == -1 || _jointStates.isEmpty()) {
return glm::vec3(); return glm::vec3();
} }
return _jointStates[jointIndex].getDefaultTranslationInConstrainedFrame(); return maybeCauterizeHead(jointIndex).getDefaultTranslationInConstrainedFrame();
} }
glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, bool constrain) { glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, bool constrain) {
@ -537,5 +550,53 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
if (jointIndex == -1 || _jointStates.isEmpty()) { if (jointIndex == -1 || _jointStates.isEmpty()) {
return glm::quat(); return glm::quat();
} }
return _jointStates[jointIndex].getDefaultRotationInParentFrame(); return maybeCauterizeHead(jointIndex).getDefaultRotationInParentFrame();
}
void Rig::initHeadBones() {
if (_neckJointIndex == -1) {
return;
}
_headBones.clear();
std::queue<int> q;
q.push(_neckJointIndex);
_headBones.push_back(_neckJointIndex);
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
while (q.size() > 0) {
int jointIndex = q.front();
for (int i = 0; i < _jointStates.size(); i++) {
const FBXJoint& fbxJoint = _jointStates[i].getFBXJoint();
if (jointIndex == fbxJoint.parentIndex) {
_headBones.push_back(i);
q.push(i);
}
}
q.pop();
}
}
JointState Rig::maybeCauterizeHead(int jointIndex) const {
// if (_headBones.contains(jointIndex)) {
// XXX fix this... make _headBones a hash? add a flag to JointState?
if (_neckJointIndex != -1 &&
_isFirstPerson &&
std::find(_headBones.begin(), _headBones.end(), jointIndex) != _headBones.end()) {
glm::vec4 trans = _jointStates[jointIndex].getTransform()[3];
glm::vec4 zero(0, 0, 0, 0);
glm::mat4 newXform(zero, zero, zero, trans);
JointState jointStateCopy = _jointStates[jointIndex];
jointStateCopy.setTransform(newXform);
jointStateCopy.setVisibleTransform(newXform);
return jointStateCopy;
} else {
return _jointStates[jointIndex];
}
}
void Rig::setFirstPerson(bool isFirstPerson) {
if (_isFirstPerson != isFirstPerson) {
_isFirstPerson = isFirstPerson;
_jointsAreDirty = true;
}
} }

View file

@ -11,14 +11,18 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
/* TBD: /* TBD:
- What iare responsibilities of Animation/AnimationPointer/AnimationCache/AnimationDetails/AnimationObject/AnimationLoop? - What are responsibilities of Animation/AnimationPointer/AnimationCache/AnimationDetails/AnimationObject/AnimationLoop?
Is there common/copied code (e.g., ScriptableAvatar::update)? Is there common/copied code (e.g., ScriptableAvatar::update)?
- How do attachments interact with the physics of the attached entity? E.g., do hand joints need to reflect held object physics? - How do attachments interact with the physics of the attached entity? E.g., do hand joints need to reflect held object
- Is there any current need (i.e., for initial campatability) to have multiple animations per role (e.g., idle) with the system choosing randomly? physics?
- Is there any current need (i.e., for initial campatability) to have multiple animations per role (e.g., idle) with the
system choosing randomly?
- Distribute some doc from here to the right files if it turns out to be correct: - Distribute some doc from here to the right files if it turns out to be correct:
- AnimationDetails is a script-useable copy of animation state, analogous to EntityItemProperties, but without anything equivalent to editEntity. - AnimationDetails is a script-useable copy of animation state, analogous to EntityItemProperties, but without anything
But what's the intended difference vs AnimationObjection? Maybe AnimationDetails is to Animation as AnimationObject is to AnimationPointer? equivalent to editEntity.
But what's the intended difference vs AnimationObjection? Maybe AnimationDetails is to Animation as AnimationObject
is to AnimationPointer?
*/ */
#ifndef __hifi__Rig__ #ifndef __hifi__Rig__
@ -51,7 +55,7 @@ public:
const QList<AnimationHandlePointer>& getRunningAnimations() const { return _runningAnimations; } const QList<AnimationHandlePointer>& getRunningAnimations() const { return _runningAnimations; }
void deleteAnimations(); void deleteAnimations();
float initJointStates(QVector<JointState> states, glm::mat4 parentTransform); float initJointStates(QVector<JointState> states, glm::mat4 parentTransform, int neckJointIndex);
bool jointStatesEmpty() { return _jointStates.isEmpty(); }; bool jointStatesEmpty() { return _jointStates.isEmpty(); };
int getJointStateCount() const { return _jointStates.size(); } int getJointStateCount() const { return _jointStates.size(); }
@ -60,11 +64,12 @@ public:
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, bool constrain, float priority);
JointState getJointState(int jointIndex) const; 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);
void clearJointStates(); void clearJointStates();
void clearJointAnimationPriority(int index); void clearJointAnimationPriority(int index);
float getJointAnimatinoPriority(int index);
void setJointAnimatinoPriority(int index, float newPriority); void setJointAnimatinoPriority(int index, float newPriority);
void setJointState(int index, bool valid, const glm::quat& rotation, float priority); void setJointState(int index, bool valid, const glm::quat& rotation, float priority);
void restoreJointRotation(int index, float fraction, float priority); void restoreJointRotation(int index, float fraction, float priority);
@ -102,11 +107,23 @@ public:
virtual void updateJointState(int index, glm::mat4 parentTransform) = 0; virtual void updateJointState(int index, glm::mat4 parentTransform) = 0;
virtual void updateFaceJointState(int index, glm::mat4 parentTransform) = 0; virtual void updateFaceJointState(int index, glm::mat4 parentTransform) = 0;
virtual void setFirstPerson(bool isFirstPerson);
virtual bool getIsFirstPerson() const { return _isFirstPerson; }
bool getJointsAreDirty() { return _jointsAreDirty; }
protected: protected:
QVector<JointState> _jointStates; QVector<JointState> _jointStates;
QSet<AnimationHandlePointer> _animationHandles; QSet<AnimationHandlePointer> _animationHandles;
QList<AnimationHandlePointer> _runningAnimations; QList<AnimationHandlePointer> _runningAnimations;
JointState maybeCauterizeHead(int jointIndex) const;
void initHeadBones();
bool _isFirstPerson = false;
std::vector<int> _headBones;
bool _jointsAreDirty = false;
int _neckJointIndex = -1;
}; };
#endif /* defined(__hifi__Rig__) */ #endif /* defined(__hifi__Rig__) */

View file

@ -478,7 +478,7 @@ bool Model::updateGeometry() {
void Model::initJointStates(QVector<JointState> states) { void Model::initJointStates(QVector<JointState> states) {
const FBXGeometry& geometry = _geometry->getFBXGeometry(); const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
_boundingRadius = _rig->initJointStates(states, parentTransform); _boundingRadius = _rig->initJointStates(states, parentTransform, geometry.neckJointIndex);
} }
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
@ -1341,28 +1341,6 @@ void Model::simulate(float deltaTime, bool fullUpdate) {
} }
} }
void Model::updateClusterMatrices() {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
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);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
}
} else {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointVisibleTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
}
}
}
}
void Model::simulateInternal(float deltaTime) { void Model::simulateInternal(float deltaTime) {
// update the world space transforms for all joints // update the world space transforms for all joints

View file

@ -308,9 +308,6 @@ protected:
_calculatedMeshTrianglesValid = false; _calculatedMeshTrianglesValid = false;
} }
// rebuild the clusterMatrices from the current jointStates
void updateClusterMatrices();
// hook for derived classes to be notified when setUrl invalidates the current model. // hook for derived classes to be notified when setUrl invalidates the current model.
virtual void onInvalidate() {}; virtual void onInvalidate() {};