From 350756e7381868abac8505143916477ab0e36c80 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 18:42:22 +0200 Subject: [PATCH] add 2 method to VertexInfluenceMap: normalize and cullInfluenceCountPerVertex --- include/osgAnimation/VertexInfluence | 6 ++ src/osgAnimation/VertexInfluence.cpp | 82 ++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 9c9e38738..ff0403134 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -65,6 +65,12 @@ namespace osgAnimation std::map(org), osg::Object(org, copyop) {} + ///normalize per vertex weights given numvert of the attached mesh + void normalize(unsigned int numvert); + + ///remove weakest influences in order to fit targetted numbonepervertex + void cullInfluenceCountPerVertex(unsigned int maxnumbonepervertex, float minweight=0, bool renormalize=true); + }; } diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 9c9e178ba..3038e8374 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -20,3 +20,85 @@ using namespace osgAnimation; +struct invweight_ordered +{ + inline bool operator() (const BoneWeight& bw1, const BoneWeight& bw2) + { + if (bw1.getWeight() > bw2.getWeight())return true; + if (bw1.getWeight() < bw2.getWeight())return false; + return(bw1.getBoneName() > PerVertWeights; + std::vector localstore; + localstore.resize(numvert); + for(VertexInfluenceMap::iterator mapit=this->begin(); mapit!=this->end(); ++mapit) { + BoneInfluenceList &curvecinf=mapit->second; + for(BoneInfluenceList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) { + IndexWeight& inf=*curinf; + localstore[inf.first].first+=inf.second; + localstore[inf.first].second.push_back(&inf.second); + + } + } + unsigned int vertid=0; + for(std::vector::iterator itvert=localstore.begin(); itvert!=localstore.end(); ++itvert, ++vertid) { + PerVertWeights & weights=*itvert; + if(weights.first< 1e-4) + { + OSG_WARN << "VertexInfluenceMap::normalize warning the vertex " <::iterator itf =weights.second.begin(); itf!=weights.second.end(); ++itf) + **itf*=mult; + } + } + +} +///remove weakest influences in order to fit targetted numbonepervertex +void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervertex,float minweight, bool renormalize) { + + typedef std::set BoneWeightOrdered; + std::map tempVec2Bones; + for(VertexInfluenceMap::iterator mapit=this->begin(); mapit!=this->end(); ++mapit) { + BoneInfluenceList &curvecinf=mapit->second; + for(BoneInfluenceList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) { + IndexWeight& inf=*curinf; + if( curvecinf.getBoneName().empty()) { + OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << inf.first << " is not assigned to a bone" << std::endl; + } + else if(inf.second>minweight)tempVec2Bones[inf.first].insert(BoneWeight(curvecinf.getBoneName(), inf.second)); + } + } + this->clear(); + for( std::map::iterator mapit=tempVec2Bones.begin(); mapit!=tempVec2Bones.end(); ++mapit) { + BoneWeightOrdered& bwset=mapit->second; + unsigned int newsize=numbonepervertexnewsize)bwset.erase(*bwset.rbegin()); + if(renormalize){ + for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) + sum+=bwit->getWeight(); + if(sum>1e-4){ + sum=1.0f/sum; + for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { + BoneInfluenceList & inf= (*this)[bwit->getBoneName()]; + inf.setBoneName(bwit->getBoneName()); + inf.push_back(IndexWeight(mapit->first, bwit->getWeight()*sum)); + } + } + }else{ + for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { + BoneInfluenceList & inf= (*this)[bwit->getBoneName()]; + inf.setBoneName(bwit->getBoneName()); + inf.push_back(IndexWeight(mapit->first,bwit->getWeight())); + } + + } + } +}