mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-23 15:34:47 +02:00
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:
parent
4566d16402
commit
33c97a1833
9 changed files with 137 additions and 140 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__) */
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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() {};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue