From ecc31802b821f9d864f9242152a5983b76d44be1 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 28 Mar 2017 17:23:36 -0700 Subject: [PATCH 1/2] Added translation support to AC avatar animations. --- .../src/avatars/ScriptableAvatar.cpp | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 516bf7a1e3..7fb319031b 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -9,11 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include +#include #include +#include #include "ScriptableAvatar.h" + QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail) { _globalPosition = getPosition(); return AvatarData::toByteArrayStateful(dataDetail); @@ -57,6 +61,14 @@ void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _animSkeleton.reset(); AvatarData::setSkeletonModelURL(skeletonModelURL); } + +static AnimPose composeAnimPose(const FBXJoint& fbxJoint, const glm::quat rotation, const glm::vec3 translation) { + glm::mat4 translationMat = glm::translate(translation); + glm::mat4 rotationMat = glm::mat4_cast(fbxJoint.preRotation * rotation * fbxJoint.postRotation); + glm::mat4 finalMat = translationMat * fbxJoint.preTransform * rotationMat * fbxJoint.postTransform; + return AnimPose(finalMat); +} + 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); @@ -81,32 +93,42 @@ void ScriptableAvatar::update(float deltatime) { if (_jointData.size() != nJoints) { _jointData.resize(nJoints); } - + 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); std::vector poses = _animSkeleton->getRelativeDefaultPoses(); - + + float UNIT_SCALE = 0.01f; + 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)) { - // Eventually, this should probably deal with post rotations and translations, too. - poses[mapping].rot() = modelJoints[mapping].preRotation * - safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);; + + AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE); + AnimPose ceilPose = composeAnimPose(modelJoints[mapping], ceilFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE); + blend(1, &floorPose, &ceilPose, frameFraction, &poses[mapping]); } } - _animSkeleton->convertRelativePosesToAbsolute(poses); + + std::vector absPoses = poses; + _animSkeleton->convertRelativePosesToAbsolute(absPoses); for (int i = 0; i < nJoints; i++) { JointData& data = _jointData[i]; - AnimPose& pose = poses[i]; - if (data.rotation != pose.rot()) { - data.rotation = pose.rot(); + AnimPose& absPose = absPoses[i]; + if (data.rotation != absPose.rot()) { + data.rotation = absPose.rot(); data.rotationSet = true; } + AnimPose& relPose = poses[i]; + if (data.translation != relPose.trans()) { + data.translation = relPose.trans(); + data.translationSet = true; + } } } else { From e100e3d19b0d38a701122b0cb29584b8f8b813c6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 28 Mar 2017 17:34:15 -0700 Subject: [PATCH 2/2] made UNIT_SCALE const --- assignment-client/src/avatars/ScriptableAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 7fb319031b..57456b00c3 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -100,7 +100,7 @@ void ScriptableAvatar::update(float deltatime) { const float frameFraction = glm::fract(currentFrame); std::vector poses = _animSkeleton->getRelativeDefaultPoses(); - float UNIT_SCALE = 0.01f; + const float UNIT_SCALE = 0.01f; for (int i = 0; i < animationJointNames.size(); i++) { const QString& name = animationJointNames[i];