From 8f7f3eed6e351c831859619cf9e38d44300381b4 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 1 Dec 2015 11:52:42 -0800 Subject: [PATCH] ScriptAvatar now gets the .fbx joints: Because the joint mappings in the .fst can be wrong when the .fst isn't updated for quick changes in the .fbx. Because models now really need the preRotation, which is only in the avatar .fbx. --- .../src/avatars/ScriptableAvatar.cpp | 31 ++++++++++++------- .../src/avatars/ScriptableAvatar.h | 1 + 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 9b3d2ed24e..82e88f67ef 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -12,7 +12,6 @@ #include #include - #include "ScriptableAvatar.h" // hold and priority unused but kept so that client side JS can run. @@ -48,14 +47,12 @@ AnimationDetails ScriptableAvatar::getAnimationDetails() { } void ScriptableAvatar::update(float deltatime) { + if (_bind.isNull() && !_skeletonFBXURL.isEmpty()) { // AvatarData will parse the .fst, but not get the .fbx skeleton. + _bind = DependencyManager::get()->getAnimation(_skeletonFBXURL); + } + // Run animation - if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0) { - QStringList modelJoints = getJointNames(); - QStringList animationJoints = _animation->getJointNames(); - - if (_jointData.size() != modelJoints.size()) { - _jointData.resize(modelJoints.size()); - } + if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && _bind->isLoaded()) { float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps; if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) { @@ -63,19 +60,29 @@ void ScriptableAvatar::update(float deltatime) { currentFrame -= (_animationDetails.lastFrame - _animationDetails.firstFrame); } _animationDetails.currentFrame = currentFrame; + + const QVector& modelJoints = _bind->getGeometry().joints; + QStringList animationJointNames = _animation->getJointNames(); + + if (_jointData.size() != modelJoints.size()) { + _jointData.resize(modelJoints.size()); + } const int frameCount = _animation->getFrames().size(); const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount); const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount); const float frameFraction = glm::fract(currentFrame); - for (int i = 0; i < animationJoints.size(); i++) { - const QString& name = animationJoints[i]; - int mapping = getJointIndex(name); + for (int i = 0; i < animationJointNames.size(); i++) { + const QString& name = animationJointNames[i]; + // As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than + // trusting the .fst (which is sometimes not updated to match changes to .fbx). + int mapping = _bind->getGeometry().getJointIndex(name); if (mapping != -1 && !_maskedJoints.contains(name)) { JointData& data = _jointData[mapping]; - auto newRotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction); + auto newRotation = modelJoints[mapping].preRotation * + safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction); // We could probably do translations as in interpolation in model space (rather than the parent space that each frame is in), // but we don't do so for MyAvatar yet, so let's not be different here. if (data.rotation != newRotation) { diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 78b2be1057..30c48d02bf 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -33,6 +33,7 @@ private: AnimationPointer _animation; AnimationDetails _animationDetails; QStringList _maskedJoints; + AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies }; #endif // hifi_ScriptableAvatar_h \ No newline at end of file