From e2168332864742cf4455c34e6f9efaadf4aadb85 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 14:23:15 +0200 Subject: [PATCH 01/37] few refactoring --- include/osgAnimation/MorphTransformSoftware | 1 + include/osgAnimation/RigTransformSoftware | 53 +++++++++++-------- include/osgAnimation/VertexInfluence | 25 +++++++-- src/osgAnimation/RigTransformSoftware.cpp | 42 ++++++++++++++- src/osgAnimation/VertexInfluence.cpp | 4 +- .../serializers/osgAnimation/RigGeometry.cpp | 2 +- 6 files changed, 97 insertions(+), 30 deletions(-) diff --git a/include/osgAnimation/MorphTransformSoftware b/include/osgAnimation/MorphTransformSoftware index 8ac451b38..1130cdedc 100644 --- a/include/osgAnimation/MorphTransformSoftware +++ b/include/osgAnimation/MorphTransformSoftware @@ -36,6 +36,7 @@ namespace osgAnimation bool init(MorphGeometry&); virtual void operator()(MorphGeometry&); + protected: bool _needInit; diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 8492a215d..677f5e619 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -37,35 +37,43 @@ namespace osgAnimation virtual void operator()(RigGeometry&); - class BonePtrWeight + class BonePtrWeight: public BoneWeight { public: - BonePtrWeight(Bone* bone, float weight) : _bone(bone), _weight(weight) {} - const Bone* getBone() const { return _bone.get(); } - float getWeight() const { return _weight; } - void setWeight(float w) { _weight = w; } + BonePtrWeight(const std::string& name, float weight, Bone *bptr=0) :BoneWeight(name,weight), _boneptr(bptr) {} + BonePtrWeight(const BonePtrWeight &bw2) : BoneWeight(bw2), _boneptr(bw2._boneptr) {} + + const Bone * getBonePtr()const{return _boneptr.get();} + void setBonePtr(Bone*b){_boneptr=b;} + + bool operator==(const BonePtrWeight& b) const { return (getBoneName() == b.getBoneName() && getWeight() == b.getWeight()); } + //default order : sort by weight desc and bonename if equal + /*bool operator<(const BoneWeight& bw2)const{ if (_weight > bw2._weight)return true; + if (_weight < bw2._weight)return false; + return(_boneName _bone; - float _weight; + osg::observer_ptr< Bone > _boneptr; }; + typedef std::vector BonePtrWeightList; + typedef std::vector IndexList; - typedef std::vector BonePtrWeightList; - typedef std::vector VertexList; - + /// map a set of boneinfluence to a list of vertex indices sharing this set class VertexGroup { public: - BonePtrWeightList& getBoneWeights() { return _boneweights; } - VertexList& getVertexes() { return _vertexes; } + inline BonePtrWeightList& getBoneWeights() { return _boneweights; } - void resetMatrix() + inline IndexList& getVertexes() { return _vertexes; } + + inline 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) + inline 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(); @@ -86,7 +94,7 @@ namespace osgAnimation ptrresult[13] += ptr[13] * weight; ptrresult[14] += ptr[14] * weight; } - void computeMatrixForVertexSet() + inline void computeMatrixForVertexSet() { if (_boneweights.empty()) { @@ -98,7 +106,7 @@ namespace osgAnimation for(BonePtrWeightList::iterator bwit=_boneweights.begin();bwit!=_boneweights.end();++bwit ) { - const Bone* bone = bwit->getBone(); + const Bone* bone = bwit->getBonePtr(); if (!bone) { osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl; @@ -110,10 +118,10 @@ namespace osgAnimation accummulateMatrix(invBindMatrix, matrix, w); } } - const osg::Matrix& getMatrix() const { return _result;} + inline const osg::Matrix& getMatrix() const { return _result;} protected: BonePtrWeightList _boneweights; - VertexList _vertexes; + IndexList _vertexes; osg::Matrix _result; }; @@ -128,8 +136,8 @@ namespace osgAnimation uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; - const VertexList& vertexes = uniq.getVertexes(); - for(VertexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) + const IndexList& vertexes = uniq.getVertexes(); + for(IndexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) { dst[*vertIDit] = src[*vertIDit] * matrix; } @@ -146,8 +154,8 @@ namespace osgAnimation uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; - const VertexList& vertexes = uniq.getVertexes(); - for(VertexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) + const IndexList& vertexes = uniq.getVertexes(); + for(IndexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) { dst[*vertIDit] = osg::Matrix::transform3x3(src[*vertIDit],matrix); } @@ -163,6 +171,7 @@ namespace osgAnimation bool _needInit; std::map _invalidInfluence; + }; } diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 0b777e283..4b2adb347 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -23,15 +23,32 @@ namespace osgAnimation { + // first is bonename, and second the weight + struct BoneWeight: public std::pair + { + BoneWeight( std::string f,float s): + std::pair(f,s){} + inline const std::string& getBoneName()const{return first;} + inline void setBoneName(const std::string&s){first=s;} + inline const float &getWeight()const{return second;} + inline void setWeight(float i){second=i;} + }; + // first is vertex index, and second the weight + struct IndexWeight: public std::pair + { + IndexWeight( unsigned int f,float s): std::pair(f,s){} + inline const unsigned int& getIndex()const{return first;} + inline void setIndex(unsigned int i){first=i;} + inline const float &getWeight()const{return second;} + inline void setWeight(float i){second=i;} + }; - // first is vertex index, and second the weight, the - typedef std::pair IndexWeight; typedef std::vector VertexList; class OSGANIMATION_EXPORT BoneInfluenceList : public VertexList { public: - const std::string& getName() const { return _name;} - void setName(const std::string& name) { _name = name;} + const std::string& getBoneName() const { return _name;} + void setBoneName(const std::string& name) { _name = name;} protected: // the name is the bone to link to diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 4ab524cdb..455fddb2b 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -34,6 +34,46 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const } +typedef std::vector BoneWeightList; +// 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; + } +}; + +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++) + { + bool result = SortByNameAndWeight()(b0[i], b1[i]); + if (result) + return true; + else if (SortByNameAndWeight()(b1[i], b0[i])) + return false; + } + return false; + } +}; + bool RigTransformSoftware::init(RigGeometry& geom) { if (!geom.getSkeleton()) @@ -142,7 +182,7 @@ void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const Vert continue; } Bone* bone = it->second.get(); - boneList.push_back(BonePtrWeight(bone, weight)); + boneList.push_back(BonePtrWeight(bone->getName(), weight, bone)); sumOfWeight += weight; } // if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0 diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index b1b10fa26..bcb626190 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -40,10 +40,10 @@ void VertexInfluenceSet::buildVertex2BoneList(unsigned int numvertices) IndexWeight viw = vi[i]; int index = viw.first; float weight = viw.second; - if (vi.getName().empty()){ + if (vi.getBoneName().empty()){ OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; } - _vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight)); + _vertex2Bones[index].push_back(BoneWeight(vi.getBoneName(), weight)); } } diff --git a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp index 5259d1e95..0d88de08d 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp @@ -21,7 +21,7 @@ static bool readInfluenceMap( osgDB::InputStream& is, osgAnimation::RigGeometry& viSize = is.readSize(); is >> is.BEGIN_BRACKET; osgAnimation::BoneInfluenceList vi; - vi.setName( name ); + vi.setBoneName( name ); vi.reserve( viSize ); for ( unsigned int j=0; j Date: Mon, 28 Aug 2017 14:25:12 +0200 Subject: [PATCH 02/37] add prepareData for rigttransform software --- include/osgAnimation/RigTransformSoftware | 3 + src/osgAnimation/RigTransformSoftware.cpp | 138 ++++++++++++++++++++++ 2 files changed, 141 insertions(+) diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 677f5e619..c468322cb 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -36,6 +36,8 @@ namespace osgAnimation META_Object(osgAnimation,RigTransformSoftware) virtual void operator()(RigGeometry&); + //to call when a skeleton is reacheable from the rig to prepare technic data + virtual bool prepareData(RigGeometry&); class BonePtrWeight: public BoneWeight { @@ -172,6 +174,7 @@ namespace osgAnimation std::map _invalidInfluence; + void buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ); }; } diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 455fddb2b..ca13a71a7 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -115,6 +115,144 @@ bool RigTransformSoftware::init(RigGeometry& geom) return true; } +void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ){ + + ///1 Create Index2Vec + typedef std::vector BoneWeightList; + typedef std::vector VertIDToBoneWeightList; + + VertIDToBoneWeightList _vertex2Bones; + _vertex2Bones.clear(); + _vertex2Bones.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements()); + + const VertexInfluenceMap *_vertexInfluenceMap=rig.getInfluenceMap(); + for (osgAnimation::VertexInfluenceMap::const_iterator it = _vertexInfluenceMap->begin(); + it != _vertexInfluenceMap->end(); + ++it) + { + const BoneInfluenceList& inflist = it->second; + for(BoneInfluenceList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) + { + const IndexWeight &iw = *infit; + const unsigned int &index = iw.getIndex(); + float weight = iw.getWeight(); + if (inflist.getBoneName().empty()) { + OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; + } + BoneMap::const_iterator it = boneMap.find(inflist.getBoneName()); + if (it == boneMap.end() ) + { + if (_invalidInfluence.find(inflist.getBoneName()) != _invalidInfluence.end()) { + _invalidInfluence[inflist.getBoneName()] = true; + OSG_WARN << "RigTransformSoftware Bone " << inflist.getBoneName() << " not found, skip the influence group " << std::endl; + } + continue; + } + Bone* bone = it->second.get(); + _vertex2Bones[index].push_back(BonePtrWeight(inflist.getBoneName(), weight,bone));; + } + } + + // normalize _vertex2Bones weight per vertex + unsigned vertexID=0; + for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) + { + BoneWeightList& bones = *it; + float sum = 0; + for(BoneWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) + sum += bwit->getWeight(); + if (sum < 1e-4) + { + OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " << vertexID << " seems to have 0 weight, skip normalize for this vertex" << std::endl; + } + else + { + float mult = 1.0/sum; + for(BoneWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) + bwit->setWeight(bwit->getWeight() * mult); + } + } + + ///2 Create inverse mapping Vec2Vec from previous built Index2Vec + ///in order to minimize weighted matrices computation on update + typedef std::map UnifyBoneGroup; + UnifyBoneGroup unifyBuffer; + vertexID=0; + for (VertIDToBoneWeightList::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(), SortByNameAndWeight()); + // we use the vector as key to differentiate group + UnifyBoneGroup::iterator result = unifyBuffer.find(bones); + if (result == unifyBuffer.end()) + unifyBuffer[bones].getBoneWeights()=bones; + unifyBuffer[bones].getVertexes().push_back(vertexID); + } + if(_vertex2Bones.size()==unifyBuffer.size()) { + OSG_WARN << "RigTransformSoftware::build mapping is useless no duplicate VertexGroup : too much " <<_vertex2Bones.size()<<"=="<second); + + + OSG_DEBUG << "uniq groups " << _uniqInfluenceSet2VertIDList.size() << " for " << rig.getName() << std::endl; +} + +bool RigTransformSoftware::prepareData(RigGeometry&rig) { + if(!rig.getSkeleton() && !rig.getParents().empty()) + { + RigGeometry::FindNearestParentSkeleton finder; + if(rig.getParents().size() > 1) + osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << rig.getName() << " )" << std::endl; + rig.getParents()[0]->accept(finder); + + if(!finder._root.valid()) + { + osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << rig.getName() << " )" << std::endl; + return false; + } + rig.setSkeleton(finder._root.get()); + } + BoneMapVisitor mapVisitor; + rig.getSkeleton()->accept(mapVisitor); + BoneMap boneMap = mapVisitor.getBoneMap(); + + buildMinimumUpdateSet(boneMap,rig); + + if (rig.getSourceGeometry()) + rig.copyFrom(*rig.getSourceGeometry()); + + + osg::Vec3Array* normalSrc = dynamic_cast(rig.getSourceGeometry()->getNormalArray()); + osg::Vec3Array* positionSrc = dynamic_cast(rig.getSourceGeometry()->getVertexArray()); + + if(!(positionSrc) || positionSrc->empty() ) + return false; + if(normalSrc&& normalSrc->size()!=positionSrc->size()) + return false; + + + rig.setVertexArray(new osg::Vec3Array); + osg::Vec3Array* positionDst =new osg::Vec3Array; + rig.setVertexArray(positionDst); + *positionDst=*positionSrc; + positionDst->setDataVariance(osg::Object::DYNAMIC); + + + if(normalSrc) { + osg::Vec3Array* normalDst =new osg::Vec3Array; + *normalDst=*normalSrc; + rig.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX); + normalDst->setDataVariance(osg::Object::DYNAMIC); + } + + _needInit = false; + return true; +} void RigTransformSoftware::operator()(RigGeometry& geom) { if (_needInit) From 2b5ac5b4dbc78e1fa4b15fb1a84df0759d4c9de2 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 15:27:46 +0200 Subject: [PATCH 03/37] add default constructor for IndexWeight with invalid indices --- include/osgAnimation/VertexInfluence | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 4b2adb347..bf3a9b2be 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -36,7 +36,7 @@ namespace osgAnimation // first is vertex index, and second the weight struct IndexWeight: public std::pair { - IndexWeight( unsigned int f,float s): std::pair(f,s){} + IndexWeight( unsigned int f = 0xffffffff,float s = 0.0f): std::pair(f,s){} inline const unsigned int& getIndex()const{return first;} inline void setIndex(unsigned int i){first=i;} inline const float &getWeight()const{return second;} From 4b56a4d3be874f0e27472ddca48d7ad77e374402 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 15:40:04 +0200 Subject: [PATCH 04/37] minor changes+fix --- src/osgAnimation/RigTransformSoftware.cpp | 50 ++++++++++++----------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index ca13a71a7..512e0a407 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -118,44 +118,45 @@ bool RigTransformSoftware::init(RigGeometry& geom) void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ){ ///1 Create Index2Vec - typedef std::vector BoneWeightList; - typedef std::vector VertIDToBoneWeightList; - - VertIDToBoneWeightList _vertex2Bones; - _vertex2Bones.clear(); + std::vector _vertex2Bones; _vertex2Bones.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements()); + typedef std::pair FloatInt; + std::vector< FloatInt > sums;///stat totalweight nbref + sums.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements() + ); const VertexInfluenceMap *_vertexInfluenceMap=rig.getInfluenceMap(); for (osgAnimation::VertexInfluenceMap::const_iterator it = _vertexInfluenceMap->begin(); it != _vertexInfluenceMap->end(); ++it) { const BoneInfluenceList& inflist = it->second; + if (inflist.getBoneName().empty()) { + OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone BoneInfluenceList" << std::endl; + } + BoneMap::const_iterator bmit = boneMap.find(inflist.getBoneName()); + if (bmit == boneMap.end() ) + { + if (_invalidInfluence.find(inflist.getBoneName()) != _invalidInfluence.end()) { + _invalidInfluence[inflist.getBoneName()] = true; + OSG_WARN << "RigTransformSoftware Bone " << inflist.getBoneName() << " not found, skip the influence group " << std::endl; + } + continue; + } + Bone* bone = bmit->second.get(); for(BoneInfluenceList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) { const IndexWeight &iw = *infit; const unsigned int &index = iw.getIndex(); float weight = iw.getWeight(); - if (inflist.getBoneName().empty()) { - OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; - } - BoneMap::const_iterator it = boneMap.find(inflist.getBoneName()); - if (it == boneMap.end() ) - { - if (_invalidInfluence.find(inflist.getBoneName()) != _invalidInfluence.end()) { - _invalidInfluence[inflist.getBoneName()] = true; - OSG_WARN << "RigTransformSoftware Bone " << inflist.getBoneName() << " not found, skip the influence group " << std::endl; - } - continue; - } - Bone* bone = it->second.get(); + _vertex2Bones[index].push_back(BonePtrWeight(inflist.getBoneName(), weight,bone));; } } // normalize _vertex2Bones weight per vertex unsigned vertexID=0; - for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) + for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) { BoneWeightList& bones = *it; float sum = 0; @@ -178,7 +179,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; vertexID=0; - for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) + for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) { BoneWeightList& bones = *it; // sort the vector to have a consistent key @@ -198,11 +199,11 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig 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; } bool RigTransformSoftware::prepareData(RigGeometry&rig) { + ///find skeleton if not set if(!rig.getSkeleton() && !rig.getParents().empty()) { RigGeometry::FindNearestParentSkeleton finder; @@ -217,12 +218,15 @@ bool RigTransformSoftware::prepareData(RigGeometry&rig) { } rig.setSkeleton(finder._root.get()); } + ///get bonemap from skeleton BoneMapVisitor mapVisitor; rig.getSkeleton()->accept(mapVisitor); BoneMap boneMap = mapVisitor.getBoneMap(); + /// build minimal set of VertexGroup buildMinimumUpdateSet(boneMap,rig); + ///set geom as it source if (rig.getSourceGeometry()) rig.copyFrom(*rig.getSourceGeometry()); @@ -235,14 +239,13 @@ bool RigTransformSoftware::prepareData(RigGeometry&rig) { if(normalSrc&& normalSrc->size()!=positionSrc->size()) return false; - + /// setup Vertex and Normal arrays with copy of sources rig.setVertexArray(new osg::Vec3Array); osg::Vec3Array* positionDst =new osg::Vec3Array; rig.setVertexArray(positionDst); *positionDst=*positionSrc; positionDst->setDataVariance(osg::Object::DYNAMIC); - if(normalSrc) { osg::Vec3Array* normalDst =new osg::Vec3Array; *normalDst=*normalSrc; @@ -253,6 +256,7 @@ bool RigTransformSoftware::prepareData(RigGeometry&rig) { _needInit = false; return true; } + void RigTransformSoftware::operator()(RigGeometry& geom) { if (_needInit) From 3efaccb2980eeb7302f403d63b17e11f570ddb11 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 15:41:14 +0200 Subject: [PATCH 05/37] add prepareData for RigTransformHW --- include/osgAnimation/RigTransformHardware | 9 +- src/osgAnimation/RigTransformHardware.cpp | 284 +++++++++++++++++++++- 2 files changed, 285 insertions(+), 8 deletions(-) diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index 28330e87e..4c2aa1875 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -43,7 +43,7 @@ namespace osgAnimation typedef std::map BoneNamePaletteIndex; typedef std::vector MatrixPalette; - struct IndexWeightEntry + /*struct IndexWeightEntry { IndexWeightEntry(unsigned int index=0, float weight=0.0f): _boneIndex(index), _boneWeight(weight){} IndexWeightEntry(const IndexWeightEntry&o): _boneIndex(o._boneIndex), _boneWeight(o._boneWeight){} @@ -52,7 +52,7 @@ namespace osgAnimation const float &getWeight() const { return _boneWeight; } unsigned int _boneIndex; float _boneWeight; - }; + };*/ osg::Vec4Array* getVertexAttrib(unsigned int index); @@ -68,6 +68,8 @@ namespace osgAnimation virtual void operator()(RigGeometry&); + virtual bool prepareData(RigGeometry& ); + void setShader(osg::Shader*); const BoneNamePaletteIndex& getBoneNameToPalette() { @@ -89,6 +91,9 @@ namespace osgAnimation osg::ref_ptr _shader; bool _needInit; + + bool buildPalette(BoneMap&boneMap ,RigGeometry&rig); + }; } diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index ad15c31e6..dc67533ae 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -76,7 +76,7 @@ void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transf unsigned int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;} unsigned int RigTransformHardware::getNumVertexes() const { return _nbVertexes;} -typedef std::vector > VertexIndexWeightList; +typedef std::vector > VertexIndexWeightList; void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList&_vertexIndexMatrixWeightList,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); bool RigTransformHardware::createPalette(unsigned int nbVertexes, const BoneMap &boneMap, const VertexInfluenceSet::VertIDToBoneWeightList& vertexIndexToBoneWeightMap) @@ -111,7 +111,7 @@ bool RigTransformHardware::createPalette(unsigned int nbVertexes, const BoneMap { boneNameCountMap[bw.getBoneName()]++; bonesForThisVertex++; // count max number of bones per vertexes - vertexIndexWeight[vertexID].push_back(IndexWeightEntry(boneName2PaletteIndex->second,bw.getWeight())); + vertexIndexWeight[vertexID].push_back(IndexWeight(boneName2PaletteIndex->second,bw.getWeight())); } else { @@ -125,7 +125,7 @@ bool RigTransformHardware::createPalette(unsigned int nbVertexes, const BoneMap bonesForThisVertex++; _boneNameToPalette[bw.getBoneName()] = _bonePalette.size() ; - vertexIndexWeight[vertexID].push_back(IndexWeightEntry(_bonePalette.size(),bw.getWeight())); + vertexIndexWeight[vertexID].push_back(IndexWeight(_bonePalette.size(),bw.getWeight())); _bonePalette.push_back(bonebyname->second); } } @@ -168,8 +168,12 @@ bool RigTransformHardware::createPalette(unsigned int nbVertexes, const BoneMap // the idea is to use this format to have a granularity smaller // than the 4 bones using two vertex attributes // + void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList& _vertexIndexMatrixWeightList, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) { + +//void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList& _vertexIndexMatrixWeightList, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) +//{ unsigned int nbVertices= rig.getNumVertexes(); unsigned int maxbonepervertex=rig.getNumBonesPerVertex(); unsigned int nbArray = static_cast(ceilf( ((float)maxbonepervertex) * 0.5f)); @@ -195,7 +199,7 @@ void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightLis (*array)[j][1 + boneIndexInVec4] = 0; if (boneIndexInList < maxbonepervertex) { - float boneIndex = static_cast(_vertexIndexMatrixWeightList[j][boneIndexInList].getBoneIndex()); + float boneIndex = static_cast(_vertexIndexMatrixWeightList[j][boneIndexInList].getIndex()); float boneWeight = _vertexIndexMatrixWeightList[j][boneIndexInList].getWeight(); // fill the vec4 (*array)[j][0 + boneIndexInVec4] = boneIndex; @@ -219,6 +223,274 @@ void RigTransformHardware::setShader(osg::Shader* shader) _shader = shader; } +bool RigTransformHardware::prepareData(RigGeometry& rig) +{ + if(!rig.getSkeleton() && !rig.getParents().empty()) + { + RigGeometry::FindNearestParentSkeleton finder; + if(rig.getParents().size() > 1) + osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << rig.getName() << " )" << std::endl; + rig.getParents()[0]->accept(finder); + + if(!finder._root.valid()) + { + osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << rig.getName() << " )" << std::endl; + return false; + } + rig.setSkeleton(finder._root.get()); + } + BoneMapVisitor mapVisitor; + rig.getSkeleton()->accept(mapVisitor); + BoneMap boneMap = mapVisitor.getBoneMap(); + + if (!buildPalette(boneMap,rig) ) + return false; + + osg::Geometry& source = *rig.getSourceGeometry(); + osg::Vec3Array* positionSrc = dynamic_cast(source.getVertexArray()); + if (!positionSrc) + { + OSG_WARN << "RigTransformHardware no vertex array in the geometry " << rig.getName() << std::endl; + return false; + } + + // copy shallow from source geometry to rig + rig.copyFrom(source); + + //if (!createPalette(positionSrc->size(),bm,geom.getVertexInfluenceSet().getVertexToBoneWeightList())) return false; + + osg::ref_ptr program ; + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = rig.getOrCreateStateSet(); + + //grab geom source program and vertex shader if _shader is not setted + if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM))) + { + for(unsigned int i=0; igetNumShaders(); ++i) + if(program->getShader(i)->getType()==osg::Shader::VERTEX) { + vertexshader=program->getShader(i); + program->removeShader(vertexshader); + + } + } else { + program = new osg::Program; + program->setName("HardwareSkinning"); + } + //set default source if _shader is not user setted + if (!vertexshader.valid()) { + if (!_shader.valid()) + vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); + else vertexshader=_shader; + } + + + if (!vertexshader.valid()) { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + + // replace max matrix by the value from uniform + { + std::string str = vertexshader->getShaderSource(); + std::string toreplace = std::string("MAX_MATRIX"); + std::size_t start = str.find(toreplace); + if (std::string::npos == start) { + ///perhaps remanance from previous init (if saved after init) so reload shader + /* OSG_WARN << str << std::endl; + vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); + if (!vertexshader.valid()) { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + str = vertexshader->getShaderSource(); + start = str.find(toreplace); + // _uniformMatrixPalette=stateset->getUniform("matrixPalette"); + unsigned int attribIndex = 11; + unsigned int nbAttribs = getNumVertexAttrib(); + if(nbAttribs==0) + OSG_WARN << "nbAttribs== " << nbAttribs << std::endl; + for (unsigned int i = 0; i < nbAttribs; i++) + { + std::stringstream ss; + ss << "boneWeight" << i; + program->addBindAttribLocation(ss.str(), attribIndex + i); + + if(getVertexAttrib(i)->getNumElements()!=_nbVertexes) + OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; + geom.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + OSG_INFO << "set vertex attrib " << ss.str() << std::endl; + } + _needInit = false; + return true;*/ + } + if (std::string::npos != start) { + std::stringstream ss; + ss << getMatrixPaletteUniform()->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); + } + else + { + OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; + } + + unsigned int attribIndex = 11; + unsigned int nbAttribs = getNumVertexAttrib(); + if(nbAttribs==0) + OSG_WARN << "nbAttribs== " << nbAttribs << std::endl; + for (unsigned int i = 0; i < nbAttribs; i++) + { + std::stringstream ss; + ss << "boneWeight" << i; + program->addBindAttribLocation(ss.str(), attribIndex + i); + + if(getVertexAttrib(i)->getNumElements()!=_nbVertexes) + OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; + rig.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + OSG_INFO << "set vertex attrib " << ss.str() << std::endl; + } + + + program->addShader(vertexshader.get()); + stateset->removeUniform("nbBonesPerVertex"); + stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); + stateset->removeUniform("matrixPalette"); + stateset->addUniform(getMatrixPaletteUniform()); + + stateset->removeAttribute(osg::StateAttribute::PROGRAM); + if(!stateset->getAttribute(osg::StateAttribute::PROGRAM)) + stateset->setAttributeAndModes(program.get()); + + _needInit = false; + return true; +} +void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList&_vertexIndexMatrixWeightList,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); + +bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { + + _nbVertexes = rig.getVertexArray()->getNumElements(); + unsigned int maxBonePerVertex=0; + + typedef std::pair FloatInt; + std::vector< FloatInt > sums;///stat totalweight nbref + sums.resize(_nbVertexes); + + typedef std::map BoneNameCountMap; + _bonePalette.clear(); + _boneNameToPalette.clear(); + BoneNameCountMap boneNameCountMap; + + VertexInfluenceMap *vertexInfluenceMap=rig.getInfluenceMap(); + BoneNamePaletteIndex::iterator boneName2PaletteIndex; + _boneWeightAttribArrays.resize(0); + + // init temp vertex attribute data + VertexIndexWeightList vertexIndexWeight; + vertexIndexWeight.resize(_nbVertexes); + + for (osgAnimation::VertexInfluenceMap::iterator it = vertexInfluenceMap->begin(); + it != vertexInfluenceMap->end(); + ++it) + { + const BoneInfluenceList& boneinflist = it->second; + for(BoneInfluenceList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) + { + const IndexWeight& iw = *infit; + const unsigned int &index = iw.getIndex(); + const float &weight = iw.getWeight(); + + FloatInt &sum=sums[index]; + unsigned int arrayid=sum.second/2; + unsigned short inx=2*(sum.second&1); + + if (boneinflist.getBoneName().empty()) { + OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; + } + + //_vertex2Bones[index].push_back(VertexInfluenceSet::BoneWeight(vi.getName(), weight));; + + if(fabs(weight) > 1e-4) // don't use bone with weight too small + { + if ((boneName2PaletteIndex= _boneNameToPalette.find(boneinflist.getBoneName())) != _boneNameToPalette.end()) + { + boneNameCountMap[boneinflist.getBoneName()]++; + vertexIndexWeight[index].push_back(IndexWeight(boneName2PaletteIndex->second,weight)); + } + else + { + BoneMap::const_iterator bonebyname; + if ((bonebyname=boneMap.find(boneinflist.getBoneName())) == boneMap.end()) + { + OSG_WARN << "RigTransformHardware::createPalette can't find bone " << boneinflist.getBoneName() << "in skeleton bonemap: skip this influence" << std::endl; + continue; + } + boneNameCountMap[boneinflist.getBoneName()] = 1; // for stats + + _boneNameToPalette[boneinflist.getBoneName()] = _bonePalette.size() ; + vertexIndexWeight[index].push_back(IndexWeight(_bonePalette.size(),weight)); + _bonePalette.push_back(bonebyname->second); + sum.first+=weight; + ++sum.second; + } + } + else + { + OSG_WARN << "RigTransformHardware::createPalette Bone " << boneinflist.getBoneName() << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; + } + maxBonePerVertex = osg::maximum(maxBonePerVertex, sum.second); + + } + OSG_INFO << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; + OSG_INFO << "RigTransformHardware::createPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; + + for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it) + { + OSG_INFO << "RigTransformHardware::createPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; + } + + OSG_INFO << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; + + + } + + _bonesPerVertex = maxBonePerVertex; + _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); + + createVertexAttribList(*this,vertexIndexWeight,this->_boneWeightAttribArrays); + // normalize weight per vertex +///..assume not sum=0 + + /* for(BoneWeightAttribList::iterator attribit=_boneWeightAttribArrays.begin();attribit!=_boneWeightAttribArrays.end();++attribit){ + std::vector< std::pair >::iterator countit=sums.begin(); + for(osg::Vec4Array::iterator vert=attribit->get()->begin();vert!=attribit->get()->end();++vert,++countit){ + osg::Vec4& v=*vert; + v[1]/=countit->first; + v[3]/=countit->first; + } + + } + */ + /* unsigned int vertexID=0; + for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) + { + BoneWeightList& bones = *it; + int size = bones.size(); + if (sums[vertexID].first < 1e-4) + { + OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " << it->first << " seems to have 0 weight, skip normalize for this vertex" << std::endl; + } + else + { + float mult = 1.0/sums[vertexID].first ; + for (int i = 0; i < size; i++) + bones[i].setWeight(bones[i].getWeight() * mult); + } + } + */ +return true; +} bool RigTransformHardware::init(RigGeometry& geom) { if (!geom.getSkeleton()) @@ -310,13 +582,13 @@ bool RigTransformHardware::init(RigGeometry& geom) } program->addShader(vertexshader.get()); - + stateset->removeUniform("matrixPalette"); stateset->addUniform(getMatrixPaletteUniform()); stateset->removeUniform("nbBonesPerVertex"); stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); - + stateset->removeAttribute(osg::StateAttribute::PROGRAM); if(!stateset->getAttribute(osg::StateAttribute::PROGRAM)) stateset->setAttributeAndModes(program.get()); From 7659b23f3836c5c7d985582db6e15a07e5bcf67a Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 15:44:09 +0200 Subject: [PATCH 06/37] remove unused --- src/osgAnimation/RigTransformSoftware.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 512e0a407..c1bc46560 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -121,10 +121,6 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig std::vector _vertex2Bones; _vertex2Bones.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements()); - typedef std::pair FloatInt; - std::vector< FloatInt > sums;///stat totalweight nbref - sums.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements() - ); const VertexInfluenceMap *_vertexInfluenceMap=rig.getInfluenceMap(); for (osgAnimation::VertexInfluenceMap::const_iterator it = _vertexInfluenceMap->begin(); it != _vertexInfluenceMap->end(); From 2aab28149fbbdc65cceeb516fe8f8aab47a25b7b Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 15:59:13 +0200 Subject: [PATCH 07/37] reroot to rigtransform::prepareData old path to rig::buildvertexinfluence --- include/osgAnimation/RigGeometry | 9 +++++++-- src/osgAnimation/RigGeometry.cpp | 5 ----- src/osgAnimation/RigTransformHardware.cpp | 2 +- src/osgAnimation/RigTransformSoftware.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index 31cda0179..a636f7717 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include @@ -151,8 +151,13 @@ namespace osgAnimation osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << geom->getName() << " )" << std::endl; return; } - geom->buildVertexInfluenceSet(); geom->setSkeleton(finder._root.get()); + + if(!geom->getRigTransformImplementation()) + { + geom->setRigTransformImplementation(new RigTransformSoftware); + } + geom->getRigTransformImplementation()->prepareData(*geom); } if(!geom->getSkeleton()) diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index b09c61966..bb5a9c8ee 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -118,11 +118,6 @@ void RigGeometry::computeMatrixFromRootSkeleton() void RigGeometry::update() { - if (!getRigTransformImplementation()) - { - _rigTransformImplementation = new RigTransformSoftware; - } - RigTransform& implementation = *getRigTransformImplementation(); (implementation)(*this); } diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index dc67533ae..90c684669 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -600,7 +600,7 @@ bool RigTransformHardware::init(RigGeometry& geom) void RigTransformHardware::operator()(RigGeometry& geom) { if (_needInit) - if (!init(geom)) + if (!prepareData(geom)) return; computeMatrixPaletteUniform(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry()); } diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index c1bc46560..69920cd71 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -256,7 +256,7 @@ bool RigTransformSoftware::prepareData(RigGeometry&rig) { void RigTransformSoftware::operator()(RigGeometry& geom) { if (_needInit) - if (!init(geom)) + if (!prepareData(geom)) return; if (!geom.getSourceGeometry()) { From 6d55d8d341fac5d71d65cfd49e7f1fc4ed0dd48d Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 16:02:00 +0200 Subject: [PATCH 08/37] minor fixes removed unused --- include/osgAnimation/RigTransform | 2 +- src/osgAnimation/RigTransformHardware.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/osgAnimation/RigTransform b/include/osgAnimation/RigTransform index 7be592035..9a6a0e367 100644 --- a/include/osgAnimation/RigTransform +++ b/include/osgAnimation/RigTransform @@ -35,7 +35,7 @@ namespace osgAnimation /// to call manually when a skeleton is reacheable from the rig /// in order to prepare technic data before rendering - virtual bool prepareData(RigGeometry&){} + virtual bool prepareData(RigGeometry&){return true;} protected: virtual ~RigTransform() {} diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index 90c684669..8751455e5 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -390,11 +390,11 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { VertexIndexWeightList vertexIndexWeight; vertexIndexWeight.resize(_nbVertexes); - for (osgAnimation::VertexInfluenceMap::iterator it = vertexInfluenceMap->begin(); - it != vertexInfluenceMap->end(); - ++it) + for (osgAnimation::VertexInfluenceMap::iterator mapit = vertexInfluenceMap->begin(); + mapit != vertexInfluenceMap->end(); + ++mapit) { - const BoneInfluenceList& boneinflist = it->second; + const BoneInfluenceList& boneinflist = mapit->second; for(BoneInfluenceList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) { const IndexWeight& iw = *infit; @@ -402,8 +402,6 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { const float &weight = iw.getWeight(); FloatInt &sum=sums[index]; - unsigned int arrayid=sum.second/2; - unsigned short inx=2*(sum.second&1); if (boneinflist.getBoneName().empty()) { OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; From da1d2b67f7b21ce976538acd49f129da805ea74a Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 16:46:01 +0200 Subject: [PATCH 09/37] remove old path and add few fixes --- include/osgAnimation/RigTransformHardware | 17 +- include/osgAnimation/RigTransformSoftware | 18 +- include/osgAnimation/VertexInfluence | 5 + src/osgAnimation/RigTransformHardware.cpp | 221 +--------------------- src/osgAnimation/RigTransformSoftware.cpp | 149 +-------------- 5 files changed, 25 insertions(+), 385 deletions(-) diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index 4c2aa1875..fd10eeec6 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2009 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -43,17 +44,6 @@ namespace osgAnimation typedef std::map BoneNamePaletteIndex; typedef std::vector MatrixPalette; - /*struct IndexWeightEntry - { - IndexWeightEntry(unsigned int index=0, float weight=0.0f): _boneIndex(index), _boneWeight(weight){} - IndexWeightEntry(const IndexWeightEntry&o): _boneIndex(o._boneIndex), _boneWeight(o._boneWeight){} - bool operator <(const IndexWeightEntry &o)const{return (_boneIndex + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -132,9 +133,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(std::vector::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) + for(VertexGroupSet::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) { - VertexGroup& uniq = *itvg; + VertexGroup& uniq = itvg->second; uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; @@ -150,9 +151,9 @@ namespace osgAnimation template void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { - for(std::vector::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) + for(VertexGroupSet::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) { - VertexGroup& uniq = *itvg; + VertexGroup& uniq = itvg->second; uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; @@ -166,15 +167,16 @@ namespace osgAnimation protected: - bool init(RigGeometry&); - void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexGroupList& influence); - std::vector _uniqInfluenceSet2VertIDList; - bool _needInit; std::map _invalidInfluence; + typedef std::vector BoneWeightList; + typedef std::map VertexGroupSet; + + VertexGroupSet _uniqInfluenceSet2VertIDList; void buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ); + }; } diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index bf3a9b2be..3060aa8c3 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -32,6 +32,11 @@ 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/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index 8751455e5..b4640df4c 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2009 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -79,87 +80,6 @@ unsigned int RigTransformHardware::getNumVertexes() const { return _nbVertexes;} typedef std::vector > VertexIndexWeightList; void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList&_vertexIndexMatrixWeightList,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); -bool RigTransformHardware::createPalette(unsigned int nbVertexes, const BoneMap &boneMap, const VertexInfluenceSet::VertIDToBoneWeightList& vertexIndexToBoneWeightMap) -{ - _nbVertexes = nbVertexes; - typedef std::map BoneNameCountMap; - _bonePalette.clear(); - _boneNameToPalette.clear(); - BoneNameCountMap boneNameCountMap; - // init vertex attribute data - VertexIndexWeightList vertexIndexWeight; - vertexIndexWeight.resize(nbVertexes); - - unsigned int maxBonePerVertex = 0; - if(vertexIndexToBoneWeightMap.size()!=nbVertexes) { - OSG_WARN << "RigTransformHardware::some vertex has no transform " < 1e-4) // don't use bone with weight too small - { - if ((boneName2PaletteIndex= _boneNameToPalette.find(bw.getBoneName())) != _boneNameToPalette.end()) - { - boneNameCountMap[bw.getBoneName()]++; - bonesForThisVertex++; // count max number of bones per vertexes - vertexIndexWeight[vertexID].push_back(IndexWeight(boneName2PaletteIndex->second,bw.getWeight())); - } - else - { - BoneMap::const_iterator bonebyname; - if ((bonebyname=boneMap.find(bw.getBoneName())) == boneMap.end()) - { - OSG_WARN << "RigTransformHardware::createPalette can't find bone " << bw.getBoneName() << "in skeleton bonemap: skip this influence" << std::endl; - continue; - } - boneNameCountMap[bw.getBoneName()] = 1; // for stats - bonesForThisVertex++; - - _boneNameToPalette[bw.getBoneName()] = _bonePalette.size() ; - vertexIndexWeight[vertexID].push_back(IndexWeight(_bonePalette.size(),bw.getWeight())); - _bonePalette.push_back(bonebyname->second); - } - } - else - { - OSG_WARN << "RigTransformHardware::createPalette Bone " << bw.getBoneName() << " has a weight " << bw.getWeight() << " for vertex " << vertexID << " this bone will not be in the palette" << std::endl; - } - } - if(bonesForThisVertex==0) { - OSG_WARN << "RigTransformHardware::no transform for vertex " << vertexID << " this will induce a bug in vertex shader" << std::endl; - } - maxBonePerVertex = osg::maximum(maxBonePerVertex, bonesForThisVertex); - } - OSG_INFO << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; - OSG_INFO << "RigTransformHardware::createPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; - - for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it) - { - OSG_INFO << "RigTransformHardware::createPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; - } - - OSG_INFO << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; - - - _bonesPerVertex = maxBonePerVertex; - for (int i = 0 ; i < (int)vertexIndexWeight.size(); i++) - vertexIndexWeight[i].resize(maxBonePerVertex); - - _uniformMatrixPalette = createVertexUniform(); - createVertexAttribList(*this,vertexIndexWeight,this->_boneWeightAttribArrays); - return true; -} - - // // create vertex attribute by 2 bones // vec4(boneIndex0, weight0, boneIndex1, weight1) @@ -171,9 +91,6 @@ bool RigTransformHardware::createPalette(unsigned int nbVertexes, const BoneMap void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList& _vertexIndexMatrixWeightList, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) { - -//void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList& _vertexIndexMatrixWeightList, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) -//{ unsigned int nbVertices= rig.getNumVertexes(); unsigned int maxbonepervertex=rig.getNumBonesPerVertex(); unsigned int nbArray = static_cast(ceilf( ((float)maxbonepervertex) * 0.5f)); @@ -257,8 +174,6 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) // copy shallow from source geometry to rig rig.copyFrom(source); - //if (!createPalette(positionSrc->size(),bm,geom.getVertexInfluenceSet().getVertexToBoneWeightList())) return false; - osg::ref_ptr program ; osg::ref_ptr vertexshader; osg::ref_ptr stateset = rig.getOrCreateStateSet(); @@ -294,35 +209,6 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) std::string str = vertexshader->getShaderSource(); std::string toreplace = std::string("MAX_MATRIX"); std::size_t start = str.find(toreplace); - if (std::string::npos == start) { - ///perhaps remanance from previous init (if saved after init) so reload shader - /* OSG_WARN << str << std::endl; - vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); - if (!vertexshader.valid()) { - OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; - return false; - } - str = vertexshader->getShaderSource(); - start = str.find(toreplace); - // _uniformMatrixPalette=stateset->getUniform("matrixPalette"); - unsigned int attribIndex = 11; - unsigned int nbAttribs = getNumVertexAttrib(); - if(nbAttribs==0) - OSG_WARN << "nbAttribs== " << nbAttribs << std::endl; - for (unsigned int i = 0; i < nbAttribs; i++) - { - std::stringstream ss; - ss << "boneWeight" << i; - program->addBindAttribLocation(ss.str(), attribIndex + i); - - if(getVertexAttrib(i)->getNumElements()!=_nbVertexes) - OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; - geom.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); - OSG_INFO << "set vertex attrib " << ss.str() << std::endl; - } - _needInit = false; - return true;*/ - } if (std::string::npos != start) { std::stringstream ss; ss << getMatrixPaletteUniform()->getNumElements(); @@ -489,111 +375,6 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { */ return true; } -bool RigTransformHardware::init(RigGeometry& geom) -{ - if (!geom.getSkeleton()) - { - OSG_WARN << "RigTransformHardware no skeleton set in geometry " << geom.getName() << std::endl; - return false; - } - BoneMapVisitor mapVisitor; - geom.getSkeleton()->accept(mapVisitor); - BoneMap bm = mapVisitor.getBoneMap(); - - osg::Geometry& source = *geom.getSourceGeometry(); - osg::Vec3Array* positionSrc = dynamic_cast(source.getVertexArray()); - if (!positionSrc) - { - OSG_WARN << "RigTransformHardware no vertex array in the geometry " << geom.getName() << std::endl; - return false; - } - - // copy shallow from source geometry to rig - geom.copyFrom(source); - - if (!createPalette(positionSrc->size(),bm,geom.getVertexInfluenceSet().getVertexToBoneList())) - return false; - - osg::ref_ptr program ; - osg::ref_ptr vertexshader; - osg::ref_ptr stateset = geom.getOrCreateStateSet(); - - //grab geom source program and vertex shader if _shader is not setted - if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM))) - { - for(unsigned int i=0;igetNumShaders();++i) - if(program->getShader(i)->getType()==osg::Shader::VERTEX){ - vertexshader=program->getShader(i); - program->removeShader(vertexshader); - - } - }else { - program = new osg::Program; - program->setName("HardwareSkinning"); - } - //set default source if _shader is not user setted - if (!vertexshader.valid()){ - if (!_shader.valid()) - vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); - else vertexshader=_shader; - } - - - if (!vertexshader.valid()) { - OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; - return false; - } - - // replace max matrix by the value from uniform - { - std::string str = vertexshader->getShaderSource(); - std::string toreplace = std::string("MAX_MATRIX"); - std::size_t start = str.find(toreplace); - - if (std::string::npos != start) { - std::stringstream ss; - ss << getMatrixPaletteUniform()->getNumElements(); - str.replace(start, toreplace.size(), ss.str()); - vertexshader->setShaderSource(str); - } - else - { - OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl; - } - OSG_INFO << "Shader " << str << std::endl; - } - - unsigned int attribIndex = 11; - unsigned int nbAttribs = getNumVertexAttrib(); - if(nbAttribs==0) - OSG_WARN << "nbAttribs== " << nbAttribs << std::endl; - for (unsigned int i = 0; i < nbAttribs; i++) - { - std::stringstream ss; - ss << "boneWeight" << i; - program->addBindAttribLocation(ss.str(), attribIndex + i); - - if(getVertexAttrib(i)->getNumElements()!=_nbVertexes) - OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; - geom.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); - OSG_INFO << "set vertex attrib " << ss.str() << std::endl; - } - - program->addShader(vertexshader.get()); - - stateset->removeUniform("matrixPalette"); - stateset->addUniform(getMatrixPaletteUniform()); - - stateset->removeUniform("nbBonesPerVertex"); - stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); - - stateset->removeAttribute(osg::StateAttribute::PROGRAM); - if(!stateset->getAttribute(osg::StateAttribute::PROGRAM)) - stateset->setAttributeAndModes(program.get()); - - _needInit = false; - return true; -} void RigTransformHardware::operator()(RigGeometry& geom) { diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 69920cd71..60a9c9476 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2009 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -34,87 +35,6 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const } -typedef std::vector BoneWeightList; -// 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; - } -}; - -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++) - { - bool result = SortByNameAndWeight()(b0[i], b1[i]); - if (result) - return true; - else if (SortByNameAndWeight()(b1[i], b0[i])) - return false; - } - return false; - } -}; - -bool RigTransformSoftware::init(RigGeometry& geom) -{ - if (!geom.getSkeleton()) - return false; - - BoneMapVisitor mapVisitor; - geom.getSkeleton()->accept(mapVisitor); - BoneMap bm = mapVisitor.getBoneMap(); - initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexGroupList()); - - if (geom.getSourceGeometry()) - geom.copyFrom(*geom.getSourceGeometry()); - - - osg::Vec3Array* normalSrc = dynamic_cast(geom.getSourceGeometry()->getNormalArray()); - osg::Vec3Array* positionSrc = dynamic_cast(geom.getSourceGeometry()->getVertexArray()); - - if(!(positionSrc) || positionSrc->empty() ) - return false; - if(normalSrc&& normalSrc->size()!=positionSrc->size()) - return false; - - - geom.setVertexArray(new osg::Vec3Array); - osg::Vec3Array* positionDst =new osg::Vec3Array; - geom.setVertexArray(positionDst); - *positionDst=*positionSrc; - positionDst->setDataVariance(osg::Object::DYNAMIC); - - - if(normalSrc){ - osg::Vec3Array* normalDst =new osg::Vec3Array; - *normalDst=*normalSrc; - geom.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX); - normalDst->setDataVariance(osg::Object::DYNAMIC); - } - - _needInit = false; - return true; -} - void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ){ ///1 Create Index2Vec @@ -172,29 +92,19 @@ 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 - typedef std::map UnifyBoneGroup; - UnifyBoneGroup unifyBuffer; + _uniqInfluenceSet2VertIDList.clear(); 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(), SortByNameAndWeight()); + std::sort(bones.begin(), bones.end()); // we use the vector as key to differentiate group - UnifyBoneGroup::iterator result = unifyBuffer.find(bones); - if (result == unifyBuffer.end()) - unifyBuffer[bones].getBoneWeights()=bones; - unifyBuffer[bones].getVertexes().push_back(vertexID); + VertexGroupSet::iterator result = _uniqInfluenceSet2VertIDList.find(bones); + if (result == _uniqInfluenceSet2VertIDList.end()) + _uniqInfluenceSet2VertIDList[bones].getBoneWeights()=bones; + _uniqInfluenceSet2VertIDList[bones].getVertexes().push_back(vertexID); } - if(_vertex2Bones.size()==unifyBuffer.size()) { - OSG_WARN << "RigTransformSoftware::build mapping is useless no duplicate VertexGroup : too much " <<_vertex2Bones.size()<<"=="<second); - OSG_DEBUG << "uniq groups " << _uniqInfluenceSet2VertIDList.size() << " for " << rig.getName() << std::endl; } @@ -290,48 +200,3 @@ void RigTransformSoftware::operator()(RigGeometry& geom) } } - -///convert BoneWeight to BonePtrWeight using bonemap -void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexGroupList& vertexgroups) -{ - _uniqInfluenceSet2VertIDList.clear(); - - int size = vertexgroups.size(); - _uniqInfluenceSet2VertIDList.resize(size); - //for (VertexInfluenceSet::UniqVertexGroupList::const_iterator vgit=vertexgroups.begin(); vgit!=vertexgroups.end();vgit++) - for(int i = 0; i < size; i++) - { - const VertexInfluenceSet::VertexGroup& vg = vertexgroups[i]; - int nbBones = vg.getBones().size(); - BonePtrWeightList& boneList = _uniqInfluenceSet2VertIDList[i].getBoneWeights(); - - double sumOfWeight = 0; - for (int b = 0; b < nbBones; b++) - { - const std::string& bname = vg.getBones()[b].getBoneName(); - float weight = vg.getBones()[b].getWeight(); - BoneMap::const_iterator it = map.find(bname); - if (it == map.end() ) - { - if (_invalidInfluence.find(bname) != _invalidInfluence.end()) { - _invalidInfluence[bname] = true; - OSG_WARN << "RigTransformSoftware Bone " << bname << " not found, skip the influence group " <second.get(); - boneList.push_back(BonePtrWeight(bone->getName(), weight, bone)); - 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 (!vg.getBones().empty() && - (sumOfWeight < 1.0 - threshold || sumOfWeight > 1.0 + threshold)) - { - for (int b = 0; b < (int)boneList.size(); b++) - boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight); - } - _uniqInfluenceSet2VertIDList[i].getVertexes() = vg.getVertexes(); - } -} From 87070869147515ac648e33a3c1dc0944ce200178 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 17:13:23 +0200 Subject: [PATCH 10/37] fix the example --- .../osganimationhardware.cpp | 176 +++++++++++------- 1 file changed, 110 insertions(+), 66 deletions(-) diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp index 74aacb7ba..eb7d8b3ea 100644 --- a/examples/osganimationhardware/osganimationhardware.cpp +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -45,84 +45,121 @@ osg::ref_ptr program; struct MyRigTransformHardware : public osgAnimation::RigTransformHardware { - void operator()(osgAnimation::RigGeometry& geom) + virtual bool prepareData(osgAnimation::RigGeometry& rig) { - if (_needInit) - if (!init(geom)) - return; - computeMatrixPaletteUniform(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry()); - } + if(!rig.getSkeleton() && !rig.getParents().empty()) + { + osgAnimation::RigGeometry::FindNearestParentSkeleton finder; + if(rig.getParents().size() > 1) + osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << rig.getName() << " )" << std::endl; + rig.getParents()[0]->accept(finder); - bool init(osgAnimation::RigGeometry& geom) - { - osg::Vec3Array* pos = dynamic_cast(geom.getVertexArray()); - if (!pos) { - osg::notify(osg::WARN) << "RigTransformHardware no vertex array in the geometry " << geom.getName() << std::endl; - return false; - } - - if (!geom.getSkeleton()) { - osg::notify(osg::WARN) << "RigTransformHardware no skeleting set in geometry " << geom.getName() << std::endl; - return false; - } - - osgAnimation::BoneMapVisitor mapVisitor; - geom.getSkeleton()->accept(mapVisitor); - osgAnimation::BoneMap bm = mapVisitor.getBoneMap(); - - if (!createPalette(pos->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList())) - return false; - - int attribIndex = 11; - int nbAttribs = getNumVertexAttrib(); - - // use a global program for all avatar - if (!program.valid()) { - program = new osg::Program; - program->setName("HardwareSkinning"); - if (!_shader.valid()) - _shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"shaders/skinning.vert"); - - if (!_shader.valid()) { - osg::notify(osg::WARN) << "RigTransformHardware can't load VertexShader" << std::endl; + if(!finder._root.valid()) + { + osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << rig.getName() << " )" << std::endl; return false; } + rig.setSkeleton(finder._root.get()); + } + osgAnimation::BoneMapVisitor mapVisitor; + rig.getSkeleton()->accept(mapVisitor); + osgAnimation::BoneMap boneMap = mapVisitor.getBoneMap(); - // replace max matrix by the value from uniform + if (!buildPalette(boneMap,rig) ) + return false; + + osg::Geometry& source = *rig.getSourceGeometry(); + osg::Vec3Array* positionSrc = dynamic_cast(source.getVertexArray()); + if (!positionSrc) + { + OSG_WARN << "RigTransformHardware no vertex array in the geometry " << rig.getName() << std::endl; + return false; + } + + // copy shallow from source geometry to rig + rig.copyFrom(source); + + // osg::ref_ptr program ; + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = rig.getOrCreateStateSet(); + + //grab geom source program and vertex shader if _shader is not setted + if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM))) + { + for(unsigned int i=0; igetNumShaders(); ++i) + if(program->getShader(i)->getType()==osg::Shader::VERTEX) + { + vertexshader=program->getShader(i); + program->removeShader(vertexshader); + + } + } + else + { + program = new osg::Program; + program->setName("HardwareSkinning"); + } + //set default source if _shader is not user setted + if (!vertexshader.valid()) + { + if (!_shader.valid()) + vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"shaders/skinning.vert"); + else vertexshader=_shader; + } + + + if (!vertexshader.valid()) + { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + + // replace max matrix by the value from uniform + { + std::string str = vertexshader->getShaderSource(); + std::string toreplace = std::string("MAX_MATRIX"); + std::size_t start = str.find(toreplace); + if (std::string::npos != start) { - std::string str = _shader->getShaderSource(); - std::string toreplace = std::string("MAX_MATRIX"); - std::size_t start = str.find(toreplace); std::stringstream ss; ss << getMatrixPaletteUniform()->getNumElements(); str.replace(start, toreplace.size(), ss.str()); - _shader->setShaderSource(str); - osg::notify(osg::INFO) << "Shader " << str << std::endl; + vertexshader->setShaderSource(str); } - - program->addShader(_shader.get()); - - for (int i = 0; i < nbAttribs; i++) + else { - std::stringstream ss; - ss << "boneWeight" << i; - program->addBindAttribLocation(ss.str(), attribIndex + i); - - osg::notify(osg::INFO) << "set vertex attrib " << ss.str() << std::endl; + OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl; } + OSG_INFO << "Shader " << str << std::endl; } - for (int i = 0; i < nbAttribs; i++) + + unsigned int attribIndex = 11; + unsigned int nbAttribs = getNumVertexAttrib(); + if(nbAttribs==0) + OSG_WARN << "nbAttribs== " << nbAttribs << std::endl; + for (unsigned int i = 0; i < nbAttribs; i++) { std::stringstream ss; ss << "boneWeight" << i; - geom.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + program->addBindAttribLocation(ss.str(), attribIndex + i); + + if(getVertexAttrib(i)->getNumElements()!=_nbVertexes) + OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; + rig.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + OSG_INFO << "set vertex attrib " << ss.str() << std::endl; } - osg::ref_ptr ss = new osg::StateSet; - ss->addUniform(getMatrixPaletteUniform()); - ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex())); - ss->setAttributeAndModes(program.get()); - geom.setStateSet(ss.get()); + + program->addShader(vertexshader.get()); + stateset->removeUniform("nbBonesPerVertex"); + stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); + stateset->removeUniform("matrixPalette"); + stateset->addUniform(getMatrixPaletteUniform()); + + stateset->removeAttribute(osg::StateAttribute::PROGRAM); + if(!stateset->getAttribute(osg::StateAttribute::PROGRAM)) + stateset->setAttributeAndModes(program.get()); + _needInit = false; return true; } @@ -142,10 +179,11 @@ struct SetupRigGeometry : public osg::NodeVisitor } void apply(osg::Drawable& geom) { - if (_hardware) { + if (_hardware) + { osgAnimation::RigGeometry* rig = dynamic_cast(&geom); if (rig) - rig->setRigTransformImplementation(new osgAnimation::RigTransformHardware); + rig->setRigTransformImplementation(new MyRigTransformHardware); } #if 0 @@ -169,7 +207,8 @@ osg::Group* createCharacterInstance(osg::Group* character, bool hardware) osgAnimation::BasicAnimationManager* anim = dynamic_cast(animationManager); const osgAnimation::AnimationList& list = animationManager->getAnimationList(); int v = getRandomValueinRange(list.size()); - if (list[v]->getName() == std::string("MatIpo_ipo")) { + if (list[v]->getName() == std::string("MatIpo_ipo")) + { anim->playAnimation(list[v].get()); v = (v + 1)%list.size(); } @@ -193,7 +232,10 @@ int main (int argc, char* argv[]) bool hardware = true; int maxChar = 10; - while (psr.read("--software")) { hardware = false; } + while (psr.read("--software")) + { + hardware = false; + } while (psr.read("--number", maxChar)) {} osg::ref_ptr node = osgDB::readRefNodeFiles(psr); @@ -243,8 +285,10 @@ int main (int argc, char* argv[]) double xChar = maxChar; double yChar = xChar * 9.0/16; - for (double i = 0.0; i < xChar; i++) { - for (double j = 0.0; j < yChar; j++) { + for (double i = 0.0; i < xChar; i++) + { + for (double j = 0.0; j < yChar; j++) + { osg::ref_ptr c = createCharacterInstance(root.get(), hardware); osg::MatrixTransform* tr = new osg::MatrixTransform; From ad550acc604ff2b468cb9c9b6469f8943ca55a8c Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 17:13:48 +0200 Subject: [PATCH 11/37] clean unused --- include/osgAnimation/RigTransformSoftware | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index eca71eba8..a8d817e64 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -49,12 +49,6 @@ namespace osgAnimation const Bone * getBonePtr()const{return _boneptr.get();} void setBonePtr(Bone*b){_boneptr=b;} - bool operator==(const BonePtrWeight& b) const { return (getBoneName() == b.getBoneName() && getWeight() == b.getWeight()); } - //default order : sort by weight desc and bonename if equal - /*bool operator<(const BoneWeight& bw2)const{ if (_weight > bw2._weight)return true; - if (_weight < bw2._weight)return false; - return(_boneName _boneptr; }; From 28bb88a0386638994de17f123af67cc549fd9a91 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 18:02:52 +0200 Subject: [PATCH 12/37] remove default order for BoneWeight and restore old sort func (behaviors differs) --- include/osgAnimation/RigTransformSoftware | 13 +++--- include/osgAnimation/VertexInfluence | 5 -- src/osgAnimation/RigTransformSoftware.cpp | 56 +++++++++++++++++++++-- 3 files changed, 57 insertions(+), 17 deletions(-) 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; } From 925f1524cffae2045d7c6175e45940a175cf498e Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 18:16:30 +0200 Subject: [PATCH 13/37] total removal of the old path --- include/osgAnimation/RigGeometry | 8 -- include/osgAnimation/VertexInfluence | 56 ------------ src/osgAnimation/RigGeometry.cpp | 18 ---- src/osgAnimation/VertexInfluence.cpp | 127 --------------------------- 4 files changed, 209 deletions(-) diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index a636f7717..a2a096b51 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -69,14 +69,8 @@ namespace osgAnimation void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;} bool getNeedToComputeMatrix() const { return _needToComputeMatrix;} - - // this build the internal database about vertex influence and bones - void buildVertexInfluenceSet(); - inline const VertexInfluenceSet& getVertexInfluenceSet() const { return _vertexInfluenceSet;} - void computeMatrixFromRootSkeleton(); - // set implementation of rig method inline RigTransform* getRigTransformImplementation() { return _rigTransformImplementation.get(); } inline void setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; } @@ -87,7 +81,6 @@ namespace osgAnimation const osg::Matrix& getMatrixFromSkeletonToGeometry() const; const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const; - inline osg::Geometry* getSourceGeometry() { return _geometry.get(); } inline const osg::Geometry* getSourceGeometry() const { return _geometry.get(); } inline void setSourceGeometry(osg::Geometry* geometry) { _geometry = geometry; } @@ -112,7 +105,6 @@ namespace osgAnimation osg::ref_ptr _geometry; osg::ref_ptr _rigTransformImplementation; - VertexInfluenceSet _vertexInfluenceSet; osg::ref_ptr _vertexInfluenceMap; osg::Matrix _matrixFromSkeletonToGeometry; diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index bf3a9b2be..9c9e38738 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -67,62 +67,6 @@ namespace osgAnimation {} }; - - // this class manage VertexInfluence database by mesh - // reference bones per vertex ... - class OSGANIMATION_EXPORT VertexInfluenceSet - { - public: - typedef std::vector BoneToVertexList; - - class BoneWeight - { - public: - BoneWeight(const std::string& name, float weight) : _boneName(name), _weight(weight) {} - BoneWeight(const BoneWeight &bw2) : _boneName(bw2._boneName), _weight(bw2._weight) {} - const std::string& getBoneName() const { return _boneName; } - float getWeight() const { return _weight; } - void setWeight(float weight) { _weight = weight; } - bool operator==(const BoneWeight& b) const { return (_boneName == b.getBoneName() && _weight == b.getWeight()); } - - protected: - std::string _boneName; - float _weight; - }; - - typedef std::vector BoneWeightList; - typedef std::vector VertIDToBoneWeightList; - - class VertexGroup - { - public: - // set Influences of the VertexGroup - void setBones(BoneWeightList& bones) { _bones = bones;} - const BoneWeightList& getBones() const { return _bones;} - // set Vertex Indices of the VertexGroup - std::vector& getVertexes() { return _vertexes;} - const std::vector& getVertexes() const { return _vertexes;} - protected: - std::vector _vertexes; - BoneWeightList _bones; // here we could limit matrix operation by caching (weight * matrix) - }; - - typedef std::vector UniqVertexGroupList; - /** construct a vector of unique VertexGroups and their influences**/ - void buildUniqVertexGroupList(); - /** return a list of unique VertexGroups and their influences**/ - const UniqVertexGroupList& getUniqVertexGroupList() const { return _uniqVertexSetToBoneSet;} - void addVertexInfluence(const BoneInfluenceList& v); - void buildVertex2BoneList(unsigned int numvertices); - void clear(); - - const VertIDToBoneWeightList& getVertexToBoneList() const; - protected: - BoneToVertexList _bone2Vertexes; - VertIDToBoneWeightList _vertex2Bones; - UniqVertexGroupList _uniqVertexSetToBoneSet; - }; - } #endif diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index bb5a9c8ee..057625876 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -66,7 +66,6 @@ RigGeometry::RigGeometry() RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) : osg::Geometry(b,copyop), _geometry(b._geometry), - _vertexInfluenceSet(b._vertexInfluenceSet), _vertexInfluenceMap(b._vertexInfluenceMap), _needToComputeMatrix(b._needToComputeMatrix) { @@ -84,23 +83,6 @@ RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) : const osg::Matrix& RigGeometry::getMatrixFromSkeletonToGeometry() const { return _matrixFromSkeletonToGeometry; } const osg::Matrix& RigGeometry::getInvMatrixFromSkeletonToGeometry() const { return _invMatrixFromSkeletonToGeometry;} -void RigGeometry::buildVertexInfluenceSet() -{ - if (!_vertexInfluenceMap.valid()) - { - OSG_WARN << "buildVertexInfluenceSet can't be called without VertexInfluence already set to the RigGeometry ( " << getName() << " ) " << std::endl; - return; - } - _vertexInfluenceSet.clear(); - for (osgAnimation::VertexInfluenceMap::iterator it = _vertexInfluenceMap->begin(); - it != _vertexInfluenceMap->end(); - ++it){ - _vertexInfluenceSet.addVertexInfluence(it->second); - } - _vertexInfluenceSet.buildVertex2BoneList(getSourceGeometry()->getVertexArray()->getNumElements()); - _vertexInfluenceSet.buildUniqVertexGroupList(); - OSG_DEBUG << "uniq groups " << _vertexInfluenceSet.getUniqVertexGroupList().size() << " for " << getName() << std::endl; -} void RigGeometry::computeMatrixFromRootSkeleton() { diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index bcb626190..9c9e178ba 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -20,130 +20,3 @@ using namespace osgAnimation; -void VertexInfluenceSet::addVertexInfluence(const BoneInfluenceList& v) { _bone2Vertexes.push_back(v); } -const VertexInfluenceSet::VertIDToBoneWeightList& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;} -// this class manage VertexInfluence database by mesh -// reference bones per vertex ... - -void VertexInfluenceSet::buildVertex2BoneList(unsigned int numvertices) -{ - _vertex2Bones.clear(); - _vertex2Bones.reserve(numvertices); - _vertex2Bones.resize(numvertices); - - for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); ++it) - { - const BoneInfluenceList& vi = (*it); - int size = vi.size(); - for (int i = 0; i < size; i++) - { - IndexWeight viw = vi[i]; - int index = viw.first; - float weight = viw.second; - if (vi.getBoneName().empty()){ - OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; - } - _vertex2Bones[index].push_back(BoneWeight(vi.getBoneName(), weight)); - } - } - - // normalize weight per vertex - unsigned int vertid=0; - for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertid) - { - BoneWeightList& bones =*it; - int size = bones.size(); - float sum = 0; - for (int i = 0; i < size; i++) - sum += bones[i].getWeight(); - if (sum < 1e-4) - { - OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " < -{ - bool operator()(const VertexInfluenceSet::BoneWeight& b0, - const VertexInfluenceSet::BoneWeight& 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; - } -}; - -struct SortByBoneWeightList : public std::less -{ - bool operator()(const VertexInfluenceSet::BoneWeightList& b0, - const VertexInfluenceSet::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++) - { - bool result = SortByNameAndWeight()(b0[i], b1[i]); - if (result) - return true; - else if (SortByNameAndWeight()(b1[i], b0[i])) - return false; - } - return false; - } -}; - -void VertexInfluenceSet::clear() -{ - _bone2Vertexes.clear(); - _uniqVertexSetToBoneSet.clear(); -} - -void VertexInfluenceSet::buildUniqVertexGroupList() -{ - _uniqVertexSetToBoneSet.clear(); - - typedef std::map UnifyBoneGroup; - UnifyBoneGroup unifyBuffer; - - unsigned int vertexID=0; - for (VertIDToBoneWeightList::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(), SortByNameAndWeight()); - - // we use the vector as key to differentiate group - UnifyBoneGroup::iterator result = unifyBuffer.find(bones); - if (result == unifyBuffer.end()) - unifyBuffer[bones].setBones(bones); - unifyBuffer[bones].getVertexes().push_back(vertexID); - } - - _uniqVertexSetToBoneSet.reserve(unifyBuffer.size()); - - - for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) - { - _uniqVertexSetToBoneSet.push_back(it->second); - } -} - From 5123614f892680253c8ef40b27de890f79dcc3d3 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 18:27:23 +0200 Subject: [PATCH 14/37] comply with refactoring --- src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp index 78824ad7c..b8813ae70 100644 --- a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp @@ -814,7 +814,7 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr) } osgAnimation::BoneInfluenceList vi; - vi.setName(name); + vi.setBoneName(name); vi.reserve(nbVertexes); for (int j = 0; j < nbVertexes; j++) { From 350756e7381868abac8505143916477ab0e36c80 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 18:42:22 +0200 Subject: [PATCH 15/37] 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())); + } + + } + } +} From 4a626cea2071a63b00de2b6f4e0c5a855c4e6b30 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 00:07:07 +0200 Subject: [PATCH 16/37] remove VertexInfluenceSet --- examples/osganimationskinning/osganimationskinning.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/osganimationskinning/osganimationskinning.cpp b/examples/osganimationskinning/osganimationskinning.cpp index bbf4614fb..c28a2b15d 100644 --- a/examples/osganimationskinning/osganimationskinning.cpp +++ b/examples/osganimationskinning/osganimationskinning.cpp @@ -134,12 +134,11 @@ void initVertexMap(osgAnimation::Bone* b0, osgAnimation::RigGeometry* geom, osg::Vec3Array* array) { - osgAnimation::VertexInfluenceSet vertexesInfluences; osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap; - (*vim)[b0->getName()].setName(b0->getName()); - (*vim)[b1->getName()].setName(b1->getName()); - (*vim)[b2->getName()].setName(b2->getName()); + (*vim)[b0->getName()].setBoneName(b0->getName()); + (*vim)[b1->getName()].setBoneName(b1->getName()); + (*vim)[b2->getName()].setBoneName(b2->getName()); for (int i = 0; i < (int)array->size(); i++) { From 9856cecb71b68e38bd57294772eef0c1fb869a83 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 00:09:38 +0200 Subject: [PATCH 17/37] cleanup --- include/osgAnimation/VertexInfluence | 14 ++++++++++-- src/osgAnimation/RigTransformSoftware.cpp | 28 +++++++++++------------ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index ff0403134..317a45e87 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -42,9 +42,19 @@ namespace osgAnimation inline const float &getWeight()const{return second;} inline void setWeight(float i){second=i;} }; + typedef std::vector IndexWeightList; + typedef std::vector BoneWeightList; + typedef std::vector IndexList; - typedef std::vector VertexList; - class OSGANIMATION_EXPORT BoneInfluenceList : public VertexList + /// map a set of boneinfluence to a list of vertex indices sharing this set + class VertexGroup: public std::pair + { + public: + inline const BoneWeightList& getBoneWeights()const { return first; } + inline void setBoneWeights(BoneWeightList&o) { first=o; } + inline IndexList& vertIDs() { return second; } + }; + class OSGANIMATION_EXPORT BoneInfluenceList : public IndexWeightList { public: const std::string& getBoneName() const { return _name;} diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 31de573b3..d7d1515df 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -46,17 +46,15 @@ struct SortByNameAndWeight : public std::less b1.getBoneName()) return false; - if (b0.getWeight() < b1.getWeight()) - return true; - return false; + return (b0.getWeight() < b1.getWeight()); } }; -typedef std::vector BoneWeightList; +typedef std::vector BonePtrWeightList; -struct SortByBoneWeightList : public std::less +struct SortByBoneWeightList : public std::less { - bool operator()(const BoneWeightList& b0, - const BoneWeightList& b1) const + bool operator()(const BonePtrWeightList& b0, + const BonePtrWeightList& b1) const { if (b0.size() < b1.size()) return true; @@ -78,7 +76,7 @@ struct SortByBoneWeightList : public std::less void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ){ ///1 Create Index2Vec - std::vector _vertex2Bones; + std::vector _vertex2Bones; _vertex2Bones.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements()); const VertexInfluenceMap *_vertexInfluenceMap=rig.getInfluenceMap(); @@ -112,11 +110,11 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig // normalize _vertex2Bones weight per vertex unsigned vertexID=0; - for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) + for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) { - BoneWeightList& bones = *it; + BonePtrWeightList& bones = *it; float sum = 0; - for(BoneWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) + for(BonePtrWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) sum += bwit->getWeight(); if (sum < 1e-4) { @@ -125,7 +123,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig else { float mult = 1.0/sum; - for(BoneWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) + for(BonePtrWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) bwit->setWeight(bwit->getWeight() * mult); } } @@ -134,12 +132,12 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig ///in order to minimize weighted matrices computation on update _uniqInfluenceSet2VertIDList.clear(); - typedef std::map UnifyBoneGroup; + typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; vertexID=0; - for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) + for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) { - BoneWeightList& bones = *it; + BonePtrWeightList& bones = *it; // sort the vector to have a consistent key std::sort(bones.begin(), bones.end(), SortByNameAndWeight() ); // we use the vector as key to differentiate group From b3402d9344f9fd877cbc27cdc43ce4d60ad082ad Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 00:34:26 +0200 Subject: [PATCH 18/37] readd the 2 methods in InfluenceMap just in case --- include/osgAnimation/VertexInfluence | 4 ++ src/osgAnimation/VertexInfluence.cpp | 90 ++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 317a45e87..1b35b2c0f 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -81,6 +81,10 @@ namespace osgAnimation ///remove weakest influences in order to fit targetted numbonepervertex void cullInfluenceCountPerVertex(unsigned int maxnumbonepervertex, float minweight=0, bool renormalize=true); + //compute PerVertexInfluenceList + void computePerVertexInfluenceList(std::vector& vertex2Bones,unsigned int numvert)const; + //create the minimal VertexGroup set + void computeMinimalVertexGroupList(std::vector&uniqVertexGroupList,unsigned int numvert)const; }; } diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 3038e8374..dabaca32f 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -102,3 +102,93 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert } } } + +void VertexInfluenceMap::computePerVertexInfluenceList(std::vector& vertex2Bones,unsigned int numvert)const +{ + vertex2Bones.resize(numvert); + for (osgAnimation::VertexInfluenceMap::const_iterator it = begin(); + it != end(); + ++it) + { + const BoneInfluenceList& inflist = it->second; + if (inflist.getBoneName().empty()) { + OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone BoneInfluenceList" << std::endl; + } + for(BoneInfluenceList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) + { + const IndexWeight &iw = *infit; + const unsigned int &index = iw.getIndex(); + float weight = iw.getWeight(); + + vertex2Bones[index].push_back(BoneWeight(inflist.getBoneName(), weight));; + } + } +} + +// sort by name and weight +struct SortByNameAndWeight : public std::less +{ + bool operator()(const BoneWeight& b0, + const BoneWeight& b1) const + { + if (b0.getBoneName() < b1.getBoneName()) + return true; + else if (b0.getBoneName() > b1.getBoneName()) + return false; + return (b0.getWeight() < b1.getWeight()); + } +}; + +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 VertexInfluenceMap::computeMinimalVertexGroupList(std::vector&uniqVertexGroupList,unsigned int numvert)const +{ + uniqVertexGroupList.clear(); + std::vector vertex2Bones; + computePerVertexInfluenceList(vertex2Bones,numvert); + typedef std::map UnifyBoneGroup; + UnifyBoneGroup unifyBuffer; + + unsigned int vertexID=0; + for (std::vector::iterator it = vertex2Bones.begin(); it != vertex2Bones.end(); ++it,++vertexID) + { + BoneWeightList &boneweightlist = *it;//->second; + //int vertexIndex = it->first; + + // sort the vector to have a consistent key + std::sort(boneweightlist.begin(), boneweightlist.end(), SortByNameAndWeight()); + + // we use the vector as key to differentiate group + UnifyBoneGroup::iterator result = unifyBuffer.find(boneweightlist); + if (result == unifyBuffer.end()) + unifyBuffer[boneweightlist].setBoneWeights(boneweightlist); + unifyBuffer[boneweightlist].vertIDs().push_back(vertexID); + } + if(vertex2Bones.size()==unifyBuffer.size()) { + OSG_WARN << "VertexInfluenceSet::buildmap is useless no duplicate VertexGroup" << std::endl; + } + uniqVertexGroupList.reserve(unifyBuffer.size()); + for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) + { + uniqVertexGroupList.push_back(it->second); + } +} From 0c9a624026ad7eedad77cc187983d6761c77f4cb Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 02:55:40 +0200 Subject: [PATCH 19/37] few refactoring and fixes --- include/osgAnimation/RigTransformSoftware | 15 +++++++------- include/osgAnimation/VertexInfluence | 24 ++++++++++++----------- src/osgAnimation/RigTransformSoftware.cpp | 20 ++++++++++++------- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 9d2a014dc..fa8aabcb9 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -53,7 +53,6 @@ namespace osgAnimation osg::observer_ptr< Bone > _boneptr; }; typedef std::vector BonePtrWeightList; - typedef std::vector IndexList; /// map a set of boneinfluence to a list of vertex indices sharing this set class VertexGroup @@ -61,7 +60,7 @@ namespace osgAnimation public: inline BonePtrWeightList& getBoneWeights() { return _boneweights; } - inline IndexList& getVertexes() { return _vertexes; } + inline IndexList& getVertices() { return _vertexes; } inline void resetMatrix() { @@ -122,9 +121,8 @@ namespace osgAnimation osg::Matrix _result; }; - - - template void compute(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) + template + inline 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(VertexGroupList::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) @@ -133,7 +131,7 @@ namespace osgAnimation uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; - const IndexList& vertexes = uniq.getVertexes(); + const IndexList& vertexes = uniq.getVertices(); for(IndexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) { dst[*vertIDit] = src[*vertIDit] * matrix; @@ -143,7 +141,8 @@ namespace osgAnimation } - template void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) + template + inline void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { for(VertexGroupList::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) { @@ -151,7 +150,7 @@ namespace osgAnimation uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; - const IndexList& vertexes = uniq.getVertexes(); + const IndexList& vertexes = uniq.getVertices(); for(IndexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) { dst[*vertIDit] = osg::Matrix::transform3x3(src[*vertIDit],matrix); diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 1b35b2c0f..4bb42b105 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -46,14 +46,6 @@ namespace osgAnimation typedef std::vector BoneWeightList; typedef std::vector IndexList; - /// map a set of boneinfluence to a list of vertex indices sharing this set - class VertexGroup: public std::pair - { - public: - inline const BoneWeightList& getBoneWeights()const { return first; } - inline void setBoneWeights(BoneWeightList&o) { first=o; } - inline IndexList& vertIDs() { return second; } - }; class OSGANIMATION_EXPORT BoneInfluenceList : public IndexWeightList { public: @@ -82,9 +74,19 @@ namespace osgAnimation void cullInfluenceCountPerVertex(unsigned int maxnumbonepervertex, float minweight=0, bool renormalize=true); //compute PerVertexInfluenceList - void computePerVertexInfluenceList(std::vector& vertex2Bones,unsigned int numvert)const; - //create the minimal VertexGroup set - void computeMinimalVertexGroupList(std::vector&uniqVertexGroupList,unsigned int numvert)const; + void computePerVertexInfluenceList(std::vector& perVertexInfluenceList, unsigned int numvert)const; + + /// map a set of boneinfluence to a list of vertex indices sharing this set + class VertexGroup: public std::pair + { + public: + inline const BoneWeightList& getBoneWeights()const { return first; } + inline void setBoneWeights( BoneWeightList& o ) { first=o; } + inline IndexList& vertIDs() { return second; } + }; + + /// compute the minimal VertexGroup Set in which vertices shares the same influence set + void computeMinimalVertexGroupList(std::vector&uniqVertexGroupList, unsigned int numvert)const; }; } diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index d7d1515df..ff241bc91 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -20,6 +20,7 @@ #include #include + using namespace osgAnimation; RigTransformSoftware::RigTransformSoftware() @@ -35,7 +36,6 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const } - // sort by name and weight struct SortByNameAndWeight : public std::less { @@ -104,7 +104,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig const unsigned int &index = iw.getIndex(); float weight = iw.getWeight(); - _vertex2Bones[index].push_back(BonePtrWeight(inflist.getBoneName(), weight,bone));; + _vertex2Bones[index].push_back(BonePtrWeight(inflist.getBoneName(), weight,bone)); } } @@ -135,19 +135,25 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; vertexID=0; + ; for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) { - BonePtrWeightList& bones = *it; + BonePtrWeightList bones = *it; // sort the vector to have a consistent key std::sort(bones.begin(), bones.end(), SortByNameAndWeight() ); // we use the vector as key to differentiate group UnifyBoneGroup::iterator result = unifyBuffer.find(bones); - if (result == unifyBuffer.end()) - unifyBuffer[bones].getBoneWeights()=bones; - unifyBuffer[bones].getVertexes().push_back(vertexID); + if (result != unifyBuffer.end()) + result->second.getVertices().push_back(vertexID); + else + { + VertexGroup& vg = unifyBuffer[bones]; + vg.getBoneWeights() = bones; + vg.getVertices().push_back(vertexID); + } } _uniqInfluenceSet2VertIDList.reserve(unifyBuffer.size()); - for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) + for (UnifyBoneGroup::const_iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) _uniqInfluenceSet2VertIDList.push_back(it->second); OSG_DEBUG << "uniq groups " << _uniqInfluenceSet2VertIDList.size() << " for " << rig.getName() << std::endl; } From 059fc703379f54c60fbe7004d3de6af5db53d9a3 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 14:11:44 +0200 Subject: [PATCH 20/37] set defaut implementation at creation --- include/osgAnimation/MorphGeometry | 20 ++++++++++---------- include/osgAnimation/MorphTransformHardware | 2 +- include/osgAnimation/RigGeometry | 4 ---- src/osgAnimation/MorphGeometry.cpp | 6 +++--- src/osgAnimation/MorphTransformHardware.cpp | 2 +- src/osgAnimation/RigGeometry.cpp | 4 +++- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index a1ec3f697..9c87ac681 100644 --- a/include/osgAnimation/MorphGeometry +++ b/include/osgAnimation/MorphGeometry @@ -61,25 +61,25 @@ namespace osgAnimation virtual const char* className() const { return "MorphGeometry"; } // set implementation of rig method - void setMorphTransformImplementation(MorphTransform*); - MorphTransform* getMorphTransformImplementation(); - const MorphTransform* getMorphTransformImplementation() const { return _rigTransformImplementation.get(); } + inline void setMorphTransformImplementation(MorphTransform*mt) { _morphTransformImplementation=mt; } + inline MorphTransform* getMorphTransformImplementation() { return _morphTransformImplementation.get(); } + inline const MorphTransform* getMorphTransformImplementation() const { return _morphTransformImplementation.get(); } /** Set the morphing method. */ - void setMethod(Method method) { _method = method; } + inline void setMethod(Method method) { _method = method; } /** Get the morphing method. */ inline Method getMethod() const { return _method; } /** Set flag for morphing normals. */ - void setMorphNormals(bool morphNormals) { _morphNormals = morphNormals; } + inline void setMorphNormals(bool morphNormals) { _morphNormals = morphNormals; } /** Get the flag for morphing normals. */ inline bool getMorphNormals() const { return _morphNormals; } /** Get the list of MorphTargets.*/ - const MorphTargetList& getMorphTargetList() const { return _morphTargets; } + inline const MorphTargetList& getMorphTargetList() const { return _morphTargets; } /** Get the list of MorphTargets. Warning if you modify this array you will have to call dirty() */ - MorphTargetList& getMorphTargetList() { return _morphTargets; } + inline MorphTargetList& getMorphTargetList() { return _morphTargets; } /** Return the \c MorphTarget at position \c i.*/ inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; } @@ -130,7 +130,7 @@ namespace osgAnimation } /** update a morph target at index setting its current weight to morphWeight */ - void setWeight(unsigned int index, float morphWeight) + inline void setWeight(unsigned int index, float morphWeight) { if (index < _morphTargets.size()) { @@ -144,10 +144,10 @@ namespace osgAnimation inline bool isDirty()const { return _dirty; } /** for retrocompatibility */ - virtual void transformSoftwareMethod(){ if (!_rigTransformImplementation.valid())_rigTransformImplementation = new MorphTransformSoftware();(*_rigTransformImplementation.get())(*this);} + virtual void transformSoftwareMethod(){(*_morphTransformImplementation.get())(*this);} protected: - osg::ref_ptr _rigTransformImplementation; + osg::ref_ptr _morphTransformImplementation; /// Do we need to recalculate the morphed geometry? bool _dirty; diff --git a/include/osgAnimation/MorphTransformHardware b/include/osgAnimation/MorphTransformHardware index e75114a74..9b5e5239b 100644 --- a/include/osgAnimation/MorphTransformHardware +++ b/include/osgAnimation/MorphTransformHardware @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2009 Cedric Pinson + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index a2a096b51..e3b3c4a46 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -145,10 +145,6 @@ namespace osgAnimation } geom->setSkeleton(finder._root.get()); - if(!geom->getRigTransformImplementation()) - { - geom->setRigTransformImplementation(new RigTransformSoftware); - } geom->getRigTransformImplementation()->prepareData(*geom); } diff --git a/src/osgAnimation/MorphGeometry.cpp b/src/osgAnimation/MorphGeometry.cpp index f52c04c3a..07a86d1a6 100644 --- a/src/osgAnimation/MorphGeometry.cpp +++ b/src/osgAnimation/MorphGeometry.cpp @@ -29,6 +29,7 @@ MorphGeometry::MorphGeometry() : setUseDisplayList(false); setUpdateCallback(new UpdateMorphGeometry); setUseVertexBufferObjects(true); + _morphTransformImplementation = new MorphTransformSoftware(); } MorphGeometry::MorphGeometry(const osg::Geometry& g) : @@ -41,10 +42,12 @@ MorphGeometry::MorphGeometry(const osg::Geometry& g) : setUseDisplayList(false); setUpdateCallback(new UpdateMorphGeometry); setUseVertexBufferObjects(true); + _morphTransformImplementation = new MorphTransformSoftware(); } MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop) : osg::Geometry(b,copyop), + _morphTransformImplementation((MorphTransform*)copyop(b._morphTransformImplementation)), _dirty(b._dirty), _method(b._method), _morphTargets(b._morphTargets), @@ -56,9 +59,6 @@ MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop) setUseVertexBufferObjects(true); } -MorphTransform* MorphGeometry::getMorphTransformImplementation() { return _rigTransformImplementation.get(); } -void MorphGeometry::setMorphTransformImplementation(MorphTransform* rig) { _rigTransformImplementation = rig; } - UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) : osg::Object(apc, copyop), osg::Callback(apc, copyop), diff --git a/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp index be37a470a..8b5351cea 100644 --- a/src/osgAnimation/MorphTransformHardware.cpp +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyleft 2016 Valentin Julien + * Copyright (C) 2017 Julien Valentin * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index 057625876..c176cf9df 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -59,6 +59,7 @@ RigGeometry::RigGeometry() _matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity(); // disable the computation of boundingbox for the rig mesh setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback()); + _rigTransformImplementation = new osgAnimation::RigTransformSoftware; } @@ -66,6 +67,7 @@ RigGeometry::RigGeometry() RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) : osg::Geometry(b,copyop), _geometry(b._geometry), + _rigTransformImplementation((RigTransform*)copyop(b._rigTransformImplementation)), _vertexInfluenceMap(b._vertexInfluenceMap), _needToComputeMatrix(b._needToComputeMatrix) { @@ -100,7 +102,7 @@ void RigGeometry::computeMatrixFromRootSkeleton() void RigGeometry::update() { - RigTransform& implementation = *getRigTransformImplementation(); + RigTransform& implementation = *_rigTransformImplementation; (implementation)(*this); } From 21bcd61c92c3af8e4ee7f576d404e23868d4a9af Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 14:47:56 +0200 Subject: [PATCH 21/37] add MorphTransformHW for RigGeometry sources that are MorphGeometry --- examples/osganimationhardware/osganimationhardware.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp index eb7d8b3ea..4c65644a8 100644 --- a/examples/osganimationhardware/osganimationhardware.cpp +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -182,8 +184,11 @@ struct SetupRigGeometry : public osg::NodeVisitor if (_hardware) { osgAnimation::RigGeometry* rig = dynamic_cast(&geom); - if (rig) + if (rig){ rig->setRigTransformImplementation(new MyRigTransformHardware); + osgAnimation::MorphGeometry *morph=dynamic_cast(rig->getSourceGeometry()); + if(morph)morph->setMorphTransformImplementation(new osgAnimation::MorphTransformHardware); + } } #if 0 From 186691a9db084ec971ca8b78872e1b12faf6c759 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 15:10:05 +0200 Subject: [PATCH 22/37] remove virtual qualifier for deprecated method --- include/osgAnimation/MorphGeometry | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index 9c87ac681..cf4b06228 100644 --- a/include/osgAnimation/MorphGeometry +++ b/include/osgAnimation/MorphGeometry @@ -144,7 +144,7 @@ namespace osgAnimation inline bool isDirty()const { return _dirty; } /** for retrocompatibility */ - virtual void transformSoftwareMethod(){(*_morphTransformImplementation.get())(*this);} + void transformSoftwareMethod(){(*_morphTransformImplementation.get())(*this);} protected: osg::ref_ptr _morphTransformImplementation; From ce6a316bde97e9fb84566a9e572d4768a036d8b0 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 17:24:35 +0200 Subject: [PATCH 23/37] cleanup --- include/osgAnimation/RigTransformSoftware | 22 +++++++----- src/osgAnimation/RigTransformSoftware.cpp | 43 +++-------------------- 2 files changed, 18 insertions(+), 47 deletions(-) diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index fa8aabcb9..1632eff96 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -40,17 +40,23 @@ namespace osgAnimation //to call when a skeleton is reacheable from the rig to prepare technic data virtual bool prepareData(RigGeometry&); - class BonePtrWeight: public BoneWeight + class BonePtrWeight: std::pair< osg::observer_ptr< Bone >, float> { public: - BonePtrWeight(const std::string& name, float weight, Bone *bptr=0) :BoneWeight(name,weight), _boneptr(bptr) {} - BonePtrWeight(const BonePtrWeight &bw2) : BoneWeight(bw2), _boneptr(bw2._boneptr) {} + BonePtrWeight(Bone*bone, float weight) :std::pair< osg::observer_ptr< Bone >, float>(bone,weight) {} + BonePtrWeight(const BonePtrWeight &bw2) : std::pair< osg::observer_ptr< Bone >, float>(bw2.first.get(),bw2.getWeight()) {} - const Bone * getBonePtr()const{return _boneptr.get();} - void setBonePtr(Bone*b){_boneptr=b;} - - protected: - osg::observer_ptr< Bone > _boneptr; + inline const Bone * getBonePtr() const {return first.get();} + inline void setBonePtr(Bone*b){first=b;} + inline const float & getWeight() const {return second;} + inline void setWeight(float b) {second=b;} + inline bool operator<(const BonePtrWeight &b1) const{ + if (getBonePtr() < b1.getBonePtr()) + return true; + else if (getBonePtr() > b1.getBonePtr()) + return false; + return (getWeight() < b1.getWeight()); + } }; typedef std::vector BonePtrWeightList; diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index ff241bc91..676cad8ea 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -36,43 +36,8 @@ 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; - return (b0.getWeight() < b1.getWeight()); - } -}; typedef std::vector BonePtrWeightList; -struct SortByBoneWeightList : public std::less -{ - bool operator()(const BonePtrWeightList& b0, - const BonePtrWeightList& 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 @@ -104,7 +69,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig const unsigned int &index = iw.getIndex(); float weight = iw.getWeight(); - _vertex2Bones[index].push_back(BonePtrWeight(inflist.getBoneName(), weight,bone)); + _vertex2Bones[index].push_back(BonePtrWeight(bone, weight)); } } @@ -132,15 +97,15 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig ///in order to minimize weighted matrices computation on update _uniqInfluenceSet2VertIDList.clear(); - typedef std::map UnifyBoneGroup; + typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; vertexID=0; ; for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) { - BonePtrWeightList bones = *it; + BonePtrWeightList &bones = *it; // sort the vector to have a consistent key - std::sort(bones.begin(), bones.end(), SortByNameAndWeight() ); + std::sort(bones.begin(), bones.end() ); // we use the vector as key to differentiate group UnifyBoneGroup::iterator result = unifyBuffer.find(bones); if (result != unifyBuffer.end()) From fae9729560193aa4b9c3e5b171e90bfa14bf68af Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 29 Aug 2017 17:32:19 +0200 Subject: [PATCH 24/37] swap priority in BonePtrWeight comparator< yeild the same VG set --- include/osgAnimation/RigTransformSoftware | 8 +++----- src/osgAnimation/RigTransformSoftware.cpp | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 1632eff96..2a9f28c86 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -51,11 +51,9 @@ namespace osgAnimation inline const float & getWeight() const {return second;} inline void setWeight(float b) {second=b;} inline bool operator<(const BonePtrWeight &b1) const{ - if (getBonePtr() < b1.getBonePtr()) - return true; - else if (getBonePtr() > b1.getBonePtr()) - return false; - return (getWeight() < b1.getWeight()); + if (second > b1.second)return true; + if (second < b1.second)return false; + return (first.get() > b1.first.get()); } }; typedef std::vector BonePtrWeightList; diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 676cad8ea..6e54b2cd6 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -120,7 +120,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig _uniqInfluenceSet2VertIDList.reserve(unifyBuffer.size()); for (UnifyBoneGroup::const_iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) _uniqInfluenceSet2VertIDList.push_back(it->second); - OSG_DEBUG << "uniq groups " << _uniqInfluenceSet2VertIDList.size() << " for " << rig.getName() << std::endl; + OSG_WARN << "uniq groups " << _uniqInfluenceSet2VertIDList.size() << " for " << rig.getName() << std::endl; } bool RigTransformSoftware::prepareData(RigGeometry&rig) { From fe99b568a0dc7dfdc3903a211ab636689fb88552 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 11:12:17 +0200 Subject: [PATCH 25/37] refactor: remove totally VertexInfluence (renamed BoneInfluenceList) everywhere --- .../osganimationskinning.cpp | 4 --- include/osgAnimation/VertexInfluence | 14 ++------ src/osgAnimation/RigTransformHardware.cpp | 25 ++++++--------- src/osgAnimation/RigTransformSoftware.cpp | 18 ++++++----- src/osgAnimation/VertexInfluence.cpp | 32 +++++++++---------- src/osgPlugins/gles/AABBonBoneVisitor.cpp | 2 +- .../gles/MostInfluencedGeometryByBone | 4 +-- .../osgAnimation/ReaderWriter.cpp | 13 ++++---- .../serializers/osgAnimation/RigGeometry.cpp | 13 ++++---- 9 files changed, 53 insertions(+), 72 deletions(-) diff --git a/examples/osganimationskinning/osganimationskinning.cpp b/examples/osganimationskinning/osganimationskinning.cpp index c28a2b15d..340868460 100644 --- a/examples/osganimationskinning/osganimationskinning.cpp +++ b/examples/osganimationskinning/osganimationskinning.cpp @@ -136,10 +136,6 @@ void initVertexMap(osgAnimation::Bone* b0, { osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap; - (*vim)[b0->getName()].setBoneName(b0->getName()); - (*vim)[b1->getName()].setBoneName(b1->getName()); - (*vim)[b2->getName()].setBoneName(b2->getName()); - for (int i = 0; i < (int)array->size(); i++) { float val = (*array)[i][0]; diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 4bb42b105..09bdf4c6b 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -46,25 +46,15 @@ namespace osgAnimation typedef std::vector BoneWeightList; typedef std::vector IndexList; - class OSGANIMATION_EXPORT BoneInfluenceList : public IndexWeightList - { - public: - const std::string& getBoneName() const { return _name;} - void setBoneName(const std::string& name) { _name = name;} - protected: - // the name is the bone to link to - std::string _name; - }; - - class VertexInfluenceMap : public std::map , public osg::Object + class VertexInfluenceMap : public std::map , public osg::Object { public: META_Object(osgAnimation, VertexInfluenceMap); VertexInfluenceMap() {} VertexInfluenceMap(const osgAnimation::VertexInfluenceMap& org, const osg::CopyOp& copyop): - std::map(org), + std::map(org), osg::Object(org, copyop) {} ///normalize per vertex weights given numvert of the attached mesh diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index b4640df4c..bc7fc16d7 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -280,8 +280,9 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { mapit != vertexInfluenceMap->end(); ++mapit) { - const BoneInfluenceList& boneinflist = mapit->second; - for(BoneInfluenceList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) + const IndexWeightList& boneinflist = mapit->second; + const std::string& bonename = mapit->first; + for(IndexWeightList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) { const IndexWeight& iw = *infit; const unsigned int &index = iw.getIndex(); @@ -289,30 +290,24 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { FloatInt &sum=sums[index]; - if (boneinflist.getBoneName().empty()) { - OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; - } - - //_vertex2Bones[index].push_back(VertexInfluenceSet::BoneWeight(vi.getName(), weight));; - if(fabs(weight) > 1e-4) // don't use bone with weight too small { - if ((boneName2PaletteIndex= _boneNameToPalette.find(boneinflist.getBoneName())) != _boneNameToPalette.end()) + if ((boneName2PaletteIndex= _boneNameToPalette.find(bonename)) != _boneNameToPalette.end()) { - boneNameCountMap[boneinflist.getBoneName()]++; + boneNameCountMap[bonename]++; vertexIndexWeight[index].push_back(IndexWeight(boneName2PaletteIndex->second,weight)); } else { BoneMap::const_iterator bonebyname; - if ((bonebyname=boneMap.find(boneinflist.getBoneName())) == boneMap.end()) + if ((bonebyname=boneMap.find(bonename)) == boneMap.end()) { - OSG_WARN << "RigTransformHardware::createPalette can't find bone " << boneinflist.getBoneName() << "in skeleton bonemap: skip this influence" << std::endl; + OSG_WARN << "RigTransformHardware::createPalette can't find bone " << bonename << "in skeleton bonemap: skip this influence" << std::endl; continue; } - boneNameCountMap[boneinflist.getBoneName()] = 1; // for stats + boneNameCountMap[bonename] = 1; // for stats - _boneNameToPalette[boneinflist.getBoneName()] = _bonePalette.size() ; + _boneNameToPalette[bonename] = _bonePalette.size() ; vertexIndexWeight[index].push_back(IndexWeight(_bonePalette.size(),weight)); _bonePalette.push_back(bonebyname->second); sum.first+=weight; @@ -321,7 +316,7 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { } else { - OSG_WARN << "RigTransformHardware::createPalette Bone " << boneinflist.getBoneName() << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; + OSG_WARN << "RigTransformHardware::createPalette Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; } maxBonePerVertex = osg::maximum(maxBonePerVertex, sum.second); diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 6e54b2cd6..c36b1aa5a 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -49,21 +49,23 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig it != _vertexInfluenceMap->end(); ++it) { - const BoneInfluenceList& inflist = it->second; - if (inflist.getBoneName().empty()) { - OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone BoneInfluenceList" << std::endl; + const IndexWeightList& inflist = it->second; + const std::string& bonename = it->first; + + if (bonename.empty()) { + OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; } - BoneMap::const_iterator bmit = boneMap.find(inflist.getBoneName()); + BoneMap::const_iterator bmit = boneMap.find(bonename); if (bmit == boneMap.end() ) { - if (_invalidInfluence.find(inflist.getBoneName()) != _invalidInfluence.end()) { - _invalidInfluence[inflist.getBoneName()] = true; - OSG_WARN << "RigTransformSoftware Bone " << inflist.getBoneName() << " not found, skip the influence group " << std::endl; + if (_invalidInfluence.find(bonename) != _invalidInfluence.end()) { + _invalidInfluence[bonename] = true; + OSG_WARN << "RigTransformSoftware Bone " << bonename << " not found, skip the influence group " << std::endl; } continue; } Bone* bone = bmit->second.get(); - for(BoneInfluenceList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) + for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) { const IndexWeight &iw = *infit; const unsigned int &index = iw.getIndex(); diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index dabaca32f..4dc433ff2 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -36,8 +36,8 @@ void VertexInfluenceMap::normalize(unsigned int numvert) { 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) { + IndexWeightList &curvecinf=mapit->second; + for(IndexWeightList::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); @@ -65,14 +65,16 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert 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) { + for(VertexInfluenceMap::iterator mapit=this->begin(); mapit!=this->end(); ++mapit) + { + const std::string& bonename=mapit->first; + IndexWeightList &curvecinf=mapit->second; + for(IndexWeightList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) { IndexWeight& inf=*curinf; - if( curvecinf.getBoneName().empty()) { + if( bonename.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)); + else if(inf.second>minweight)tempVec2Bones[inf.first].insert(BoneWeight(bonename, inf.second)); } } this->clear(); @@ -87,15 +89,13 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert 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()); + IndexWeightList & inf= (*this)[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()); + IndexWeightList & inf= (*this)[bwit->getBoneName()]; inf.push_back(IndexWeight(mapit->first,bwit->getWeight())); } @@ -110,17 +110,17 @@ void VertexInfluenceMap::computePerVertexInfluenceList(std::vectorsecond; - if (inflist.getBoneName().empty()) { - OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone BoneInfluenceList" << std::endl; + const IndexWeightList& inflist = it->second; + if (it->first.empty()) { + OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; } - for(BoneInfluenceList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) + for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) { const IndexWeight &iw = *infit; const unsigned int &index = iw.getIndex(); float weight = iw.getWeight(); - vertex2Bones[index].push_back(BoneWeight(inflist.getBoneName(), weight));; + vertex2Bones[index].push_back(BoneWeight(it->first, weight));; } } } diff --git a/src/osgPlugins/gles/AABBonBoneVisitor.cpp b/src/osgPlugins/gles/AABBonBoneVisitor.cpp index 5b3fc99dd..ec0bc7e46 100644 --- a/src/osgPlugins/gles/AABBonBoneVisitor.cpp +++ b/src/osgPlugins/gles/AABBonBoneVisitor.cpp @@ -51,7 +51,7 @@ void ComputeAABBOnBoneVisitor::computeBoundingBoxOnBones() { osg::Vec3Array *vertices = dynamic_cast(rigGeometry->getVertexArray()); if(!vertices) continue; - osgAnimation::BoneInfluenceList vxtInf = (*itMap).second; + osgAnimation::IndexWeightList vxtInf = (*itMap).second; //Expand the boundingBox with each vertex for(unsigned int j = 0; j < vxtInf.size(); j++) { diff --git a/src/osgPlugins/gles/MostInfluencedGeometryByBone b/src/osgPlugins/gles/MostInfluencedGeometryByBone index a5e8c5e97..000b9930f 100644 --- a/src/osgPlugins/gles/MostInfluencedGeometryByBone +++ b/src/osgPlugins/gles/MostInfluencedGeometryByBone @@ -200,9 +200,9 @@ protected: BoneNameBoneMap::iterator bone_it = boneMap.find(vertexInfluencePair->first); if(bone_it == boneMap.end()) continue; osg::ref_ptr bone = bone_it->second; - const osgAnimation::BoneInfluenceList& vertexInfluence = (*vertexInfluencePair).second; + const osgAnimation::IndexWeightList& vertexInfluence = (*vertexInfluencePair).second; - for(osgAnimation::BoneInfluenceList::const_iterator vertexIndexWeight = vertexInfluence.begin(); vertexIndexWeight != vertexInfluence.end(); ++vertexIndexWeight) { + for(osgAnimation::IndexWeightList::const_iterator vertexIndexWeight = vertexInfluence.begin(); vertexIndexWeight != vertexInfluence.end(); ++vertexIndexWeight) { rigGeometryInfluenceByBoneMap[bone.get()][*rigGeometry].addWeight((*vertexIndexWeight).second); } } diff --git a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp index b8813ae70..57796375b 100644 --- a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp @@ -804,17 +804,16 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr) for (int i = 0; i < nbGroups; i++) { int nbVertexes = 0; - std::string name; + std::string bonename; if (fr.matchSequence("osgAnimation::VertexInfluence %s %i {")) { - name = fr[1].getStr(); + bonename = fr[1].getStr(); fr[2].getInt(nbVertexes); fr += 4; iteratorAdvanced = true; } - osgAnimation::BoneInfluenceList vi; - vi.setBoneName(name); + osgAnimation::IndexWeightList vi; vi.reserve(nbVertexes); for (int j = 0; j < nbVertexes; j++) { @@ -833,7 +832,7 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr) { fr+=1; } - (*vmap)[name] = vi; + (*vmap)[bonename] = vi; } if (!vmap->empty()) geom.setInfluenceMap(vmap.get()); @@ -863,8 +862,8 @@ bool RigGeometry_writeLocalData(const Object& obj, Output& fw) name = "Empty"; fw.indent() << "osgAnimation::VertexInfluence \"" << name << "\" " << it->second.size() << " {" << std::endl; fw.moveIn(); - const osgAnimation::BoneInfluenceList& vi = it->second; - for (osgAnimation::BoneInfluenceList::const_iterator itv = vi.begin(); itv != vi.end(); itv++) + const osgAnimation::IndexWeightList& vi = it->second; + for (osgAnimation::IndexWeightList::const_iterator itv = vi.begin(); itv != vi.end(); itv++) { fw.indent() << itv->first << " " << itv->second << std::endl; } diff --git a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp index 0d88de08d..1403bd648 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp @@ -14,14 +14,13 @@ static bool readInfluenceMap( osgDB::InputStream& is, osgAnimation::RigGeometry& unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; for ( unsigned int i=0; i> is.PROPERTY("VertexInfluence"); - is.readWrappedString(name); + is.readWrappedString(bonename); viSize = is.readSize(); is >> is.BEGIN_BRACKET; - osgAnimation::BoneInfluenceList vi; - vi.setBoneName( name ); + osgAnimation::IndexWeightList vi; vi.reserve( viSize ); for ( unsigned int j=0; j> index >> weight; vi.push_back( osgAnimation::IndexWeight(index, weight) ); } - (*map)[name] = vi; + (*map)[bonename] = vi; is >> is.END_BRACKET; } is >> is.END_BRACKET; @@ -47,14 +46,14 @@ static bool writeInfluenceMap( osgDB::OutputStream& os, const osgAnimation::RigG itr!=map->end(); ++itr ) { std::string name = itr->first; - const osgAnimation::BoneInfluenceList& vi = itr->second; + const osgAnimation::IndexWeightList& vi = itr->second; if ( name.empty() ) name = "Empty"; os << os.PROPERTY("VertexInfluence"); os.writeWrappedString(name); os.writeSize(vi.size()) ; os << os.BEGIN_BRACKET << std::endl; - for ( osgAnimation::BoneInfluenceList::const_iterator vitr=vi.begin(); + for ( osgAnimation::IndexWeightList::const_iterator vitr=vi.begin(); vitr != vi.end(); ++vitr ) { os << vitr->first << vitr->second << std::endl; From 0ebf540d655dee3bc7121d837a4ff8aac90e213f Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 12:09:54 +0200 Subject: [PATCH 26/37] add and comment out normlization in rigtransformXXX --- src/osgAnimation/RigTransformHardware.cpp | 107 ++++++++++------------ src/osgAnimation/RigTransformSoftware.cpp | 4 +- 2 files changed, 50 insertions(+), 61 deletions(-) diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index bc7fc16d7..262d99c9a 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -257,7 +257,7 @@ void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightLis bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { _nbVertexes = rig.getVertexArray()->getNumElements(); - unsigned int maxBonePerVertex=0; + IndexWeightList::size_type maxBonePerVertex=0; typedef std::pair FloatInt; std::vector< FloatInt > sums;///stat totalweight nbref @@ -276,98 +276,87 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { VertexIndexWeightList vertexIndexWeight; vertexIndexWeight.resize(_nbVertexes); + unsigned int paletteindex; for (osgAnimation::VertexInfluenceMap::iterator mapit = vertexInfluenceMap->begin(); mapit != vertexInfluenceMap->end(); ++mapit) { const IndexWeightList& boneinflist = mapit->second; const std::string& bonename = mapit->first; + BoneMap::const_iterator bonebyname; + if ((bonebyname=boneMap.find(bonename)) == boneMap.end()) + { + OSG_WARN << "RigTransformHardware::buildPalette can't find bone " << bonename << "in skeleton bonemap: skip this influence" << std::endl; + continue; + } + if ((boneName2PaletteIndex= _boneNameToPalette.find(bonename)) != _boneNameToPalette.end()) + { + boneNameCountMap[bonename]++; + paletteindex= boneName2PaletteIndex->second ; + } + else + { + boneNameCountMap[bonename] = 1; // for stats + _boneNameToPalette[bonename] = _bonePalette.size() ; + paletteindex= _bonePalette.size() ; + _bonePalette.push_back(bonebyname->second); + + } for(IndexWeightList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) { const IndexWeight& iw = *infit; const unsigned int &index = iw.getIndex(); const float &weight = iw.getWeight(); - - FloatInt &sum=sums[index]; + IndexWeightList & iwlist=vertexIndexWeight[index]; if(fabs(weight) > 1e-4) // don't use bone with weight too small { - if ((boneName2PaletteIndex= _boneNameToPalette.find(bonename)) != _boneNameToPalette.end()) - { - boneNameCountMap[bonename]++; - vertexIndexWeight[index].push_back(IndexWeight(boneName2PaletteIndex->second,weight)); - } - else - { - BoneMap::const_iterator bonebyname; - if ((bonebyname=boneMap.find(bonename)) == boneMap.end()) - { - OSG_WARN << "RigTransformHardware::createPalette can't find bone " << bonename << "in skeleton bonemap: skip this influence" << std::endl; - continue; - } - boneNameCountMap[bonename] = 1; // for stats - - _boneNameToPalette[bonename] = _bonePalette.size() ; - vertexIndexWeight[index].push_back(IndexWeight(_bonePalette.size(),weight)); - _bonePalette.push_back(bonebyname->second); - sum.first+=weight; - ++sum.second; - } + iwlist.push_back(IndexWeight(paletteindex,weight)); } else { - OSG_WARN << "RigTransformHardware::createPalette Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; + OSG_WARN << "RigTransformHardware::buildPalette Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; } - maxBonePerVertex = osg::maximum(maxBonePerVertex, sum.second); + maxBonePerVertex = osg::maximum(maxBonePerVertex, iwlist.size()); } - OSG_INFO << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; - OSG_INFO << "RigTransformHardware::createPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; + OSG_INFO << "RigTransformHardware::buildPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; + OSG_INFO << "RigTransformHardware::buildPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it) { - OSG_INFO << "RigTransformHardware::createPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; + OSG_INFO << "RigTransformHardware::buildPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; } - OSG_INFO << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; + OSG_INFO << "RigTransformHardware::buildPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; } + ///normalize + /*unsigned int vertid=0; + for(VertexIndexWeightList::iterator it=vertexIndexWeight.begin();it!=vertexIndexWeight.end();++it,++vertid) + { + float sum=0; + for(IndexWeightList::iterator iwit=it->begin();iwit!=it->end();++iwit) + sum+=iwit->second; + + if(sum< 1e-4){ + OSG_WARN << "RigTransformHardware::buildPalette Warning: vertex with zero sum weights: " <begin();iwit!=it->end();++iwit) + iwit->second*=sum; + } + }*/ + _bonesPerVertex = maxBonePerVertex; _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); createVertexAttribList(*this,vertexIndexWeight,this->_boneWeightAttribArrays); - // normalize weight per vertex -///..assume not sum=0 - /* for(BoneWeightAttribList::iterator attribit=_boneWeightAttribArrays.begin();attribit!=_boneWeightAttribArrays.end();++attribit){ - std::vector< std::pair >::iterator countit=sums.begin(); - for(osg::Vec4Array::iterator vert=attribit->get()->begin();vert!=attribit->get()->end();++vert,++countit){ - osg::Vec4& v=*vert; - v[1]/=countit->first; - v[3]/=countit->first; - } - - } - */ - /* unsigned int vertexID=0; - for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) - { - BoneWeightList& bones = *it; - int size = bones.size(); - if (sums[vertexID].first < 1e-4) - { - OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " << it->first << " seems to have 0 weight, skip normalize for this vertex" << std::endl; - } - else - { - float mult = 1.0/sums[vertexID].first ; - for (int i = 0; i < size; i++) - bones[i].setWeight(bones[i].getWeight() * mult); - } - } - */ return true; } diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index c36b1aa5a..a2ef47abf 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -77,7 +77,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig // normalize _vertex2Bones weight per vertex unsigned vertexID=0; - for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) + /*for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) { BonePtrWeightList& bones = *it; float sum = 0; @@ -93,7 +93,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig for(BonePtrWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) bwit->setWeight(bwit->getWeight() * mult); } - } + }*/ ///2 Create inverse mapping Vec2Vec from previous built Index2Vec ///in order to minimize weighted matrices computation on update From 985d766f058114380d6ed5730e3419d19dc8af75 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 12:55:45 +0200 Subject: [PATCH 27/37] uncomment normalization in rigtransformxxx --- include/osgAnimation/MorphTransformHardware | 5 ----- src/osgAnimation/RigTransformSoftware.cpp | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/include/osgAnimation/MorphTransformHardware b/include/osgAnimation/MorphTransformHardware index 9b5e5239b..fde644a96 100644 --- a/include/osgAnimation/MorphTransformHardware +++ b/include/osgAnimation/MorphTransformHardware @@ -37,14 +37,9 @@ namespace osgAnimation META_Object(osgAnimation,MorphTransformHardware); - - - virtual void operator()(MorphGeometry&); void setShader(osg::Shader*); - - protected: bool init(MorphGeometry&); diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index a2ef47abf..c36b1aa5a 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -77,7 +77,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig // normalize _vertex2Bones weight per vertex unsigned vertexID=0; - /*for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) + for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) { BonePtrWeightList& bones = *it; float sum = 0; @@ -93,7 +93,7 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig for(BonePtrWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) bwit->setWeight(bwit->getWeight() * mult); } - }*/ + } ///2 Create inverse mapping Vec2Vec from previous built Index2Vec ///in order to minimize weighted matrices computation on update From fd9b8f103e543d31b4a0b757a4406c0979bc9ecc Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 13:21:32 +0200 Subject: [PATCH 28/37] cleanup --- include/osgAnimation/RigGeometry | 2 +- include/osgAnimation/RigTransformHardware | 28 +++---- include/osgAnimation/RigTransformSoftware | 6 +- src/osgAnimation/RigTransformHardware.cpp | 89 ++++++++--------------- src/osgAnimation/RigTransformSoftware.cpp | 43 ++++++----- 5 files changed, 67 insertions(+), 101 deletions(-) diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index e3b3c4a46..5319b4e0a 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index fd10eeec6..cbb825e16 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -38,36 +38,32 @@ namespace osgAnimation META_Object(osgAnimation,RigTransformHardware); - typedef osg::Matrix MatrixType; typedef std::vector > BoneWeightAttribList; typedef std::vector > BonePalette; typedef std::map BoneNamePaletteIndex; - typedef std::vector MatrixPalette; osg::Vec4Array* getVertexAttrib(unsigned int index); - unsigned int getNumVertexAttrib(); + unsigned int getNumVertexAttrib() const {return _boneWeightAttribArrays.size();} + + void setShader(osg::Shader* shader) { _shader = shader; } + osg::Shader* getShader() const { return _shader; } + + const unsigned int &getNumBonesPerVertex() const{ return _bonesPerVertex; } + const unsigned int &getNumVertexes() const { return _nbVertexes; } + + const BoneNamePaletteIndex& getBoneNameToPalette(){ return _boneNameToPalette; } + const BonePalette& getBonePalette() { return _bonePalette; } + osg::Uniform* getMatrixPaletteUniform() { return _uniformMatrixPalette; } - osg::Uniform* getMatrixPaletteUniform(); void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry); - unsigned int getNumBonesPerVertex() const; - unsigned int getNumVertexes() const; - virtual void operator()(RigGeometry&); virtual bool prepareData(RigGeometry& ); - void setShader(osg::Shader*); - - const BoneNamePaletteIndex& getBoneNameToPalette() { - return _boneNameToPalette; - } - protected: - osg::Uniform* createVertexUniform(); - unsigned int _bonesPerVertex; unsigned int _nbVertexes; @@ -79,7 +75,7 @@ namespace osgAnimation bool _needInit; - bool buildPalette(BoneMap&boneMap ,RigGeometry&rig); + bool buildPalette(const BoneMap& boneMap ,const RigGeometry& rig); }; } diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 2a9f28c86..ac97f527a 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -129,7 +129,7 @@ namespace osgAnimation inline 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(VertexGroupList::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) + for(VertexGroupList::iterator itvg=_uniqVertexGroupList.begin(); itvg!=_uniqVertexGroupList.end(); ++itvg) { VertexGroup& uniq = *itvg; uniq.computeMatrixForVertexSet(); @@ -148,7 +148,7 @@ namespace osgAnimation template inline void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { - for(VertexGroupList::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) + for(VertexGroupList::iterator itvg=_uniqVertexGroupList.begin(); itvg!=_uniqVertexGroupList.end(); ++itvg) { VertexGroup& uniq = *itvg; uniq.computeMatrixForVertexSet(); @@ -170,7 +170,7 @@ namespace osgAnimation typedef std::vector VertexGroupList; - VertexGroupList _uniqInfluenceSet2VertIDList; + VertexGroupList _uniqVertexGroupList; void buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ); }; diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index 262d99c9a..fb51cb177 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -48,17 +48,6 @@ osg::Vec4Array* RigTransformHardware::getVertexAttrib(unsigned int index) return _boneWeightAttribArrays[index].get(); } -unsigned int RigTransformHardware::getNumVertexAttrib() -{ - return _boneWeightAttribArrays.size(); -} - -osg::Uniform* RigTransformHardware::getMatrixPaletteUniform() -{ - return _uniformMatrixPalette.get(); -} - - void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry) { for (unsigned int i = 0; i < _bonePalette.size(); i++) @@ -74,11 +63,7 @@ void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transf } -unsigned int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;} -unsigned int RigTransformHardware::getNumVertexes() const { return _nbVertexes;} - -typedef std::vector > VertexIndexWeightList; -void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList&_vertexIndexMatrixWeightList,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); +void createVertexAttribList(RigTransformHardware& rig,const std::vector > &perVertexInfluences,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); // // create vertex attribute by 2 bones @@ -89,11 +74,15 @@ void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightLis // than the 4 bones using two vertex attributes // -void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList& _vertexIndexMatrixWeightList, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) +typedef std::vector > PerVertexInfList; +void createVertexAttribList(RigTransformHardware& rig, + const PerVertexInfList & perVertexInfluences, + RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) { unsigned int nbVertices= rig.getNumVertexes(); unsigned int maxbonepervertex=rig.getNumBonesPerVertex(); unsigned int nbArray = static_cast(ceilf( ((float)maxbonepervertex) * 0.5f)); + if (!nbArray) return ; @@ -105,7 +94,6 @@ void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightLis array->resize( nbVertices); for (unsigned int j = 0; j < nbVertices; j++) { - for (unsigned int b = 0; b < 2; b++) { // the granularity is 2 so if we have only one bone @@ -116,8 +104,8 @@ void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightLis (*array)[j][1 + boneIndexInVec4] = 0; if (boneIndexInList < maxbonepervertex) { - float boneIndex = static_cast(_vertexIndexMatrixWeightList[j][boneIndexInList].getIndex()); - float boneWeight = _vertexIndexMatrixWeightList[j][boneIndexInList].getWeight(); + float boneIndex = static_cast(perVertexInfluences[j][boneIndexInList].getIndex()); + float boneWeight = perVertexInfluences[j][boneIndexInList].getWeight(); // fill the vec4 (*array)[j][0 + boneIndexInVec4] = boneIndex; (*array)[j][1 + boneIndexInVec4] = boneWeight; @@ -125,19 +113,7 @@ void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightLis } } } - return ; -} - -osg::Uniform* RigTransformHardware::createVertexUniform() -{ - osg::Uniform* uniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); - return uniform; -} - - -void RigTransformHardware::setShader(osg::Shader* shader) -{ - _shader = shader; + return; } bool RigTransformHardware::prepareData(RigGeometry& rig) @@ -252,37 +228,32 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) _needInit = false; return true; } -void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList&_vertexIndexMatrixWeightList,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); -bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { - - _nbVertexes = rig.getVertexArray()->getNumElements(); - IndexWeightList::size_type maxBonePerVertex=0; - - typedef std::pair FloatInt; - std::vector< FloatInt > sums;///stat totalweight nbref - sums.resize(_nbVertexes); +bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry&rig) { typedef std::map BoneNameCountMap; + _nbVertexes = rig.getVertexArray()->getNumElements(); + _boneWeightAttribArrays.resize(0); _bonePalette.clear(); _boneNameToPalette.clear(); + + IndexWeightList::size_type maxBonePerVertex=0; BoneNameCountMap boneNameCountMap; - VertexInfluenceMap *vertexInfluenceMap=rig.getInfluenceMap(); + const VertexInfluenceMap &vertexInfluenceMap=*rig.getInfluenceMap(); BoneNamePaletteIndex::iterator boneName2PaletteIndex; - _boneWeightAttribArrays.resize(0); // init temp vertex attribute data - VertexIndexWeightList vertexIndexWeight; - vertexIndexWeight.resize(_nbVertexes); + std::vector > perVertexInfluences; + perVertexInfluences.resize(_nbVertexes); unsigned int paletteindex; - for (osgAnimation::VertexInfluenceMap::iterator mapit = vertexInfluenceMap->begin(); - mapit != vertexInfluenceMap->end(); - ++mapit) + for (osgAnimation::VertexInfluenceMap::const_iterator boneinflistit = vertexInfluenceMap.begin(); + boneinflistit != vertexInfluenceMap.end(); + ++boneinflistit) { - const IndexWeightList& boneinflist = mapit->second; - const std::string& bonename = mapit->first; + const IndexWeightList& boneinflist = boneinflistit->second; + const std::string& bonename = boneinflistit->first; BoneMap::const_iterator bonebyname; if ((bonebyname=boneMap.find(bonename)) == boneMap.end()) { @@ -307,7 +278,7 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { const IndexWeight& iw = *infit; const unsigned int &index = iw.getIndex(); const float &weight = iw.getWeight(); - IndexWeightList & iwlist=vertexIndexWeight[index]; + IndexWeightList & iwlist=perVertexInfluences[index]; if(fabs(weight) > 1e-4) // don't use bone with weight too small { @@ -315,7 +286,7 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { } else { - OSG_WARN << "RigTransformHardware::buildPalette Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; + OSG_INFO << "RigTransformHardware::buildPalette Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; } maxBonePerVertex = osg::maximum(maxBonePerVertex, iwlist.size()); @@ -334,11 +305,11 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { } ///normalize - /*unsigned int vertid=0; - for(VertexIndexWeightList::iterator it=vertexIndexWeight.begin();it!=vertexIndexWeight.end();++it,++vertid) + unsigned int vertid=0; + for(PerVertexInfList::iterator vertinfit=perVertexInfluences.begin(); vertinfit != perVertexInfluences.end(); ++vertinfit,++vertid) { float sum=0; - for(IndexWeightList::iterator iwit=it->begin();iwit!=it->end();++iwit) + for(IndexWeightList::iterator iwit = vertinfit->begin(); iwit != vertinfit->end(); ++iwit) sum+=iwit->second; if(sum< 1e-4){ @@ -347,15 +318,15 @@ bool RigTransformHardware::buildPalette(BoneMap&boneMap ,RigGeometry&rig) { else { sum=1.0f/sum; - for(IndexWeightList::iterator iwit=it->begin();iwit!=it->end();++iwit) + for(IndexWeightList::iterator iwit=vertinfit->begin();iwit!=vertinfit->end();++iwit) iwit->second*=sum; } - }*/ + } _bonesPerVertex = maxBonePerVertex; _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); - createVertexAttribList(*this,vertexIndexWeight,this->_boneWeightAttribArrays); + createVertexAttribList(*this,perVertexInfluences,this->_boneWeightAttribArrays); return true; } diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index c36b1aa5a..35bea4823 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -38,19 +38,19 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const typedef std::vector BonePtrWeightList; -void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ){ +void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const RigGeometry&rig ){ ///1 Create Index2Vec - std::vector _vertex2Bones; - _vertex2Bones.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements()); + const VertexInfluenceMap &vertexInfluenceMap=*rig.getInfluenceMap(); + std::vector perVertexInfluences; + perVertexInfluences.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements()); - const VertexInfluenceMap *_vertexInfluenceMap=rig.getInfluenceMap(); - for (osgAnimation::VertexInfluenceMap::const_iterator it = _vertexInfluenceMap->begin(); - it != _vertexInfluenceMap->end(); - ++it) + for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin(); + perBoneinfit != vertexInfluenceMap.end(); + ++perBoneinfit) { - const IndexWeightList& inflist = it->second; - const std::string& bonename = it->first; + const IndexWeightList& inflist = perBoneinfit->second; + const std::string& bonename = perBoneinfit->first; if (bonename.empty()) { OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; @@ -71,13 +71,13 @@ void RigTransformSoftware::buildMinimumUpdateSet(const BoneMap&boneMap,const Rig const unsigned int &index = iw.getIndex(); float weight = iw.getWeight(); - _vertex2Bones[index].push_back(BonePtrWeight(bone, weight)); + perVertexInfluences[index].push_back(BonePtrWeight(bone, weight)); } } // normalize _vertex2Bones weight per vertex unsigned vertexID=0; - for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it, ++vertexID) + for (std::vector::iterator it = perVertexInfluences.begin(); it != perVertexInfluences.end(); ++it, ++vertexID) { BonePtrWeightList& bones = *it; float sum = 0; @@ -97,32 +97,31 @@ 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(); + _uniqVertexGroupList.clear(); typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; vertexID=0; - ; - for (std::vector::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) + for (std::vector::iterator perVertinfit = perVertexInfluences.begin(); perVertinfit!=perVertexInfluences.end(); ++perVertinfit,++vertexID) { - BonePtrWeightList &bones = *it; + BonePtrWeightList &boneinfs = *perVertinfit; // sort the vector to have a consistent key - std::sort(bones.begin(), bones.end() ); + std::sort(boneinfs.begin(), boneinfs.end() ); // we use the vector as key to differentiate group - UnifyBoneGroup::iterator result = unifyBuffer.find(bones); + UnifyBoneGroup::iterator result = unifyBuffer.find(boneinfs); if (result != unifyBuffer.end()) result->second.getVertices().push_back(vertexID); else { - VertexGroup& vg = unifyBuffer[bones]; - vg.getBoneWeights() = bones; + VertexGroup& vg = unifyBuffer[boneinfs]; + vg.getBoneWeights() = boneinfs; vg.getVertices().push_back(vertexID); } } - _uniqInfluenceSet2VertIDList.reserve(unifyBuffer.size()); + _uniqVertexGroupList.reserve(unifyBuffer.size()); for (UnifyBoneGroup::const_iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) - _uniqInfluenceSet2VertIDList.push_back(it->second); - OSG_WARN << "uniq groups " << _uniqInfluenceSet2VertIDList.size() << " for " << rig.getName() << std::endl; + _uniqVertexGroupList.push_back(it->second); + OSG_INFO << "uniq groups " << _uniqVertexGroupList.size() << " for " << rig.getName() << std::endl; } bool RigTransformSoftware::prepareData(RigGeometry&rig) { From 6d1193ee70855467546a324d3f0d2f143815b5d6 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 14:59:31 +0200 Subject: [PATCH 29/37] readd buildVertexInfluenceSet for backward compat --- include/osgAnimation/RigGeometry | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index 5319b4e0a..805e9c779 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -78,6 +78,8 @@ namespace osgAnimation void update(); + void buildVertexInfluenceSet(){_rigTransformImplementation->prepareData(*this);} + const osg::Matrix& getMatrixFromSkeletonToGeometry() const; const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const; From 8fad310ce12cfb0a602e3c2ca129cfe6620e307d Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 15:13:54 +0200 Subject: [PATCH 30/37] readd VertexInfluence whenever it's bad named and kinda useless --- .../osganimationskinning/osganimationskinning.cpp | 4 +++- include/osgAnimation/VertexInfluence | 15 +++++++++++++-- src/osgAnimation/VertexInfluence.cpp | 6 ++++-- src/osgPlugins/gles/AABBonBoneVisitor.cpp | 2 +- src/osgPlugins/gles/MostInfluencedGeometryByBone | 4 ++-- .../osgAnimation/ReaderWriter.cpp | 13 +++++++------ .../serializers/osgAnimation/RigGeometry.cpp | 8 ++++---- 7 files changed, 34 insertions(+), 18 deletions(-) diff --git a/examples/osganimationskinning/osganimationskinning.cpp b/examples/osganimationskinning/osganimationskinning.cpp index 340868460..485276e03 100644 --- a/examples/osganimationskinning/osganimationskinning.cpp +++ b/examples/osganimationskinning/osganimationskinning.cpp @@ -135,7 +135,9 @@ void initVertexMap(osgAnimation::Bone* b0, osg::Vec3Array* array) { osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap; - + (*vim)[b0->getName()].setName(b0->getName()); + (*vim)[b1->getName()].setName(b1->getName()); + (*vim)[b2->getName()].setName(b2->getName()); for (int i = 0; i < (int)array->size(); i++) { float val = (*array)[i][0]; diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 09bdf4c6b..94c12b0e4 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -46,15 +46,26 @@ namespace osgAnimation typedef std::vector BoneWeightList; typedef std::vector IndexList; + //Bone influence list + class OSGANIMATION_EXPORT VertexInfluence : public IndexWeightList + { + public: + const std::string& getName() const { return _name;} + void setName(const std::string& name) { _name = name;} - class VertexInfluenceMap : public std::map , public osg::Object + protected: + // the name is the bone to link to + std::string _name; + }; + + class VertexInfluenceMap : public std::map , public osg::Object { public: META_Object(osgAnimation, VertexInfluenceMap); VertexInfluenceMap() {} VertexInfluenceMap(const osgAnimation::VertexInfluenceMap& org, const osg::CopyOp& copyop): - std::map(org), + std::map(org), osg::Object(org, copyop) {} ///normalize per vertex weights given numvert of the attached mesh diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 4dc433ff2..2fffc7559 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -89,14 +89,16 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert if(sum>1e-4){ sum=1.0f/sum; for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { - IndexWeightList & inf= (*this)[bwit->getBoneName()]; + VertexInfluence & inf= (*this)[bwit->getBoneName()]; inf.push_back(IndexWeight(mapit->first, bwit->getWeight()*sum)); + inf.setName(bwit->getBoneName()); } } }else{ for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { - IndexWeightList & inf= (*this)[bwit->getBoneName()]; + VertexInfluence & inf= (*this)[bwit->getBoneName()]; inf.push_back(IndexWeight(mapit->first,bwit->getWeight())); + inf.setName(bwit->getBoneName()); } } diff --git a/src/osgPlugins/gles/AABBonBoneVisitor.cpp b/src/osgPlugins/gles/AABBonBoneVisitor.cpp index ec0bc7e46..0ea5302f7 100644 --- a/src/osgPlugins/gles/AABBonBoneVisitor.cpp +++ b/src/osgPlugins/gles/AABBonBoneVisitor.cpp @@ -51,7 +51,7 @@ void ComputeAABBOnBoneVisitor::computeBoundingBoxOnBones() { osg::Vec3Array *vertices = dynamic_cast(rigGeometry->getVertexArray()); if(!vertices) continue; - osgAnimation::IndexWeightList vxtInf = (*itMap).second; + osgAnimation::VertexInfluence vxtInf = (*itMap).second; //Expand the boundingBox with each vertex for(unsigned int j = 0; j < vxtInf.size(); j++) { diff --git a/src/osgPlugins/gles/MostInfluencedGeometryByBone b/src/osgPlugins/gles/MostInfluencedGeometryByBone index 000b9930f..024d87ddb 100644 --- a/src/osgPlugins/gles/MostInfluencedGeometryByBone +++ b/src/osgPlugins/gles/MostInfluencedGeometryByBone @@ -200,9 +200,9 @@ protected: BoneNameBoneMap::iterator bone_it = boneMap.find(vertexInfluencePair->first); if(bone_it == boneMap.end()) continue; osg::ref_ptr bone = bone_it->second; - const osgAnimation::IndexWeightList& vertexInfluence = (*vertexInfluencePair).second; + const osgAnimation::VertexInfluence& vertexInfluence = (*vertexInfluencePair).second; - for(osgAnimation::IndexWeightList::const_iterator vertexIndexWeight = vertexInfluence.begin(); vertexIndexWeight != vertexInfluence.end(); ++vertexIndexWeight) { + for(osgAnimation::VertexInfluence::const_iterator vertexIndexWeight = vertexInfluence.begin(); vertexIndexWeight != vertexInfluence.end(); ++vertexIndexWeight) { rigGeometryInfluenceByBoneMap[bone.get()][*rigGeometry].addWeight((*vertexIndexWeight).second); } } diff --git a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp index 57796375b..4dbf949dc 100644 --- a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp @@ -804,16 +804,17 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr) for (int i = 0; i < nbGroups; i++) { int nbVertexes = 0; - std::string bonename; + std::string name; if (fr.matchSequence("osgAnimation::VertexInfluence %s %i {")) { - bonename = fr[1].getStr(); + name = fr[1].getStr(); fr[2].getInt(nbVertexes); fr += 4; iteratorAdvanced = true; } - osgAnimation::IndexWeightList vi; + osgAnimation::VertexInfluence vi; + vi.setName(name); vi.reserve(nbVertexes); for (int j = 0; j < nbVertexes; j++) { @@ -832,7 +833,7 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr) { fr+=1; } - (*vmap)[bonename] = vi; + (*vmap)[name] = vi; } if (!vmap->empty()) geom.setInfluenceMap(vmap.get()); @@ -862,8 +863,8 @@ bool RigGeometry_writeLocalData(const Object& obj, Output& fw) name = "Empty"; fw.indent() << "osgAnimation::VertexInfluence \"" << name << "\" " << it->second.size() << " {" << std::endl; fw.moveIn(); - const osgAnimation::IndexWeightList& vi = it->second; - for (osgAnimation::IndexWeightList::const_iterator itv = vi.begin(); itv != vi.end(); itv++) + const osgAnimation::VertexInfluence& vi = it->second; + for (osgAnimation::VertexInfluence::const_iterator itv = vi.begin(); itv != vi.end(); itv++) { fw.indent() << itv->first << " " << itv->second << std::endl; } diff --git a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp index 1403bd648..2ea4b9551 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp @@ -19,8 +19,8 @@ static bool readInfluenceMap( osgDB::InputStream& is, osgAnimation::RigGeometry& is >> is.PROPERTY("VertexInfluence"); is.readWrappedString(bonename); viSize = is.readSize(); is >> is.BEGIN_BRACKET; - - osgAnimation::IndexWeightList vi; + osgAnimation::VertexInfluence vi; + vi.setName( bonename ); vi.reserve( viSize ); for ( unsigned int j=0; jend(); ++itr ) { std::string name = itr->first; - const osgAnimation::IndexWeightList& vi = itr->second; + const osgAnimation::VertexInfluence& vi = itr->second; if ( name.empty() ) name = "Empty"; os << os.PROPERTY("VertexInfluence"); os.writeWrappedString(name); os.writeSize(vi.size()) ; os << os.BEGIN_BRACKET << std::endl; - for ( osgAnimation::IndexWeightList::const_iterator vitr=vi.begin(); + for ( osgAnimation::VertexInfluence::const_iterator vitr=vi.begin(); vitr != vi.end(); ++vitr ) { os << vitr->first << vitr->second << std::endl; From 705695b41da7c76db13f496c301b7135343856ba Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 15:46:19 +0200 Subject: [PATCH 31/37] add a guard (if dirty) on uniform update --- src/osgAnimation/MorphTransformHardware.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp index 8b5351cea..86df7b465 100644 --- a/src/osgAnimation/MorphTransformHardware.cpp +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -187,11 +187,14 @@ void MorphTransformHardware::operator()(MorphGeometry& geom) if (_needInit) if (!init(geom)) return; - - ///upload new morph weights each update via uniform - int curimorph=0; - MorphGeometry::MorphTargetList & morphlist=geom.getMorphTargetList(); - for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph) - _uniformTargetsWeight->setElement(curimorph++, curmorph->getWeight()); - _uniformTargetsWeight->dirty(); + if (geom.isDirty()) + { + ///upload new morph weights each update via uniform + int curimorph=0; + MorphGeometry::MorphTargetList & morphlist=geom.getMorphTargetList(); + for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph) + _uniformTargetsWeight->setElement(curimorph++, curmorph->getWeight()); + _uniformTargetsWeight->dirty(); + geom.dirty(false); + } } From 86ad54f67102e32b7d07213f8adeb3d1549d2dda Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 17:07:11 +0200 Subject: [PATCH 32/37] add parameter to XXXTranformHW to customize reserved texture attribs and vertex attribs --- include/osgAnimation/MorphTransformHardware | 9 ++++++++- include/osgAnimation/RigTransformHardware | 10 +++++++--- src/osgAnimation/MorphTransformHardware.cpp | 18 ++++++------------ src/osgAnimation/RigTransformHardware.cpp | 8 +++++--- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/include/osgAnimation/MorphTransformHardware b/include/osgAnimation/MorphTransformHardware index fde644a96..b061cccae 100644 --- a/include/osgAnimation/MorphTransformHardware +++ b/include/osgAnimation/MorphTransformHardware @@ -38,7 +38,13 @@ namespace osgAnimation META_Object(osgAnimation,MorphTransformHardware); virtual void operator()(MorphGeometry&); - void setShader(osg::Shader*); + + inline void setShader(osg::Shader*s){_shader=s;} + inline osg::Shader * getShader()const{return _shader;} + + ///texture unit reserved for morphtarget TBO default is 7 + void setReservedTextureUnit(unsigned int t){_reservedTextureUnit=t;} + unsigned int getReservedTextureUnit() const {return _reservedTextureUnit;} protected: @@ -49,6 +55,7 @@ namespace osgAnimation osg::ref_ptr _shader; bool _needInit; + unsigned int _reservedTextureUnit; }; } diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index cbb825e16..91c586d33 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -43,12 +43,16 @@ namespace osgAnimation typedef std::map BoneNamePaletteIndex; typedef std::vector MatrixPalette; - osg::Vec4Array* getVertexAttrib(unsigned int index); - unsigned int getNumVertexAttrib() const {return _boneWeightAttribArrays.size();} + ///set the first Vertex Attribute Array index of the rig generated by this technic (default:11) + void setFirstVertexAttributeTarget(unsigned int i){ _minAttribIndex=i;} + unsigned int getFirstVertexAttributeTarget()const { return _minAttribIndex;} void setShader(osg::Shader* shader) { _shader = shader; } osg::Shader* getShader() const { return _shader; } + osg::Vec4Array* getVertexAttrib(unsigned int index); + unsigned int getNumVertexAttrib() const {return _boneWeightAttribArrays.size();} + const unsigned int &getNumBonesPerVertex() const{ return _bonesPerVertex; } const unsigned int &getNumVertexes() const { return _nbVertexes; } @@ -74,7 +78,7 @@ namespace osgAnimation osg::ref_ptr _shader; bool _needInit; - + unsigned int _minAttribIndex; bool buildPalette(const BoneMap& boneMap ,const RigGeometry& rig); }; diff --git a/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp index 86df7b465..f0915bbf1 100644 --- a/src/osgAnimation/MorphTransformHardware.cpp +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -19,29 +19,23 @@ #include ///texture unit reserved for morphtarget TBO -#define MORPHTEXTUREUNIT 7 +#define DEFAULTMORPHTEXTUREUNIT 7 using namespace osgAnimation; -MorphTransformHardware::MorphTransformHardware() +MorphTransformHardware::MorphTransformHardware():_needInit(true),_reservedTextureUnit(DEFAULTMORPHTEXTUREUNIT) { - _needInit = true; - } MorphTransformHardware::MorphTransformHardware(const MorphTransformHardware& rth, const osg::CopyOp& copyop): MorphTransform(rth, copyop), _uniformTargetsWeight(rth._uniformTargetsWeight), _shader(rth._shader), - _needInit(rth._needInit) + _needInit(rth._needInit), + _reservedTextureUnit(rth._reservedTextureUnit) { } -void MorphTransformHardware::setShader(osg::Shader* shader) -{ - _shader = shader; -} - bool MorphTransformHardware::init(MorphGeometry& morphGeometry) { osg::Vec3Array* pos = dynamic_cast(morphGeometry.getVertexArray()); @@ -104,7 +98,7 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) //create TBO Texture handle osg::Uniform * morphTBOHandle=new osg::Uniform(osg::Uniform::SAMPLER_BUFFER,"morphTargets"); - morphTBOHandle->set(MORPHTEXTUREUNIT); + morphTBOHandle->set(_reservedTextureUnit); //create dynamic uniform for morphtargets animation weights _uniformTargetsWeight=new osg::Uniform(osg::Uniform::FLOAT,"morphWeights",morphlist.size()); @@ -174,7 +168,7 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) osg::ref_ptr ss = morphGeometry.getOrCreateStateSet(); ss->addUniform(_uniformTargetsWeight); - ss->setTextureAttribute(MORPHTEXTUREUNIT,morphTargetsTBO); + ss->setTextureAttribute(_reservedTextureUnit,morphTargetsTBO); ss->addUniform( morphTBOHandle); ss->addUniform(new osg::Uniform("nbMorphVertex", morphGeometry.getVertexArray()->getNumElements())); diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index fb51cb177..ae2e0dfa6 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -20,12 +20,13 @@ using namespace osgAnimation; - +#define DEFAULT_FIRST_VERTATTRIB_TARGETTED 11 RigTransformHardware::RigTransformHardware() { _needInit = true; _bonesPerVertex = 0; _nbVertexes = 0; + _minAttribIndex = DEFAULT_FIRST_VERTATTRIB_TARGETTED; } RigTransformHardware::RigTransformHardware(const RigTransformHardware& rth, const osg::CopyOp& copyop): @@ -37,7 +38,8 @@ RigTransformHardware::RigTransformHardware(const RigTransformHardware& rth, cons _boneWeightAttribArrays(rth._boneWeightAttribArrays), _uniformMatrixPalette(rth._uniformMatrixPalette), _shader(rth._shader), - _needInit(rth._needInit) + _needInit(rth._needInit), + _minAttribIndex(rth._minAttribIndex) { } @@ -198,7 +200,7 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) OSG_INFO << "Shader " << str << std::endl; } - unsigned int attribIndex = 11; + unsigned int attribIndex = _minAttribIndex; unsigned int nbAttribs = getNumVertexAttrib(); if(nbAttribs==0) OSG_WARN << "nbAttribs== " << nbAttribs << std::endl; From 1f628235d469eea1c6613cc2e4011857490b2f12 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 20:36:34 +0200 Subject: [PATCH 33/37] rehabilit an init method to ensure morphing po setted before skinning po in case of rigeom source that are morphgeom --- include/osgAnimation/RigTransformHardware | 2 + src/osgAnimation/RigTransformHardware.cpp | 159 ++++++++++++---------- 2 files changed, 86 insertions(+), 75 deletions(-) diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index 91c586d33..9e2cb23f1 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -81,6 +81,8 @@ namespace osgAnimation unsigned int _minAttribIndex; bool buildPalette(const BoneMap& boneMap ,const RigGeometry& rig); + bool init(RigGeometry& ); + }; } diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index ae2e0dfa6..ef690d5fb 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -152,82 +152,8 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) // copy shallow from source geometry to rig rig.copyFrom(source); - osg::ref_ptr program ; - osg::ref_ptr vertexshader; - osg::ref_ptr stateset = rig.getOrCreateStateSet(); - - //grab geom source program and vertex shader if _shader is not setted - if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM))) - { - for(unsigned int i=0; igetNumShaders(); ++i) - if(program->getShader(i)->getType()==osg::Shader::VERTEX) { - vertexshader=program->getShader(i); - program->removeShader(vertexshader); - - } - } else { - program = new osg::Program; - program->setName("HardwareSkinning"); - } - //set default source if _shader is not user setted - if (!vertexshader.valid()) { - if (!_shader.valid()) - vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); - else vertexshader=_shader; - } - if (!vertexshader.valid()) { - OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; - return false; - } - - // replace max matrix by the value from uniform - { - std::string str = vertexshader->getShaderSource(); - std::string toreplace = std::string("MAX_MATRIX"); - std::size_t start = str.find(toreplace); - if (std::string::npos != start) { - std::stringstream ss; - ss << getMatrixPaletteUniform()->getNumElements(); - str.replace(start, toreplace.size(), ss.str()); - vertexshader->setShaderSource(str); - } - else - { - OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl; - } - OSG_INFO << "Shader " << str << std::endl; - } - - unsigned int attribIndex = _minAttribIndex; - unsigned int nbAttribs = getNumVertexAttrib(); - if(nbAttribs==0) - OSG_WARN << "nbAttribs== " << nbAttribs << std::endl; - for (unsigned int i = 0; i < nbAttribs; i++) - { - std::stringstream ss; - ss << "boneWeight" << i; - program->addBindAttribLocation(ss.str(), attribIndex + i); - - if(getVertexAttrib(i)->getNumElements()!=_nbVertexes) - OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; - rig.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); - OSG_INFO << "set vertex attrib " << ss.str() << std::endl; - } - - - program->addShader(vertexshader.get()); - stateset->removeUniform("nbBonesPerVertex"); - stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); - stateset->removeUniform("matrixPalette"); - stateset->addUniform(getMatrixPaletteUniform()); - - stateset->removeAttribute(osg::StateAttribute::PROGRAM); - if(!stateset->getAttribute(osg::StateAttribute::PROGRAM)) - stateset->setAttributeAndModes(program.get()); - - _needInit = false; return true; } @@ -333,10 +259,93 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry return true; } +bool RigTransformHardware::init(RigGeometry& rig){ + if(_uniformMatrixPalette.valid()){ + ///data seams prepared + osg::ref_ptr program ; + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = rig.getOrCreateStateSet(); + + //grab geom source program and vertex shader if _shader is not setted + if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM))) + { + for(unsigned int i=0; igetNumShaders(); ++i) + if(program->getShader(i)->getType()==osg::Shader::VERTEX) { + vertexshader=program->getShader(i); + program->removeShader(vertexshader); + + } + } else { + program = new osg::Program; + program->setName("HardwareSkinning"); + } + //set default source if _shader is not user setted + if (!vertexshader.valid()) { + if (!_shader.valid()) + vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); + else vertexshader=_shader; + } + + + if (!vertexshader.valid()) { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + + // replace max matrix by the value from uniform + { + std::string str = vertexshader->getShaderSource(); + std::string toreplace = std::string("MAX_MATRIX"); + std::size_t start = str.find(toreplace); + if (std::string::npos != start) { + std::stringstream ss; + ss << getMatrixPaletteUniform()->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); + } + else + { + OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; + } + + unsigned int attribIndex = _minAttribIndex; + unsigned int nbAttribs = getNumVertexAttrib(); + if(nbAttribs==0) + OSG_WARN << "nbAttribs== " << nbAttribs << std::endl; + for (unsigned int i = 0; i < nbAttribs; i++) + { + std::stringstream ss; + ss << "boneWeight" << i; + program->addBindAttribLocation(ss.str(), attribIndex + i); + + if(getVertexAttrib(i)->getNumElements()!=_nbVertexes) + OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; + rig.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + OSG_INFO << "set vertex attrib " << ss.str() << std::endl; + } + + + program->addShader(vertexshader.get()); + stateset->removeUniform("nbBonesPerVertex"); + stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); + stateset->removeUniform("matrixPalette"); + stateset->addUniform(getMatrixPaletteUniform()); + + stateset->removeAttribute(osg::StateAttribute::PROGRAM); + if(!stateset->getAttribute(osg::StateAttribute::PROGRAM)) + stateset->setAttributeAndModes(program.get()); + _needInit = false; + return false; + } + else prepareData(rig); + return false; +} void RigTransformHardware::operator()(RigGeometry& geom) { if (_needInit) - if (!prepareData(geom)) + if (!init(geom)) return; computeMatrixPaletteUniform(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry()); } From f4675a56482eeea6d9663adbf3b711c354be86fb Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 30 Aug 2017 23:01:21 +0200 Subject: [PATCH 34/37] I found the damn bug in RigTransformHW --- src/osgAnimation/RigTransformHardware.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index ef690d5fb..f2fac8c43 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -104,7 +104,7 @@ void createVertexAttribList(RigTransformHardware& rig, unsigned int boneIndexInVec4 = b*2; (*array)[j][0 + boneIndexInVec4] = 0; (*array)[j][1 + boneIndexInVec4] = 0; - if (boneIndexInList < maxbonepervertex) + if (boneIndexInList < perVertexInfluences[j].size()) { float boneIndex = static_cast(perVertexInfluences[j][boneIndexInList].getIndex()); float boneWeight = perVertexInfluences[j][boneIndexInList].getWeight(); @@ -214,7 +214,7 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry } else { - OSG_INFO << "RigTransformHardware::buildPalette Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; + OSG_WARN << "RigTransformHardware::buildPalette Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; } maxBonePerVertex = osg::maximum(maxBonePerVertex, iwlist.size()); From 0926bb783d208bf84b1a8130d620dd2d39cc65d8 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Thu, 31 Aug 2017 13:29:42 +0200 Subject: [PATCH 35/37] fix example --- examples/osganimationhardware/osganimationhardware.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp index 4c65644a8..acc2bf2f8 100644 --- a/examples/osganimationhardware/osganimationhardware.cpp +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -42,12 +42,12 @@ static unsigned int getRandomValueinRange(unsigned int v) } -osg::ref_ptr program; +//osg::ref_ptr program; // show how to override the default RigTransformHardware for customized usage struct MyRigTransformHardware : public osgAnimation::RigTransformHardware { - virtual bool prepareData(osgAnimation::RigGeometry& rig) + virtual bool init(osgAnimation::RigGeometry& rig) { if(!rig.getSkeleton() && !rig.getParents().empty()) { @@ -81,7 +81,7 @@ struct MyRigTransformHardware : public osgAnimation::RigTransformHardware // copy shallow from source geometry to rig rig.copyFrom(source); - // osg::ref_ptr program ; + osg::ref_ptr program ; osg::ref_ptr vertexshader; osg::ref_ptr stateset = rig.getOrCreateStateSet(); From 068a032dacfbfb7b1157f7504f5db0a9da4d72c3 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Thu, 31 Aug 2017 13:30:24 +0200 Subject: [PATCH 36/37] revert s/VertexIndexWeight/IndexWeight/ --- .../osganimationskinning.cpp | 6 +++--- include/osgAnimation/RigTransformHardware | 2 +- include/osgAnimation/VertexInfluence | 6 +++--- src/osgAnimation/RigTransformHardware.cpp | 10 +++++----- src/osgAnimation/RigTransformSoftware.cpp | 2 +- src/osgAnimation/VertexInfluence.cpp | 18 +++++++----------- .../osgAnimation/ReaderWriter.cpp | 2 +- .../serializers/osgAnimation/RigGeometry.cpp | 2 +- 8 files changed, 22 insertions(+), 26 deletions(-) diff --git a/examples/osganimationskinning/osganimationskinning.cpp b/examples/osganimationskinning/osganimationskinning.cpp index 485276e03..2536353a6 100644 --- a/examples/osganimationskinning/osganimationskinning.cpp +++ b/examples/osganimationskinning/osganimationskinning.cpp @@ -143,11 +143,11 @@ void initVertexMap(osgAnimation::Bone* b0, float val = (*array)[i][0]; std::cout << val << std::endl; if (val >= -1.0f && val <= 0.0f) - (*vim)[b0->getName()].push_back(osgAnimation::IndexWeight(i,1.0f)); + (*vim)[b0->getName()].push_back(osgAnimation::VertexIndexWeight(i,1.0f)); else if ( val > 0.0f && val <= 1.0f) - (*vim)[b1->getName()].push_back(osgAnimation::IndexWeight(i,1.0f)); + (*vim)[b1->getName()].push_back(osgAnimation::VertexIndexWeight(i,1.0f)); else if ( val > 1.0f) - (*vim)[b2->getName()].push_back(osgAnimation::IndexWeight(i,1.0f)); + (*vim)[b2->getName()].push_back(osgAnimation::VertexIndexWeight(i,1.0f)); } geom->setInfluenceMap(vim); diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index 9e2cb23f1..eeefa0030 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -81,7 +81,7 @@ namespace osgAnimation unsigned int _minAttribIndex; bool buildPalette(const BoneMap& boneMap ,const RigGeometry& rig); - bool init(RigGeometry& ); + virtual bool init(RigGeometry& ); }; } diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 94c12b0e4..a521f13d7 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -34,15 +34,15 @@ namespace osgAnimation inline void setWeight(float i){second=i;} }; // first is vertex index, and second the weight - struct IndexWeight: public std::pair + struct VertexIndexWeight: public std::pair { - IndexWeight( unsigned int f = 0xffffffff,float s = 0.0f): std::pair(f,s){} + VertexIndexWeight( unsigned int f = 0xffffffff,float s = 0.0f): std::pair(f,s){} inline const unsigned int& getIndex()const{return first;} inline void setIndex(unsigned int i){first=i;} inline const float &getWeight()const{return second;} inline void setWeight(float i){second=i;} }; - typedef std::vector IndexWeightList; + typedef std::vector IndexWeightList; typedef std::vector BoneWeightList; typedef std::vector IndexList; diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index f2fac8c43..8713b5cef 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -65,7 +65,7 @@ void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transf } -void createVertexAttribList(RigTransformHardware& rig,const std::vector > &perVertexInfluences,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); +void createVertexAttribList(RigTransformHardware& rig,const std::vector > &perVertexInfluences,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); // // create vertex attribute by 2 bones @@ -76,7 +76,7 @@ void createVertexAttribList(RigTransformHardware& rig,const std::vector > PerVertexInfList; +typedef std::vector > PerVertexInfList; void createVertexAttribList(RigTransformHardware& rig, const PerVertexInfList & perVertexInfluences, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) @@ -172,7 +172,7 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry BoneNamePaletteIndex::iterator boneName2PaletteIndex; // init temp vertex attribute data - std::vector > perVertexInfluences; + std::vector perVertexInfluences; perVertexInfluences.resize(_nbVertexes); unsigned int paletteindex; @@ -203,14 +203,14 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry } for(IndexWeightList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) { - const IndexWeight& iw = *infit; + const VertexIndexWeight& iw = *infit; const unsigned int &index = iw.getIndex(); const float &weight = iw.getWeight(); IndexWeightList & iwlist=perVertexInfluences[index]; if(fabs(weight) > 1e-4) // don't use bone with weight too small { - iwlist.push_back(IndexWeight(paletteindex,weight)); + iwlist.push_back(VertexIndexWeight(paletteindex,weight)); } else { diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 35bea4823..3e858647a 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -67,7 +67,7 @@ void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const R Bone* bone = bmit->second.get(); for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) { - const IndexWeight &iw = *infit; + const VertexIndexWeight &iw = *infit; const unsigned int &index = iw.getIndex(); float weight = iw.getWeight(); diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 2fffc7559..d0bba7599 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -38,7 +38,7 @@ void VertexInfluenceMap::normalize(unsigned int numvert) { for(VertexInfluenceMap::iterator mapit=this->begin(); mapit!=this->end(); ++mapit) { IndexWeightList &curvecinf=mapit->second; for(IndexWeightList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) { - IndexWeight& inf=*curinf; + VertexIndexWeight& inf=*curinf; localstore[inf.first].first+=inf.second; localstore[inf.first].second.push_back(&inf.second); @@ -70,7 +70,7 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert const std::string& bonename=mapit->first; IndexWeightList &curvecinf=mapit->second; for(IndexWeightList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) { - IndexWeight& inf=*curinf; + VertexIndexWeight& inf=*curinf; if( bonename.empty()) { OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << inf.first << " is not assigned to a bone" << std::endl; } @@ -90,14 +90,14 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert sum=1.0f/sum; for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { VertexInfluence & inf= (*this)[bwit->getBoneName()]; - inf.push_back(IndexWeight(mapit->first, bwit->getWeight()*sum)); + inf.push_back(VertexIndexWeight(mapit->first, bwit->getWeight()*sum)); inf.setName(bwit->getBoneName()); } } }else{ for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { VertexInfluence & inf= (*this)[bwit->getBoneName()]; - inf.push_back(IndexWeight(mapit->first,bwit->getWeight())); + inf.push_back(VertexIndexWeight(mapit->first,bwit->getWeight())); inf.setName(bwit->getBoneName()); } @@ -114,14 +114,13 @@ void VertexInfluenceMap::computePerVertexInfluenceList(std::vectorsecond; if (it->first.empty()) { - OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; + OSG_WARN << "VertexInfluenceMap::computePerVertexInfluenceList contains unamed bone IndexWeightList" << std::endl; } for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) { - const IndexWeight &iw = *infit; + const VertexIndexWeight &iw = *infit; const unsigned int &index = iw.getIndex(); float weight = iw.getWeight(); - vertex2Bones[index].push_back(BoneWeight(it->first, weight));; } } @@ -173,12 +172,9 @@ void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& unsigned int vertexID=0; for (std::vector::iterator it = vertex2Bones.begin(); it != vertex2Bones.end(); ++it,++vertexID) { - BoneWeightList &boneweightlist = *it;//->second; - //int vertexIndex = it->first; - + BoneWeightList &boneweightlist = *it; // sort the vector to have a consistent key std::sort(boneweightlist.begin(), boneweightlist.end(), SortByNameAndWeight()); - // we use the vector as key to differentiate group UnifyBoneGroup::iterator result = unifyBuffer.find(boneweightlist); if (result == unifyBuffer.end()) diff --git a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp index 4dbf949dc..add7f50fd 100644 --- a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp @@ -827,7 +827,7 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr) fr += 2; iteratorAdvanced = true; } - vi.push_back(osgAnimation::IndexWeight(index, weight)); + vi.push_back(osgAnimation::VertexIndexWeight(index, weight)); } if (fr.matchSequence("}")) { diff --git a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp index 2ea4b9551..10b14d0f1 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp @@ -27,7 +27,7 @@ static bool readInfluenceMap( osgDB::InputStream& is, osgAnimation::RigGeometry& int index = 0; float weight = 0.0f; is >> index >> weight; - vi.push_back( osgAnimation::IndexWeight(index, weight) ); + vi.push_back( osgAnimation::VertexIndexWeight(index, weight) ); } (*map)[bonename] = vi; is >> is.END_BRACKET; From b790986f3739db204dfdc1326ce426f34f6b0cc5 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Thu, 31 Aug 2017 13:49:27 +0200 Subject: [PATCH 37/37] few cleanup --- include/osgAnimation/RigTransformHardware | 3 +++ src/osgAnimation/RigTransformHardware.cpp | 26 +++++++++++------------ src/osgAnimation/RigTransformSoftware.cpp | 1 - 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index eeefa0030..5469fb299 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -62,8 +62,10 @@ namespace osgAnimation void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry); + // update rig if needed virtual void operator()(RigGeometry&); + // init animations data virtual bool prepareData(RigGeometry& ); protected: @@ -81,6 +83,7 @@ namespace osgAnimation unsigned int _minAttribIndex; bool buildPalette(const BoneMap& boneMap ,const RigGeometry& rig); + //on first update virtual bool init(RigGeometry& ); }; diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index 8713b5cef..85a32bdaa 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -21,13 +21,12 @@ using namespace osgAnimation; #define DEFAULT_FIRST_VERTATTRIB_TARGETTED 11 -RigTransformHardware::RigTransformHardware() -{ - _needInit = true; - _bonesPerVertex = 0; - _nbVertexes = 0; - _minAttribIndex = DEFAULT_FIRST_VERTATTRIB_TARGETTED; -} +RigTransformHardware::RigTransformHardware(): + _bonesPerVertex (0), + _nbVertexes (0), + _needInit (true), + _minAttribIndex(DEFAULT_FIRST_VERTATTRIB_TARGETTED) + {} RigTransformHardware::RigTransformHardware(const RigTransformHardware& rth, const osg::CopyOp& copyop): RigTransform(rth, copyop), @@ -152,8 +151,6 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) // copy shallow from source geometry to rig rig.copyFrom(source); - - return true; } @@ -229,7 +226,6 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry OSG_INFO << "RigTransformHardware::buildPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; - } ///normalize @@ -251,16 +247,17 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry } } - _bonesPerVertex = maxBonePerVertex; _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); + _bonesPerVertex = maxBonePerVertex; + createVertexAttribList(*this,perVertexInfluences,this->_boneWeightAttribArrays); return true; } bool RigTransformHardware::init(RigGeometry& rig){ - if(_uniformMatrixPalette.valid()){ + if(_bonesPerVertex>0){ ///data seams prepared osg::ref_ptr program ; osg::ref_ptr vertexshader; @@ -328,14 +325,17 @@ bool RigTransformHardware::init(RigGeometry& rig){ program->addShader(vertexshader.get()); + stateset->removeUniform("nbBonesPerVertex"); stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); + stateset->removeUniform("matrixPalette"); - stateset->addUniform(getMatrixPaletteUniform()); + stateset->addUniform(_uniformMatrixPalette); stateset->removeAttribute(osg::StateAttribute::PROGRAM); if(!stateset->getAttribute(osg::StateAttribute::PROGRAM)) stateset->setAttributeAndModes(program.get()); + _needInit = false; return false; } diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 3e858647a..403033da3 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -70,7 +70,6 @@ void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const R const VertexIndexWeight &iw = *infit; const unsigned int &index = iw.getIndex(); float weight = iw.getWeight(); - perVertexInfluences[index].push_back(BonePtrWeight(bone, weight)); } }