From d3b2d9b074f85ad16b0049cd0670ab754c13f1cc Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 28 Nov 2008 14:34:38 +0000 Subject: [PATCH] From Cedric Pinson, updates toosgAnimation. Merged by Robert Osfield, from OpenSceneGraph-osgWidget-dev. --- include/osgAnimation/Bone | 2 +- include/osgAnimation/EaseMotion | 58 +++++++++++++++++++---- include/osgAnimation/Skinning | 71 ++++++++++++++++++++++------ include/osgAnimation/Timeline | 5 +- include/osgAnimation/VertexInfluence | 1 - src/osgAnimation/UpdateCallback.cpp | 2 + 6 files changed, 112 insertions(+), 27 deletions(-) diff --git a/include/osgAnimation/Bone b/include/osgAnimation/Bone index cafca6647..dfa2fcb65 100644 --- a/include/osgAnimation/Bone +++ b/include/osgAnimation/Bone @@ -78,7 +78,7 @@ namespace osgAnimation { setName(name); _needToRecomputeBindMatrix = false; - setUpdateCallback(new UpdateBone); + setUpdateCallback(new UpdateBone(name)); } diff --git a/include/osgAnimation/EaseMotion b/include/osgAnimation/EaseMotion index 875fd32c0..c65d3a619 100644 --- a/include/osgAnimation/EaseMotion +++ b/include/osgAnimation/EaseMotion @@ -17,11 +17,6 @@ namespace osgAnimation { - struct LinearFunction - { - inline static void getValueAt(float t, float& result) { result = t;} - }; - struct OutBounceFunction { @@ -75,7 +70,15 @@ namespace osgAnimation { } }; + + /// Linear function + struct LinearFunction + { + inline static void getValueAt(float t, float& result) { result = t;} + }; + + /// Quad function struct OutQuadFunction { inline static void getValueAt(float t, float& result) { result = - (t * (t -2.0));} @@ -101,6 +104,7 @@ namespace osgAnimation { }; + /// Cubic function struct OutCubicFunction { inline static void getValueAt(float t, float& result) { t = t-1.0; result = t*t*t + 1;} @@ -123,6 +127,35 @@ namespace osgAnimation { } }; + + /// Quart function + struct InQuartFunction + { + inline static void getValueAt(float t, float& result) { result = t*t*t*t*t;} + }; + + struct OutQuartFunction + { + inline static void getValueAt(float t, float& result) { t = t - 1; result = - (t*t*t*t -1); } + }; + + struct InOutQuartFunction + { + inline static void getValueAt(float t, float& result) + { + t = t * 2.0; + if ( t < 1) + result = 0.5*t*t*t*t; + else + { + t -= 2.0; + result = -0.5 * (t*t*t*t -2); + } + } + }; + + + class Motion { public: @@ -185,6 +218,7 @@ namespace osgAnimation { }; + template struct MathMotionTemplate : public Motion { @@ -217,15 +251,21 @@ namespace osgAnimation { // linear typedef MathMotionTemplate LinearMotion; + // quad + typedef MathMotionTemplate OutQuadMotion; + typedef MathMotionTemplate InQuadMotion; + typedef MathMotionTemplate InOutQuadMotion; + // cubic typedef MathMotionTemplate OutCubicMotion; typedef MathMotionTemplate InCubicMotion; typedef MathMotionTemplate InOutCubicMotion; - // quad - typedef MathMotionTemplate OutQuadMotion; - typedef MathMotionTemplate InQuadMotion; - typedef MathMotionTemplate InOutQuadMotion; + // quart + typedef MathMotionTemplate OutQuartMotion; + typedef MathMotionTemplate InQuartMotion; + typedef MathMotionTemplate InOutQuartMotion; + // bounce typedef MathMotionTemplate OutBounceMotion; diff --git a/include/osgAnimation/Skinning b/include/osgAnimation/Skinning index 07f2a747c..18ccaa96f 100644 --- a/include/osgAnimation/Skinning +++ b/include/osgAnimation/Skinning @@ -30,7 +30,12 @@ namespace osgAnimation { - + /// This class manage format for software skinning + /// it used the technic on this paper http://www.intel.com/cd/ids/developer/asmo-na/eng/172124.htm + /// The idea is to prepare the data to do only v' = M x v with M a combined matrix as below + /// M = Mbone1 * w1 + Mbone2 * w2 + ... + /// a M matrix is uniq for a set of vertex then to fully compute the skinned mesh + /// you have to iterate on each UniqBoneSetVertexSet class TransformVertexFunctor { public: @@ -44,6 +49,7 @@ namespace osgAnimation BoneWeight(BoneType* bone, float weight) : _bone(bone), _weight(weight) {} const BoneType* getBone() const { return &(*_bone); } float getWeight() const { return _weight; } + void setWeight(float w) { _weight = w; } protected: osg::ref_ptr _bone; float _weight; @@ -57,6 +63,35 @@ namespace osgAnimation public: BoneWeightList& getBones() { return _bones; } VertexList& getVertexes() { return _vertexes; } + + void resetMatrix() + { + _result.set(0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1); + } + void accummulateMatrix(const osg::Matrix& invBindMatrix, const osg::Matrix& matrix, osg::Matrix::value_type weight) + { + osg::Matrix m = invBindMatrix * matrix; + osg::Matrix::value_type* ptr = m.ptr(); + osg::Matrix::value_type* ptrresult = _result.ptr(); + ptrresult[0] += ptr[0] * weight; + ptrresult[1] += ptr[1] * weight; + ptrresult[2] += ptr[2] * weight; + + ptrresult[4] += ptr[4] * weight; + ptrresult[5] += ptr[5] * weight; + ptrresult[6] += ptr[6] * weight; + + ptrresult[8] += ptr[8] * weight; + ptrresult[9] += ptr[9] * weight; + ptrresult[10] += ptr[10] * weight; + + ptrresult[12] += ptr[12] * weight; + ptrresult[13] += ptr[13] * weight; + ptrresult[14] += ptr[14] * weight; + } void computeMatrixForVertexSet() { if (_bones.empty()) @@ -65,18 +100,16 @@ namespace osgAnimation _result = MatrixType::identity(); return; } - _result = MatrixType(0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0); + resetMatrix(); + int size = _bones.size(); - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { const BoneType* bone = _bones[i].getBone(); const MatrixType& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); const MatrixType& matrix = bone->getMatrixInSkeletonSpace(); - double w = _bones[i].getWeight(); - _result = _result + ( (invBindMatrix * matrix ) * w); + osg::Matrix::value_type w = _bones[i].getWeight(); + accummulateMatrix(invBindMatrix, matrix, w); } } const MatrixType& getMatrix() const { return _result;} @@ -97,21 +130,31 @@ namespace osgAnimation { const osgAnimation::VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i]; int nbBones = inf.getBones().size(); + BoneWeightList& boneList = _boneSetVertexSet[i].getBones(); + double sumOfWeight = 0; for (int b = 0; b < nbBones; b++) { const std::string& bname = inf.getBones()[b].getBoneName(); float weight = inf.getBones()[b].getWeight(); - if (map.find(bname) == map.end()) + BoneMap::const_iterator it = map.find(bname); + if (it == map.end()) { - std::cerr << "Warning TransformVertexFunctor Bone " << bname << " not found, skip the influence group " <second.get(); - _boneSetVertexSet[i].getBones().push_back(BoneWeight(bone, weight)); + boneList.push_back(BoneWeight(bone, weight)); + sumOfWeight += weight; + } + // if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0 + // so we check it and renormalize the all weight bone + const double threshold = 1e-4; + if (!_boneSetVertexSet[i].getBones().empty() && + (sumOfWeight < 1.0 - threshold || sumOfWeight > 1.0 + threshold)) + { + for (int b = 0; b < boneList.size(); b++) + boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight); } _boneSetVertexSet[i].getVertexes() = inf.getVertexes(); } diff --git a/include/osgAnimation/Timeline b/include/osgAnimation/Timeline index b9a218c72..aa6b0fb5b 100644 --- a/include/osgAnimation/Timeline +++ b/include/osgAnimation/Timeline @@ -15,14 +15,15 @@ #ifndef OSGANIMATION_TIMELINE_H #define OSGANIMATION_TIMELINE_H +#include #include #include #include +#include #include #include #include #include -#include namespace osgAnimation { @@ -213,7 +214,7 @@ namespace osgAnimation // process all pending remove action operation while( !_removeActionOperations.empty()) { - internalRemoveAction(_removeActionOperations.back().second.get()); + internalRemoveAction(_removeActionOperations.back().second); _removeActionOperations.pop_back(); } } diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index aadbdc5d3..d9c09044b 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -93,7 +93,6 @@ namespace osgAnimation void buildUniqVertexSetToBoneSetList(); void clear() { - _bone2Vertexes.clear(); _bone2Vertexes.clear(); _uniqVertexSetToBoneSet.clear(); } diff --git a/src/osgAnimation/UpdateCallback.cpp b/src/osgAnimation/UpdateCallback.cpp index c2b96786c..86c176345 100644 --- a/src/osgAnimation/UpdateCallback.cpp +++ b/src/osgAnimation/UpdateCallback.cpp @@ -26,6 +26,8 @@ AnimationUpdateCallback::AnimationUpdateCallback(const AnimationUpdateCallback& int AnimationUpdateCallback::link(osgAnimation::Animation* animation) { + if (getName().empty()) + osg::notify(osg::WARN) << "An update callback has no name, it means it can link only with \"\" named Target, often an error" << std::endl; int nbLinks = 0; for (osgAnimation::ChannelList::iterator it = animation->getChannels().begin(); it != animation->getChannels().end();