diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index a8d817e64..9d2a014dc 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -127,9 +127,9 @@ namespace osgAnimation template void compute(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { // the result of matrix mult should be cached to be used for vertexes transform and normal transform and maybe other computation - for(VertexGroupSet::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) + for(VertexGroupList::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) { - VertexGroup& uniq = itvg->second; + VertexGroup& uniq = *itvg; uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; @@ -145,9 +145,9 @@ namespace osgAnimation template void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { - for(VertexGroupSet::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) + for(VertexGroupList::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) { - VertexGroup& uniq = itvg->second; + VertexGroup& uniq = *itvg; uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; @@ -165,10 +165,9 @@ namespace osgAnimation std::map _invalidInfluence; - typedef std::vector BoneWeightList; - typedef std::map VertexGroupSet; + typedef std::vector VertexGroupList; - VertexGroupSet _uniqInfluenceSet2VertIDList; + VertexGroupList _uniqInfluenceSet2VertIDList; void buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ); }; diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 3060aa8c3..bf3a9b2be 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -32,11 +32,6 @@ namespace osgAnimation inline void setBoneName(const std::string&s){first=s;} inline const float &getWeight()const{return second;} inline void setWeight(float i){second=i;} - ///default invweight ordered - bool operator <(const BoneWeight&o)const{ - if(getWeight()>o.getWeight()) return true; - if(getWeight() diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 60a9c9476..31de573b3 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -35,6 +35,46 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const } + +// sort by name and weight +struct SortByNameAndWeight : public std::less +{ + bool operator()(const RigTransformSoftware::BonePtrWeight& b0, + const RigTransformSoftware::BonePtrWeight& b1) const + { + if (b0.getBoneName() < b1.getBoneName()) + return true; + else if (b0.getBoneName() > b1.getBoneName()) + return false; + if (b0.getWeight() < b1.getWeight()) + return true; + return false; + } +}; +typedef std::vector BoneWeightList; + +struct SortByBoneWeightList : public std::less +{ + bool operator()(const BoneWeightList& b0, + const BoneWeightList& b1) const + { + if (b0.size() < b1.size()) + return true; + else if (b0.size() > b1.size()) + return false; + + int size = b0.size(); + for (int i = 0; i < size; i++) + { + if (SortByNameAndWeight()(b0[i], b1[i])) + return true; + else if (SortByNameAndWeight()(b1[i], b0[i])) + return false; + } + return false; + } +}; + void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ){ ///1 Create Index2Vec @@ -93,18 +133,24 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig ///2 Create inverse mapping Vec2Vec from previous built Index2Vec ///in order to minimize weighted matrices computation on update _uniqInfluenceSet2VertIDList.clear(); + + typedef std::map UnifyBoneGroup; + UnifyBoneGroup unifyBuffer; vertexID=0; for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) { BoneWeightList& bones = *it; // sort the vector to have a consistent key - std::sort(bones.begin(), bones.end()); + std::sort(bones.begin(), bones.end(), SortByNameAndWeight() ); // we use the vector as key to differentiate group - VertexGroupSet::iterator result = _uniqInfluenceSet2VertIDList.find(bones); - if (result == _uniqInfluenceSet2VertIDList.end()) - _uniqInfluenceSet2VertIDList[bones].getBoneWeights()=bones; - _uniqInfluenceSet2VertIDList[bones].getVertexes().push_back(vertexID); + UnifyBoneGroup::iterator result = unifyBuffer.find(bones); + if (result == unifyBuffer.end()) + unifyBuffer[bones].getBoneWeights()=bones; + unifyBuffer[bones].getVertexes().push_back(vertexID); } + _uniqInfluenceSet2VertIDList.reserve(unifyBuffer.size()); + for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) + _uniqInfluenceSet2VertIDList.push_back(it->second); OSG_DEBUG << "uniq groups " << _uniqInfluenceSet2VertIDList.size() << " for " << rig.getName() << std::endl; }