From d8a20340a043cf8840d254a006799217abe7b308 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 3 Aug 2015 18:31:32 -0700 Subject: [PATCH] Found and fix source of memory corruption. std::vector.reserve() and raw access do not mix. raw access will only work if you push_back elements onto the vector first. However this worked fine on MacOSX, probably due to differences in STL implementations. Some code clean up and some commented out debugging lines. Debug rendering of animaions of fight club model is not working. Not sure what frame these transformations are in. --- libraries/animation/src/AnimClip.cpp | 14 +++--- libraries/animation/src/AnimSkeleton.cpp | 49 ++++++++++++++++---- libraries/animation/src/AnimSkeleton.h | 19 ++++---- libraries/render-utils/src/AnimDebugDraw.cpp | 25 +++++++--- 4 files changed, 75 insertions(+), 32 deletions(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 6f16a8d884..dbb241d484 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -121,14 +121,14 @@ void AnimClip::copyFromNetworkAnim() { // build a mapping from animation joint indices to skeleton joint indices. // by matching joints with the same name. const FBXGeometry& geom = _networkAnim->getGeometry(); - const QVector& joints = geom.joints; + const QVector& animJoints = geom.joints; std::vector jointMap; - const int animJointCount = joints.count(); + const int animJointCount = animJoints.count(); jointMap.reserve(animJointCount); for (int i = 0; i < animJointCount; i++) { - int skeletonJoint = _skeleton->nameToJointIndex(joints.at(i).name); + int skeletonJoint = _skeleton->nameToJointIndex(animJoints.at(i).name); if (skeletonJoint == -1) { - qCWarning(animation) << "animation contains joint =" << joints.at(i).name << " which is not in the skeleton, url =" << _url.c_str(); + qCWarning(animation) << "animation contains joint =" << animJoints.at(i).name << " which is not in the skeleton, url =" << _url.c_str(); } jointMap.push_back(skeletonJoint); } @@ -138,10 +138,10 @@ void AnimClip::copyFromNetworkAnim() { _anim.resize(frameCount); for (int i = 0; i < frameCount; i++) { - // init all joints in animation to relative bind pose + // init all joints in animation to identity _anim[i].reserve(skeletonJointCount); for (int j = 0; j < skeletonJointCount; j++) { - _anim[i].push_back(_skeleton->getRelativeBindPose(j)); + _anim[i].push_back(AnimPose::identity); } // init over all joint animations @@ -149,7 +149,7 @@ void AnimClip::copyFromNetworkAnim() { int k = jointMap[j]; if (k >= 0 && k < skeletonJointCount) { // currently FBX animations only have rotation. - _anim[i][k].rot = _skeleton->getRelativeBindPose(k).rot * geom.animationFrames[i].rotations[j]; + _anim[i][k].rot = geom.animationFrames[i].rotations[j]; } } } diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index e966203d22..feaa1828ce 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -8,6 +8,7 @@ // #include "AnimSkeleton.h" +#include "AnimationLogging.h" #include "glmHelpers.h" const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f), @@ -16,10 +17,22 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f), AnimPose::AnimPose(const glm::mat4& mat) { scale = extractScale(mat); - rot = glm::quat_cast(mat); + rot = glm::normalize(glm::quat_cast(mat)); trans = extractTranslation(mat); } +glm::vec3 AnimPose::operator*(const glm::vec3& rhs) const { + return trans + (rot * (scale * rhs)); +} + +AnimPose AnimPose::operator*(const AnimPose& rhs) const { + return AnimPose(static_cast(*this) * static_cast(rhs)); +} + +AnimPose AnimPose::inverse() const { + return AnimPose(glm::inverse(static_cast(*this))); +} + AnimPose::operator glm::mat4() const { glm::vec3 xAxis = rot * glm::vec3(scale.x, 0.0f, 0.0f); glm::vec3 yAxis = rot * glm::vec3(0.0f, scale.y, 0.0f); @@ -28,6 +41,7 @@ AnimPose::operator glm::mat4() const { glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f)); } + AnimSkeleton::AnimSkeleton(const std::vector& joints) { _joints = joints; @@ -35,17 +49,32 @@ AnimSkeleton::AnimSkeleton(const std::vector& joints) { _absoluteBindPoses.reserve(joints.size()); _relativeBindPoses.reserve(joints.size()); for (size_t i = 0; i < joints.size(); i++) { - glm::mat4 absBindMat = _joints[i].bindTransform; - AnimPose absBindPose(_joints[i].bindTransform); - _absoluteBindPoses.push_back(absBindPose); + + AnimPose absoluteBindPose(_joints[i].bindTransform); + _absoluteBindPoses.push_back(absoluteBindPose); + int parentIndex = getParentIndex(i); if (parentIndex >= 0) { - glm::mat4 invParentAbsBindMat = glm::inverse(_joints[parentIndex].bindTransform); - glm::mat4 relBindMat = invParentAbsBindMat * absBindMat; - _relativeBindPoses.push_back(AnimPose(relBindMat)); + AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse(); + _relativeBindPoses.push_back(inverseParentAbsoluteBindPose * absoluteBindPose); } else { - _relativeBindPoses.push_back(absBindPose); + _relativeBindPoses.push_back(absoluteBindPose); } + + // AJT: + // Attempt to use relative bind pose.. but it's not working. + /* + AnimPose relBindPose(glm::vec3(1.0f), _joints[i].rotation, _joints[i].translation); + _relativeBindPoses.push_back(relBindPose); + + int parentIndex = getParentIndex(i); + if (parentIndex >= 0) { + AnimPose parentAbsBindPose = _absoluteBindPoses[parentIndex]; + _absoluteBindPoses.push_back(parentAbsBindPose * relBindPose); + } else { + _absoluteBindPoses.push_back(relBindPose); + } + */ } } @@ -74,4 +103,6 @@ int AnimSkeleton::getParentIndex(int jointIndex) const { return _joints[jointIndex].parentIndex; } - +const QString& AnimSkeleton::getJointName(int jointIndex) const { + return _joints[jointIndex].name; +} diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index 9019a1b356..b51daadae7 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -16,18 +16,13 @@ struct AnimPose { AnimPose() {} - AnimPose(const glm::mat4& mat); + explicit AnimPose(const glm::mat4& mat); AnimPose(const glm::vec3& scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : scale(scaleIn), rot(rotIn), trans(transIn) {} static const AnimPose identity; - glm::vec3 operator*(const glm::vec3& rhs) const { - return trans + (rot * (scale * rhs)); - } - - AnimPose operator*(const AnimPose& rhs) const { - return AnimPose(static_cast(*this) * static_cast(rhs)); - } - + glm::vec3 operator*(const glm::vec3& rhs) const; + AnimPose operator*(const AnimPose& rhs) const; + AnimPose inverse() const; operator glm::mat4() const; glm::vec3 scale; @@ -35,12 +30,18 @@ struct AnimPose { glm::vec3 trans; }; +inline QDebug operator<<(QDebug debug, const AnimPose& pose) { + debug << "AnimPose, trans = (" << pose.trans.x << pose.trans.y << pose.trans.z << "), rot = (" << pose.rot.x << pose.rot.y << pose.rot.z << pose.rot.w << "), scale = (" << pose.scale.x << pose.scale.y << pose.scale.z << ")"; + return debug; +} + class AnimSkeleton { public: typedef std::shared_ptr Pointer; AnimSkeleton(const std::vector& joints); int nameToJointIndex(const QString& jointName) const; + const QString& getJointName(int jointIndex) const; int getNumJoints() const; // absolute pose, not relative to parent diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 6e3bb4bc8a..8a9877ca12 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -13,6 +13,7 @@ #include "AnimDebugDraw.h" #include "AbstractViewStateInterface.h" +#include "RenderUtilsLogging.h" struct Vertex { glm::vec3 pos; @@ -218,7 +219,8 @@ void AnimDebugDraw::update() { AnimSkeleton::Pointer& skeleton = iter.second.first; numVerts += skeleton->getNumJoints() * 6; for (int i = 0; i < skeleton->getNumJoints(); i++) { - if (skeleton->getParentIndex(i) >= 0) { + auto parentIndex = skeleton->getParentIndex(i); + if (parentIndex >= 0) { numVerts += 2; } } @@ -229,8 +231,9 @@ void AnimDebugDraw::update() { auto poses = animNode->getPosesInternal(); numVerts += poses.size() * 6; auto skeleton = animNode->getSkeleton(); - for (int i = 0; i < poses.size(); i++) { - if (skeleton->getParentIndex(i) >= 0) { + for (size_t i = 0; i < poses.size(); i++) { + auto parentIndex = skeleton->getParentIndex(i); + if (parentIndex >= 0) { numVerts += 2; } } @@ -251,8 +254,14 @@ void AnimDebugDraw::update() { addWireframeSphereWithAxes(rootPose, pose, radius, v); // line to parent. - if (skeleton->getParentIndex(i) >= 0) { - AnimPose parentPose = skeleton->getAbsoluteBindPose(skeleton->getParentIndex(i)); + auto parentIndex = skeleton->getParentIndex(i); + //qCDebug(renderutils) << skeleton->getJointName(i) << " index = " << i; + //qCDebug(renderutils) << " absPose =" << skeleton->getAbsoluteBindPose(i); + //qCDebug(renderutils) << " relPose =" << skeleton->getRelativeBindPose(i); + if (parentIndex >= 0) { + //qCDebug(renderutils) << " parent =" << parentIndex; + assert(parentIndex < skeleton->getNumJoints()); + AnimPose parentPose = skeleton->getAbsoluteBindPose(parentIndex); addWireframeBoneAxis(rootPose, pose, parentPose, radius, v); } } @@ -266,7 +275,7 @@ void AnimDebugDraw::update() { auto skeleton = animNode->getSkeleton(); std::vector absAnimPose; - absAnimPose.reserve(skeleton->getNumJoints()); + absAnimPose.resize(skeleton->getNumJoints()); for (size_t i = 0; i < poses.size(); i++) { @@ -282,18 +291,20 @@ void AnimDebugDraw::update() { addWireframeSphereWithAxes(rootPose, absAnimPose[i], radius, v); if (parentIndex >= 0) { + assert((size_t)parentIndex < poses.size()); // draw line to parent addWireframeBoneAxis(rootPose, absAnimPose[i], absAnimPose[parentIndex], radius, v); } } } + assert(numVerts == (v - verts)); + data._indexBuffer->resize(sizeof(uint16_t) * numVerts); uint16_t* indices = (uint16_t*)data._indexBuffer->editData(); for (int i = 0; i < numVerts; i++) { indices[i] = i; } - }); scene->enqueuePendingChanges(pendingChanges); }