From 32aaeccee1e1b50928dc1d9afaf8457262e12333 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Sat, 26 Aug 2017 20:37:10 +0200 Subject: [PATCH 01/80] refactoring and fixes only change in design: decouplage between MorphGeometry and MorphTransform technique no real change in behavior (i hope) --- include/osgAnimation/AnimationManagerBase | 10 + include/osgAnimation/MorphGeometry | 58 ++++-- include/osgAnimation/MorphTransformSoftware | 45 +++++ include/osgAnimation/RigGeometry | 28 +-- include/osgAnimation/RigTransform | 17 ++ include/osgAnimation/RigTransformHardware | 37 ++-- include/osgAnimation/RigTransformSoftware | 52 +++-- include/osgAnimation/VertexInfluence | 33 ++-- src/osgAnimation/AnimationManagerBase.cpp | 5 +- src/osgAnimation/CMakeLists.txt | 2 + src/osgAnimation/MorphGeometry.cpp | 151 +------------- src/osgAnimation/MorphTransformSoftware.cpp | 182 +++++++++++++++++ src/osgAnimation/RigGeometry.cpp | 57 +++--- src/osgAnimation/RigTransformHardware.cpp | 205 ++++++++++++-------- src/osgAnimation/RigTransformSoftware.cpp | 150 ++++++++------ src/osgAnimation/VertexInfluence.cpp | 33 ++-- 16 files changed, 643 insertions(+), 422 deletions(-) create mode 100644 include/osgAnimation/MorphTransformSoftware create mode 100644 src/osgAnimation/MorphTransformSoftware.cpp diff --git a/include/osgAnimation/AnimationManagerBase b/include/osgAnimation/AnimationManagerBase index bdc0c5c89..15b4617ab 100644 --- a/include/osgAnimation/AnimationManagerBase +++ b/include/osgAnimation/AnimationManagerBase @@ -42,6 +42,16 @@ namespace osgAnimation const AnimationList& getAnimationList() const { return _animations;} AnimationList& getAnimationList() { return _animations;} + //uniformisation of the API + inline Animation * getRegisteredAnimation(unsigned int i){return _animations[i].get();} + inline unsigned int getNumRegisteredAnimations()const{return _animations.size();} + inline void addRegisteredAnimation(Animation* animation){ + _needToLink = true; + _animations.push_back(animation); + buildTargetReference(); + } + void removeRegisteredAnimation(Animation* animation); + /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index 1a242efd7..e8c89d22d 100644 --- a/include/osgAnimation/MorphGeometry +++ b/include/osgAnimation/MorphGeometry @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -59,7 +60,10 @@ namespace osgAnimation virtual const char* libraryName() const { return "osgAnimation"; } virtual const char* className() const { return "MorphGeometry"; } - virtual void transformSoftwareMethod(); + // set implementation of rig method + void setMorphTransformImplementation(MorphTransform*); + MorphTransform* getMorphTransformImplementation(); + const MorphTransform* getMorphTransformImplementation() const { return _rigTransformImplementation.get(); } /** Set the morphing method. */ void setMethod(Method method) { _method = method; } @@ -71,6 +75,30 @@ namespace osgAnimation /** Get the flag for morphing normals. */ inline bool getMorphNormals() const { return _morphNormals; } + /** Get the list of MorphTargets.*/ + 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; } + + /** Return the \c MorphTarget at position \c i.*/ + inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; } + + /** Return the \c MorphTarget at position \c i.*/ + inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; } + + /** Set source of vertices for this morph geometry */ + inline void setVertexSource(osg::Vec3Array *v){ _positionSource=v;} + + /** Get source of vertices for this morph geometry */ + inline osg::Vec3Array * getVertexSource()const{return _positionSource;} + + /** Set source of normals for this morph geometry */ + inline void setNormalSource(osg::Vec3Array *n){ _normalSource=n;} + + /** Get source of normals for this morph geometry */ + inline osg::Vec3Array * getNormalSource()const{return _normalSource;} + /** Add a \c MorphTarget to the \c MorphGeometry. * If \c MorphTarget is not \c NULL and is not contained in the \c MorphGeometry * then increment its reference count, add it to the MorphTargets list and @@ -101,6 +129,7 @@ namespace osgAnimation } + /** update a morph target at index setting its current weight to morphWeight */ void setWeight(unsigned int index, float morphWeight) { if (index < _morphTargets.size()) @@ -111,29 +140,20 @@ namespace osgAnimation } /** Set the MorphGeometry dirty.*/ - void dirty() { _dirty = true; } + inline void dirty(bool b=true) { _dirty = b; } + inline bool isDirty()const { return _dirty; } - /** Get the list of MorphTargets.*/ - 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; } - - /** Return the \c MorphTarget at position \c i.*/ - inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; } - - /** Return the \c MorphTarget at position \c i.*/ - inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; } protected: + osg::ref_ptr _rigTransformImplementation; /// Do we need to recalculate the morphed geometry? bool _dirty; Method _method; MorphTargetList _morphTargets; - std::vector _positionSource; - std::vector _normalSource; + osg::ref_ptr _positionSource; + osg::ref_ptr _normalSource; /// Do we also morph between normals? bool _morphNormals; @@ -195,7 +215,13 @@ namespace osgAnimation if (!geom) return; - geom->transformSoftwareMethod(); + if (!geom->getMorphTransformImplementation()) + { + geom->setMorphTransformImplementation( new MorphTransformSoftware); + } + + MorphTransform& implementation = *geom->getMorphTransformImplementation(); + (implementation)(*geom); } }; diff --git a/include/osgAnimation/MorphTransformSoftware b/include/osgAnimation/MorphTransformSoftware new file mode 100644 index 000000000..8ac451b38 --- /dev/null +++ b/include/osgAnimation/MorphTransformSoftware @@ -0,0 +1,45 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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 + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. + */ + +#ifndef OSGANIMATION_MORPHTRANSFORM_SOFTWARE +#define OSGANIMATION_MORPHTRANSFORM_SOFTWARE 1 + +#include +#include +#include +#include + +namespace osgAnimation +{ + + class MorphGeometry; + + /// This class manage format for software morphing + class OSGANIMATION_EXPORT MorphTransformSoftware : public MorphTransform + { + public: + MorphTransformSoftware():_needInit(true){} + MorphTransformSoftware(const MorphTransformSoftware& rts,const osg::CopyOp& copyop): MorphTransform(rts, copyop), _needInit(true){} + + META_Object(osgAnimation,MorphTransformSoftware) + + bool init(MorphGeometry&); + virtual void operator()(MorphGeometry&); + protected: + bool _needInit; + + }; +} + +#endif diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index 74a5cf00f..31cda0179 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -57,14 +57,14 @@ namespace osgAnimation META_Object(osgAnimation, RigGeometry); - void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } - const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();} - VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();} + inline void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } + inline const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();} + inline VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();} - const Skeleton* getSkeleton() const; - Skeleton* getSkeleton(); + inline const Skeleton* getSkeleton() const { return _root.get(); } + inline Skeleton* getSkeleton() { return _root.get(); } // will be used by the update callback to init correctly the rig mesh - void setSkeleton(Skeleton*); + inline void setSkeleton(Skeleton* root){ _root = root;} void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;} bool getNeedToComputeMatrix() const { return _needToComputeMatrix;} @@ -72,25 +72,25 @@ namespace osgAnimation // this build the internal database about vertex influence and bones void buildVertexInfluenceSet(); - const VertexInfluenceSet& getVertexInfluenceSet() const; + inline const VertexInfluenceSet& getVertexInfluenceSet() const { return _vertexInfluenceSet;} void computeMatrixFromRootSkeleton(); // set implementation of rig method - void setRigTransformImplementation(RigTransform*); - RigTransform* getRigTransformImplementation(); - const RigTransform* getRigTransformImplementation() const { return _rigTransformImplementation.get(); } + inline RigTransform* getRigTransformImplementation() { return _rigTransformImplementation.get(); } + inline void setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; } + inline const RigTransform* getRigTransformImplementation() const { return _rigTransformImplementation.get(); } - virtual void drawImplementation(osg::RenderInfo& renderInfo) const; void update(); const osg::Matrix& getMatrixFromSkeletonToGeometry() const; const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const; - osg::Geometry* getSourceGeometry(); - const osg::Geometry* getSourceGeometry() const; - void setSourceGeometry(osg::Geometry* geometry); + + inline osg::Geometry* getSourceGeometry() { return _geometry.get(); } + inline const osg::Geometry* getSourceGeometry() const { return _geometry.get(); } + inline void setSourceGeometry(osg::Geometry* geometry) { _geometry = geometry; } void copyFrom(osg::Geometry& from); diff --git a/include/osgAnimation/RigTransform b/include/osgAnimation/RigTransform index 66ae0a219..184cdae0c 100644 --- a/include/osgAnimation/RigTransform +++ b/include/osgAnimation/RigTransform @@ -37,6 +37,23 @@ namespace osgAnimation virtual ~RigTransform() {} }; + class MorphGeometry; + + class MorphTransform : public osg::Object + { + public: + MorphTransform() {} + MorphTransform(const MorphTransform& org, const osg::CopyOp& copyop): + osg::Object(org, copyop) {} + + META_Object(osgAnimation,MorphTransform) + + virtual void operator()(MorphGeometry&) {} + + protected: + virtual ~MorphTransform() {} + + }; } diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index ce9006ddd..28330e87e 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -38,37 +38,36 @@ namespace osgAnimation META_Object(osgAnimation,RigTransformHardware); typedef osg::Matrix MatrixType; - typedef osgAnimation::Bone BoneType; typedef std::vector > BoneWeightAttribList; - typedef std::vector > BonePalette; - typedef std::map BoneNamePaletteIndex; + typedef std::vector > BonePalette; + typedef std::map BoneNamePaletteIndex; typedef std::vector MatrixPalette; struct IndexWeightEntry { - int _boneIndex; + 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 > VertexIndexWeightList; - - osg::Vec4Array* getVertexAttrib(int index); - int getNumVertexAttrib(); + osg::Vec4Array* getVertexAttrib(unsigned int index); + unsigned int getNumVertexAttrib(); osg::Uniform* getMatrixPaletteUniform(); void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry); - int getNumBonesPerVertex() const; - int getNumVertexes() const; + unsigned int getNumBonesPerVertex() const; + unsigned int getNumVertexes() const; - bool createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap); + bool createPalette(unsigned int nbVertexes,const BoneMap& boneMap, const VertexInfluenceSet::VertIDToBoneWeightList& vertexIndexToBoneWeightMap); virtual void operator()(RigGeometry&); + void setShader(osg::Shader*); const BoneNamePaletteIndex& getBoneNameToPalette() { @@ -78,13 +77,11 @@ namespace osgAnimation protected: bool init(RigGeometry&); + osg::Uniform* createVertexUniform(); - BoneWeightAttribList createVertexAttribList(); - osg::Uniform* createVertexUniform(); + unsigned int _bonesPerVertex; + unsigned int _nbVertexes; - int _bonesPerVertex; - int _nbVertexes; - VertexIndexWeightList _vertexIndexMatrixWeightList; BonePalette _bonePalette; BoneNamePaletteIndex _boneNameToPalette; BoneWeightAttribList _boneWeightAttribArrays; diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 300e513fd..8492a215d 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -37,10 +37,10 @@ namespace osgAnimation virtual void operator()(RigGeometry&); - class BoneWeight + class BonePtrWeight { public: - BoneWeight(Bone* bone, float weight) : _bone(bone), _weight(weight) {} + 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; } @@ -49,13 +49,13 @@ namespace osgAnimation float _weight; }; - typedef std::vector BoneWeightList; - typedef std::vector VertexList; + typedef std::vector BonePtrWeightList; + typedef std::vector VertexList; - class UniqBoneSetVertexSet + class VertexGroup { public: - BoneWeightList& getBones() { return _bones; } + BonePtrWeightList& getBoneWeights() { return _boneweights; } VertexList& getVertexes() { return _vertexes; } void resetMatrix() @@ -88,18 +88,17 @@ namespace osgAnimation } void computeMatrixForVertexSet() { - if (_bones.empty()) + if (_boneweights.empty()) { - osg::notify(osg::WARN) << this << " RigTransformSoftware::UniqBoneSetVertexSet no bones found" << std::endl; + osg::notify(osg::WARN) << this << " RigTransformSoftware::VertexGroup no bones found" << std::endl; _result = osg::Matrix::identity(); return; } resetMatrix(); - int size = _bones.size(); - for (int i = 0; i < size; i++) + for(BonePtrWeightList::iterator bwit=_boneweights.begin();bwit!=_boneweights.end();++bwit ) { - const Bone* bone = _bones[i].getBone(); + const Bone* bone = bwit->getBone(); if (!bone) { osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl; @@ -107,13 +106,13 @@ namespace osgAnimation } const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); const osg::Matrix& matrix = bone->getMatrixInSkeletonSpace(); - osg::Matrix::value_type w = _bones[i].getWeight(); + osg::Matrix::value_type w = bwit->getWeight(); accummulateMatrix(invBindMatrix, matrix, w); } } const osg::Matrix& getMatrix() const { return _result;} protected: - BoneWeightList _bones; + BonePtrWeightList _boneweights; VertexList _vertexes; osg::Matrix _result; }; @@ -123,39 +122,34 @@ 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 - int size = _boneSetVertexSet.size(); - for (int i = 0; i < size; i++) + for(std::vector::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) { - UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i]; + VertexGroup& uniq = *itvg; uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; const VertexList& vertexes = uniq.getVertexes(); - int vertexSize = vertexes.size(); - for (int j = 0; j < vertexSize; j++) + for(VertexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) { - int idx = vertexes[j]; - dst[idx] = src[idx] * matrix; + dst[*vertIDit] = src[*vertIDit] * matrix; } + } } template void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { - int size = _boneSetVertexSet.size(); - for (int i = 0; i < size; i++) + for(std::vector::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg) { - UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i]; + VertexGroup& uniq = *itvg; uniq.computeMatrixForVertexSet(); osg::Matrix matrix = transform * uniq.getMatrix() * invTransform; const VertexList& vertexes = uniq.getVertexes(); - int vertexSize = vertexes.size(); - for (int j = 0; j < vertexSize; j++) + for(VertexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit) { - int idx = vertexes[j]; - dst[idx] = osg::Matrix::transform3x3(src[idx],matrix); + dst[*vertIDit] = osg::Matrix::transform3x3(src[*vertIDit],matrix); } } } @@ -163,8 +157,8 @@ namespace osgAnimation protected: bool init(RigGeometry&); - void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence); - std::vector _boneSetVertexSet; + void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexGroupList& influence); + std::vector _uniqInfluenceSet2VertIDList; bool _needInit; diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 47941a43f..345b25db4 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -25,7 +25,7 @@ namespace osgAnimation { // first is vertex index, and second the weight, the - typedef std::pair VertexIndexWeight; + typedef std::pair VertexIndexWeight; typedef std::vector VertexList; class OSGANIMATION_EXPORT VertexInfluence : public VertexList { @@ -62,43 +62,48 @@ namespace osgAnimation { 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::map VertexIndexToBoneWeightMap; + typedef std::vector VertIDToBoneWeightList; - class UniqVertexSetToBoneSet + class VertexGroup { public: + // set Influences of the VertexGroup void setBones(BoneWeightList& bones) { _bones = bones;} const BoneWeightList& getBones() const { return _bones;} - std::vector& getVertexes() { return _vertexes;} - const std::vector& getVertexes() const { return _vertexes;} + // set Vertex Indices of the VertexGroup + std::vector& getVertexes() { return _vertexes;} + const std::vector& getVertexes() const { return _vertexes;} protected: - std::vector _vertexes; + std::vector _vertexes; BoneWeightList _bones; // here we could limit matrix operation by caching (weight * matrix) }; - typedef std::vector UniqVertexSetToBoneSetList; - - const UniqVertexSetToBoneSetList& getUniqVertexSetToBoneSetList() const { return _uniqVertexSetToBoneSet;} + 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 VertexInfluence& v); - void buildVertex2BoneList(); - void buildUniqVertexSetToBoneSetList(); + void buildVertex2BoneList(unsigned int numvertices); void clear(); - const VertexIndexToBoneWeightMap& getVertexToBoneList() const; + const VertIDToBoneWeightList& getVertexToBoneList() const; protected: BoneToVertexList _bone2Vertexes; - VertexIndexToBoneWeightMap _vertex2Bones; - UniqVertexSetToBoneSetList _uniqVertexSetToBoneSet; + VertIDToBoneWeightList _vertex2Bones; + UniqVertexGroupList _uniqVertexSetToBoneSet; }; } diff --git a/src/osgAnimation/AnimationManagerBase.cpp b/src/osgAnimation/AnimationManagerBase.cpp index 1c47851a7..d5a95b421 100644 --- a/src/osgAnimation/AnimationManagerBase.cpp +++ b/src/osgAnimation/AnimationManagerBase.cpp @@ -101,7 +101,10 @@ void AnimationManagerBase::registerAnimation (Animation* animation) buildTargetReference(); } -void AnimationManagerBase::unregisterAnimation (Animation* animation) +void AnimationManagerBase::removeRegisteredAnimation(Animation* animation){ + unregisterAnimation(animation); +} +void AnimationManagerBase::unregisterAnimation(Animation* animation) { AnimationList::iterator it = std::find(_animations.begin(), _animations.end(), animation); if (it != _animations.end()) diff --git a/src/osgAnimation/CMakeLists.txt b/src/osgAnimation/CMakeLists.txt index b0e920544..dc199ef9c 100644 --- a/src/osgAnimation/CMakeLists.txt +++ b/src/osgAnimation/CMakeLists.txt @@ -34,6 +34,7 @@ SET(TARGET_H ${HEADER_PATH}/RigTransform ${HEADER_PATH}/RigTransformHardware ${HEADER_PATH}/RigTransformSoftware + ${HEADER_PATH}/MorphTransformSoftware ${HEADER_PATH}/Sampler ${HEADER_PATH}/Skeleton ${HEADER_PATH}/StackedMatrixElement @@ -75,6 +76,7 @@ SET(TARGET_SRC RigGeometry.cpp RigTransformHardware.cpp RigTransformSoftware.cpp + MorphTransformSoftware.cpp Skeleton.cpp StackedMatrixElement.cpp StackedQuaternionElement.cpp diff --git a/src/osgAnimation/MorphGeometry.cpp b/src/osgAnimation/MorphGeometry.cpp index 9735c06f9..f52c04c3a 100644 --- a/src/osgAnimation/MorphGeometry.cpp +++ b/src/osgAnimation/MorphGeometry.cpp @@ -23,23 +23,23 @@ using namespace osgAnimation; MorphGeometry::MorphGeometry() : _dirty(false), _method(NORMALIZED), + _positionSource(0),_normalSource(0), _morphNormals(true) { setUseDisplayList(false); setUpdateCallback(new UpdateMorphGeometry); - setDataVariance(osg::Object::DYNAMIC); setUseVertexBufferObjects(true); } -MorphGeometry::MorphGeometry(const osg::Geometry& b) : - osg::Geometry(b, osg::CopyOp::DEEP_COPY_ARRAYS), +MorphGeometry::MorphGeometry(const osg::Geometry& g) : + osg::Geometry(g, osg::CopyOp::DEEP_COPY_ARRAYS), _dirty(false), _method(NORMALIZED), + _positionSource(0),_normalSource(0), _morphNormals(true) { setUseDisplayList(false); setUpdateCallback(new UpdateMorphGeometry); - setDataVariance(osg::Object::DYNAMIC); setUseVertexBufferObjects(true); } @@ -56,151 +56,14 @@ MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop) setUseVertexBufferObjects(true); } - -void MorphGeometry::transformSoftwareMethod() -{ - if (_dirty) - { - // See if we have an internal optimized geometry - osg::Geometry* morphGeometry = this; - - osg::Vec3Array* pos = dynamic_cast(morphGeometry->getVertexArray()); - - if(pos) - { - if ( _positionSource.size() != pos->size()) - { - _positionSource = std::vector(pos->begin(),pos->end()); - pos->setDataVariance(osg::Object::DYNAMIC); - } - - osg::Vec3Array* normal = dynamic_cast(morphGeometry->getNormalArray()); - bool normalmorphable = _morphNormals && normal; - if (normal && _normalSource.size() != normal->size()) - { - _normalSource = std::vector(normal->begin(),normal->end()); - normal->setDataVariance(osg::Object::DYNAMIC); - } - - - if (!_positionSource.empty()) - { - bool initialized = false; - if (_method == NORMALIZED) - { - // base * 1 - (sum of weights) + sum of (weight * target) - float baseWeight = 0; - for (unsigned int i=0; i < _morphTargets.size(); i++) - { - baseWeight += _morphTargets[i].getWeight(); - } - baseWeight = 1 - baseWeight; - - if (baseWeight != 0) - { - initialized = true; - for (unsigned int i=0; i < pos->size(); i++) - { - (*pos)[i] = _positionSource[i] * baseWeight; - } - if (normalmorphable) - { - for (unsigned int i=0; i < normal->size(); i++) - { - (*normal)[i] = _normalSource[i] * baseWeight; - } - } - } - } - else //if (_method == RELATIVE) - { - // base + sum of (weight * target) - initialized = true; - for (unsigned int i=0; i < pos->size(); i++) - { - (*pos)[i] = _positionSource[i]; - } - if (normalmorphable) - { - for (unsigned int i=0; i < normal->size(); i++) - { - (*normal)[i] = _normalSource[i]; - } - } - } - - for (unsigned int i=0; i < _morphTargets.size(); i++) - { - if (_morphTargets[i].getWeight() > 0) - { - // See if any the targets use the internal optimized geometry - osg::Geometry* targetGeometry = _morphTargets[i].getGeometry(); - - osg::Vec3Array* targetPos = dynamic_cast(targetGeometry->getVertexArray()); - osg::Vec3Array* targetNormals = dynamic_cast(targetGeometry->getNormalArray()); - normalmorphable = normalmorphable && targetNormals; - if(targetPos) - { - if (initialized) - { - // If vertices are initialized, add the morphtargets - for (unsigned int j=0; j < pos->size(); j++) - { - (*pos)[j] += (*targetPos)[j] * _morphTargets[i].getWeight(); - } - - if (normalmorphable) - { - for (unsigned int j=0; j < normal->size(); j++) - { - (*normal)[j] += (*targetNormals)[j] * _morphTargets[i].getWeight(); - } - } - } - else - { - // If not initialized, initialize with this morph target - initialized = true; - for (unsigned int j=0; j < pos->size(); j++) - { - (*pos)[j] = (*targetPos)[j] * _morphTargets[i].getWeight(); - } - - if (normalmorphable) - { - for (unsigned int j=0; j < normal->size(); j++) - { - (*normal)[j] = (*targetNormals)[j] * _morphTargets[i].getWeight(); - } - } - } - } - } - } - - pos->dirty(); - if (normalmorphable) - { - for (unsigned int j=0; j < normal->size(); j++) - { - (*normal)[j].normalize(); - } - normal->dirty(); - } - } - - dirtyBound(); - - } - _dirty = false; - } -} +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), AnimationUpdateCallback(apc, copyop) -{ +{_targetNames=apc._targetNames; } UpdateMorph::UpdateMorph(const std::string& name) : AnimationUpdateCallback(name) diff --git a/src/osgAnimation/MorphTransformSoftware.cpp b/src/osgAnimation/MorphTransformSoftware.cpp new file mode 100644 index 000000000..7080d8a4d --- /dev/null +++ b/src/osgAnimation/MorphTransformSoftware.cpp @@ -0,0 +1,182 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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 + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. + */ + + +#include +#include +#include +#include + +using namespace osgAnimation; + + +bool MorphTransformSoftware::init(MorphGeometry& morphGeometry){ + + + morphGeometry.setDataVariance(osg::Object::DYNAMIC); + osg::Vec3Array* pos = dynamic_cast(morphGeometry.getVertexArray()); + osg::Vec3Array * vertexSource = (morphGeometry.getVertexSource()); + osg::Vec3Array * normalSource = (morphGeometry.getNormalSource()); + + // See if we have an internal optimized geometry + + if(pos) + { + if (!vertexSource|| vertexSource->size() != pos->size()) + { + morphGeometry.setVertexSource(new osg::Vec3Array(pos->begin(),pos->end())); + pos->setDataVariance(osg::Object::DYNAMIC); + } + + osg::Vec3Array* normal = dynamic_cast(morphGeometry.getNormalArray()); + bool normalmorphable = morphGeometry.getMorphNormals() && normal; + morphGeometry.setMorphNormals(normalmorphable); + if (normalmorphable && (!normalSource || normalSource->size() != normal->size())) + { + morphGeometry.setNormalSource(new osg::Vec3Array(normal->begin(),normal->end())); + normal->setDataVariance(osg::Object::DYNAMIC); + } + }else return false; + + _needInit=false; + return true; +} + +void MorphTransformSoftware::operator()(MorphGeometry& morphGeometry) +{ + if (_needInit) + if (!init(morphGeometry)) + return; + if (morphGeometry.isDirty()) + { + osg::Vec3Array* pos = static_cast(morphGeometry.getVertexArray()); + osg::Vec3Array & vertexSource = *(morphGeometry.getVertexSource()); + osg::Vec3Array& normalSource = *(morphGeometry.getNormalSource()); + osg::Vec3Array* normal = static_cast(morphGeometry.getNormalArray()); + bool normalmorphable = morphGeometry.getMorphNormals() && normal; + + + if (!vertexSource.empty()) + { + bool initialized = false; + if (morphGeometry.getMethod() == MorphGeometry::NORMALIZED) + { + // base * 1 - (sum of weights) + sum of (weight * target) + float baseWeight = 0; + for (unsigned int i=0; i < morphGeometry.getMorphTargetList().size(); i++) + { + baseWeight += morphGeometry.getMorphTarget(i).getWeight(); + } + baseWeight = 1 - baseWeight; + + if (baseWeight != 0) + { + initialized = true; + for (unsigned int i=0; i < pos->size(); i++) + { + (*pos)[i] = vertexSource[i] * baseWeight; + } + if (normalmorphable) + { + for (unsigned int i=0; i < normal->size(); i++) + { + (*normal)[i] = normalSource[i] * baseWeight; + } + } + } + } + else //if (_method == RELATIVE) + { + // base + sum of (weight * target) + initialized = true; + for (unsigned int i=0; i < pos->size(); i++) + { + (*pos)[i] = vertexSource[i]; + } + if (normalmorphable) + { + for (unsigned int i=0; i < normal->size(); i++) + { + (*normal)[i] = normalSource[i]; + } + } + } + + for (unsigned int i=0; i < morphGeometry.getMorphTargetList().size(); i++) + { + if (morphGeometry.getMorphTarget(i).getWeight() > 0) + { + // See if any the targets use the internal optimized geometry + osg::Geometry* targetGeometry = morphGeometry.getMorphTarget(i).getGeometry(); + + osg::Vec3Array* targetPos = dynamic_cast(targetGeometry->getVertexArray()); + osg::Vec3Array* targetNormals = dynamic_cast(targetGeometry->getNormalArray()); + normalmorphable = normalmorphable && targetNormals; + if(targetPos) + { + if (initialized) + { + // If vertices are initialized, add the morphtargets + for (unsigned int j=0; j < pos->size(); j++) + { + (*pos)[j] += (*targetPos)[j] * morphGeometry.getMorphTarget(i).getWeight(); + } + + if (normalmorphable) + { + for (unsigned int j=0; j < normal->size(); j++) + { + (*normal)[j] += (*targetNormals)[j] * morphGeometry.getMorphTarget(i).getWeight(); + } + } + } + else + { + // If not initialized, initialize with this morph target + initialized = true; + for (unsigned int j=0; j < pos->size(); j++) + { + (*pos)[j] = (*targetPos)[j] * morphGeometry.getMorphTarget(i).getWeight(); + } + + if (normalmorphable) + { + for (unsigned int j=0; j < normal->size(); j++) + { + (*normal)[j] = (*targetNormals)[j] * morphGeometry.getMorphTarget(i).getWeight(); + } + } + } + } + } + } + + pos->dirty(); + if (normalmorphable) + { + for (unsigned int j=0; j < normal->size(); j++) + { + (*normal)[j].normalize(); + } + normal->dirty(); + } + } + + morphGeometry.dirtyBound(); + + + morphGeometry.dirty(false); + } + +} diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index 938629a97..b09c61966 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -58,7 +58,7 @@ RigGeometry::RigGeometry() _needToComputeMatrix = true; _matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity(); // disable the computation of boundingbox for the rig mesh - setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback); + setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback()); } @@ -69,9 +69,12 @@ RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) : _vertexInfluenceSet(b._vertexInfluenceSet), _vertexInfluenceMap(b._vertexInfluenceMap), _needToComputeMatrix(b._needToComputeMatrix) -{ +{ + _needToComputeMatrix = true; + _matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity(); // disable the computation of boundingbox for the rig mesh - setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback); + + setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback()); // we don't copy the RigImplementation yet. because the RigImplementation need to be initialized in a valid graph, with a skeleton ... // don't know yet what to do with a clone of a RigGeometry @@ -81,12 +84,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::drawImplementation(osg::RenderInfo& renderInfo) const -{ - osg::Geometry::drawImplementation(renderInfo); -} - void RigGeometry::buildVertexInfluenceSet() { if (!_vertexInfluenceMap.valid()) @@ -97,12 +94,12 @@ void RigGeometry::buildVertexInfluenceSet() _vertexInfluenceSet.clear(); for (osgAnimation::VertexInfluenceMap::iterator it = _vertexInfluenceMap->begin(); it != _vertexInfluenceMap->end(); - ++it) + ++it){ _vertexInfluenceSet.addVertexInfluence(it->second); - - _vertexInfluenceSet.buildVertex2BoneList(); - _vertexInfluenceSet.buildUniqVertexSetToBoneSetList(); - OSG_DEBUG << "uniq groups " << _vertexInfluenceSet.getUniqVertexSetToBoneSetList().size() << " for " << getName() << std::endl; + } + _vertexInfluenceSet.buildVertex2BoneList(getSourceGeometry()->getVertexArray()->getNumElements()); + _vertexInfluenceSet.buildUniqVertexGroupList(); + OSG_DEBUG << "uniq groups " << _vertexInfluenceSet.getUniqVertexGroupList().size() << " for " << getName() << std::endl; } void RigGeometry::computeMatrixFromRootSkeleton() @@ -116,7 +113,7 @@ void RigGeometry::computeMatrixFromRootSkeleton() osg::Matrix notRoot = _root->getMatrix(); _matrixFromSkeletonToGeometry = mtxList[0] * osg::Matrix::inverse(notRoot); _invMatrixFromSkeletonToGeometry = osg::Matrix::inverse(_matrixFromSkeletonToGeometry); - _needToComputeMatrix = false; + _needToComputeMatrix = false; } void RigGeometry::update() @@ -132,45 +129,45 @@ void RigGeometry::update() void RigGeometry::copyFrom(osg::Geometry& from) { - bool copyToSelf = (this==&from); + if (this==&from) return; osg::Geometry& target = *this; - if (!copyToSelf) target.setStateSet(from.getStateSet()); + target.setStateSet(from.getStateSet()); // copy over primitive sets. - if (!copyToSelf) target.getPrimitiveSetList() = from.getPrimitiveSetList(); + target.getPrimitiveSetList() = from.getPrimitiveSetList(); if (from.getVertexArray()) { - if (!copyToSelf) target.setVertexArray(from.getVertexArray()); + target.setVertexArray(from.getVertexArray()); } if (from.getNormalArray()) { - if (!copyToSelf) target.setNormalArray(from.getNormalArray()); + target.setNormalArray(from.getNormalArray()); } if (from.getColorArray()) { - if (!copyToSelf) target.setColorArray(from.getColorArray()); + target.setColorArray(from.getColorArray()); } if (from.getSecondaryColorArray()) { - if (!copyToSelf) target.setSecondaryColorArray(from.getSecondaryColorArray()); + target.setSecondaryColorArray(from.getSecondaryColorArray()); } if (from.getFogCoordArray()) { - if (!copyToSelf) target.setFogCoordArray(from.getFogCoordArray()); + target.setFogCoordArray(from.getFogCoordArray()); } for(unsigned int ti=0;ti= (int)_boneWeightAttribArrays.size()) + if (index >= _boneWeightAttribArrays.size()) return 0; return _boneWeightAttribArrays[index].get(); } -int RigTransformHardware::getNumVertexAttrib() +unsigned int RigTransformHardware::getNumVertexAttrib() { return _boneWeightAttribArrays.size(); } @@ -61,68 +60,83 @@ osg::Uniform* RigTransformHardware::getMatrixPaletteUniform() void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry) { - for (int i = 0; i < (int)_bonePalette.size(); i++) + for (unsigned int i = 0; i < _bonePalette.size(); i++) { osg::ref_ptr bone = _bonePalette[i].get(); - const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); - const osg::Matrix& boneMatrix = bone->getMatrixInSkeletonSpace(); - osg::Matrix resultBoneMatrix = invBindMatrix * boneMatrix; - osg::Matrix result = transformFromSkeletonToGeometry * resultBoneMatrix * invTransformFromSkeletonToGeometry; + const osg::Matrixf& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); + const osg::Matrixf& boneMatrix = bone->getMatrixInSkeletonSpace(); + osg::Matrixf resultBoneMatrix = invBindMatrix * boneMatrix; + osg::Matrixf result = transformFromSkeletonToGeometry * resultBoneMatrix * invTransformFromSkeletonToGeometry; if (!_uniformMatrixPalette->setElement(i, result)) OSG_WARN << "RigTransformHardware::computeUniformMatrixPalette can't set uniform at " << i << " elements" << std::endl; } } -int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;} -int RigTransformHardware::getNumVertexes() const { return _nbVertexes;} +unsigned int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;} +unsigned int RigTransformHardware::getNumVertexes() const { return _nbVertexes;} -bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap) +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 palette; + _bonePalette.clear(); + _boneNameToPalette.clear(); BoneNameCountMap boneNameCountMap; - // init vertex attribute data VertexIndexWeightList vertexIndexWeight; vertexIndexWeight.resize(nbVertexes); - int maxBonePerVertex = 0; - for (VertexInfluenceSet::VertexIndexToBoneWeightMap::const_iterator vit = vertexIndexToBoneWeightMap.begin(); vit != vertexIndexToBoneWeightMap.end(); ++vit) + unsigned int maxBonePerVertex = 0; + if(vertexIndexToBoneWeightMap.size()!=nbVertexes) { + OSG_WARN << "RigTransformHardware::some vertex has no transform " <first; - const VertexInfluenceSet::BoneWeightList& boneWeightList = vit->second; - int bonesForThisVertex = 0; + const VertexInfluenceSet::BoneWeightList& boneWeightList = *vit; + unsigned int bonesForThisVertex = 0; for (VertexInfluenceSet::BoneWeightList::const_iterator it = boneWeightList.begin(); it != boneWeightList.end(); ++it) { const VertexInfluenceSet::BoneWeight& bw = *it; - if(fabs(bw.getWeight()) > 1e-2) // don't use bone with weight too small + if(fabs(bw.getWeight()) > 1e-4) // don't use bone with weight too small { - if (boneNameCountMap.find(bw.getBoneName()) != boneNameCountMap.end()) + if ((boneName2PaletteIndex= _boneNameToPalette.find(bw.getBoneName())) != _boneNameToPalette.end()) { boneNameCountMap[bw.getBoneName()]++; bonesForThisVertex++; // count max number of bones per vertexes - vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(_boneNameToPalette[bw.getBoneName()],bw.getWeight())); + vertexIndexWeight[vertexID].push_back(IndexWeightEntry(boneName2PaletteIndex->second,bw.getWeight())); } else { - if (boneMap.find(bw.getBoneName()) == boneMap.end()) + BoneMap::const_iterator bonebyname; + if ((bonebyname=boneMap.find(bw.getBoneName())) == boneMap.end()) { - OSG_INFO << "RigTransformHardware::createPalette can't find bone " << bw.getBoneName() << " skip this influence" << std::endl; + 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++; - palette.push_back(boneMap[bw.getBoneName()]); - _boneNameToPalette[bw.getBoneName()] = palette.size()-1; - vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(_boneNameToPalette[bw.getBoneName()],bw.getWeight())); - } + + _boneNameToPalette[bw.getBoneName()] = _bonePalette.size() ; + vertexIndexWeight[vertexID].push_back(IndexWeightEntry(_bonePalette.size(),bw.getWeight())); + _bonePalette.push_back(bonebyname->second); + } } else { - OSG_WARN << "RigTransformHardware::createPalette Bone " << bw.getBoneName() << " has a weight " << bw.getWeight() << " for vertex " << vertexIndex << " this bone will not be in the palette" << std::endl; + 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; @@ -136,15 +150,12 @@ bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const OSG_INFO << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; - for (int i = 0 ; i < (int)vertexIndexWeight.size(); i++) - vertexIndexWeight[i].resize(maxBonePerVertex); - - _nbVertexes = nbVertexes; _bonesPerVertex = maxBonePerVertex; - _bonePalette = palette; - _vertexIndexMatrixWeightList = vertexIndexWeight; + for (int i = 0 ; i < (int)vertexIndexWeight.size(); i++) + vertexIndexWeight[i].resize(maxBonePerVertex); + _uniformMatrixPalette = createVertexUniform(); - _boneWeightAttribArrays = createVertexAttribList(); + createVertexAttribList(*this,vertexIndexWeight,this->_boneWeightAttribArrays); return true; } @@ -157,33 +168,34 @@ bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const // the idea is to use this format to have a granularity smaller // than the 4 bones using two vertex attributes // -RigTransformHardware::BoneWeightAttribList RigTransformHardware::createVertexAttribList() +void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList& _vertexIndexMatrixWeightList, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) { - BoneWeightAttribList arrayList; - int nbArray = static_cast(ceilf(getNumBonesPerVertex() * 0.5)); + unsigned int nbVertices= rig.getNumVertexes(); + unsigned int maxbonepervertex=rig.getNumBonesPerVertex(); + unsigned int nbArray = static_cast(ceilf( ((float)maxbonepervertex) * 0.5f)); if (!nbArray) - return arrayList; + return ; - arrayList.resize(nbArray); - for (int i = 0; i < nbArray; i++) + boneWeightAttribArrays.resize(nbArray); + for (unsigned int i = 0; i < nbArray; i++) { osg::ref_ptr array = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); - arrayList[i] = array; - int nbVertexes = getNumVertexes(); - array->resize(nbVertexes); - for (int j = 0; j < nbVertexes; j++) + boneWeightAttribArrays[i] = array; + array->resize( nbVertices); + for (unsigned int j = 0; j < nbVertices; j++) { - for (int b = 0; b < 2; b++) + + for (unsigned int b = 0; b < 2; b++) { // the granularity is 2 so if we have only one bone // it's convenient to init the second with a weight 0 - int boneIndexInList = i*2 + b; - int boneIndexInVec4 = b*2; + unsigned int boneIndexInList = i*2 + b; + unsigned int boneIndexInVec4 = b*2; (*array)[j][0 + boneIndexInVec4] = 0; (*array)[j][1 + boneIndexInVec4] = 0; - if (boneIndexInList < getNumBonesPerVertex()) + if (boneIndexInList < maxbonepervertex) { - float boneIndex = static_cast(_vertexIndexMatrixWeightList[j][boneIndexInList].getIndex()); + float boneIndex = static_cast(_vertexIndexMatrixWeightList[j][boneIndexInList].getBoneIndex()); float boneWeight = _vertexIndexMatrixWeightList[j][boneIndexInList].getWeight(); // fill the vec4 (*array)[j][0 + boneIndexInVec4] = boneIndex; @@ -192,10 +204,9 @@ RigTransformHardware::BoneWeightAttribList RigTransformHardware::createVertexAtt } } } - return arrayList; + return ; } - osg::Uniform* RigTransformHardware::createVertexUniform() { osg::Uniform* uniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); @@ -210,6 +221,15 @@ void RigTransformHardware::setShader(osg::Shader* shader) 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) @@ -218,72 +238,93 @@ bool RigTransformHardware::init(RigGeometry& geom) return false; } - if (!geom.getSkeleton()) - { - OSG_WARN << "RigTransformHardware no skeleton set in geometry " << geom.getName() << std::endl; - return false; - } - - // copy shallow from source geometry to rig geom.copyFrom(source); - - BoneMapVisitor mapVisitor; - geom.getSkeleton()->accept(mapVisitor); - BoneMap bm = mapVisitor.getBoneMap(); - - if (!createPalette(positionSrc->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList())) + if (!createPalette(positionSrc->size(),bm,geom.getVertexInfluenceSet().getVertexToBoneList())) return false; - osg::ref_ptr program = new osg::Program; - program->setName("HardwareSkinning"); - if (!_shader.valid()) - _shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); + osg::ref_ptr program ; + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = geom.getOrCreateStateSet(); - if (!_shader.valid()) { + //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 = _shader->getShaderSource(); + 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()); - _shader->setShaderSource(str); + vertexshader->setShaderSource(str); } else { - OSG_WARN << "MAX_MATRIX not found in Shader! " << str << std::endl; + OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl; } OSG_INFO << "Shader " << str << std::endl; } - int attribIndex = 11; - int nbAttribs = getNumVertexAttrib(); - 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; 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(_shader.get()); - osg::ref_ptr ss = geom.getOrCreateStateSet(); - ss->addUniform(getMatrixPaletteUniform()); - ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex())); - ss->setAttributeAndModes(program.get()); + 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) { if (_needInit) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index b9537cf8d..79224cdd1 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -18,6 +18,7 @@ #include #include +#include using namespace osgAnimation; RigTransformSoftware::RigTransformSoftware() @@ -33,6 +34,45 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const } +// sort by name and weight +struct SortByNameAndWeight : public std::less +{ + 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; + } +}; + bool RigTransformSoftware::init(RigGeometry& geom) { if (!geom.getSkeleton()) @@ -41,12 +81,34 @@ bool RigTransformSoftware::init(RigGeometry& geom) BoneMapVisitor mapVisitor; geom.getSkeleton()->accept(mapVisitor); BoneMap bm = mapVisitor.getBoneMap(); - initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexSetToBoneSetList()); + initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexGroupList()); if (geom.getSourceGeometry()) geom.copyFrom(*geom.getSourceGeometry()); - geom.setVertexArray(0); - geom.setNormalArray(0); + + + 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; @@ -65,74 +127,50 @@ void RigTransformSoftware::operator()(RigGeometry& geom) osg::Geometry& source = *geom.getSourceGeometry(); osg::Geometry& destination = geom; - osg::Vec3Array* positionSrc = dynamic_cast(source.getVertexArray()); - osg::Vec3Array* positionDst = dynamic_cast(destination.getVertexArray()); - if (positionSrc ) - { - if (!positionDst || (positionDst->size() != positionSrc->size()) ) - { - if (!positionDst) - { - positionDst = new osg::Vec3Array; - positionDst->setDataVariance(osg::Object::DYNAMIC); - destination.setVertexArray(positionDst); - } - *positionDst = *positionSrc; - } - if (!positionDst->empty()) - { - compute(geom.getMatrixFromSkeletonToGeometry(), - geom.getInvMatrixFromSkeletonToGeometry(), - &positionSrc->front(), - &positionDst->front()); - positionDst->dirty(); - } - - } - + osg::Vec3Array* positionSrc = static_cast(source.getVertexArray()); + osg::Vec3Array* positionDst = static_cast(destination.getVertexArray()); osg::Vec3Array* normalSrc = dynamic_cast(source.getNormalArray()); - osg::Vec3Array* normalDst = dynamic_cast(destination.getNormalArray()); + osg::Vec3Array* normalDst = static_cast(destination.getNormalArray()); + + + compute(geom.getMatrixFromSkeletonToGeometry(), + geom.getInvMatrixFromSkeletonToGeometry(), + &positionSrc->front(), + &positionDst->front()); + positionDst->dirty(); + + + if (normalSrc ) { - if (!normalDst || (normalDst->size() != normalSrc->size()) ) - { - if (!normalDst) - { - normalDst = new osg::Vec3Array; - normalDst->setDataVariance(osg::Object::DYNAMIC); - destination.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX); - } - *normalDst = *normalSrc; - } - if (!normalDst->empty()) - { computeNormal(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry(), &normalSrc->front(), &normalDst->front()); normalDst->dirty(); - } } } -void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence) +///convert BoneWeight to BonePtrWeight using bonemap +void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexGroupList& vertexgroups) { - _boneSetVertexSet.clear(); + _uniqInfluenceSet2VertIDList.clear(); - int size = influence.size(); - _boneSetVertexSet.resize(size); - for (int i = 0; i < size; i++) + 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::UniqVertexSetToBoneSet& inf = influence[i]; - int nbBones = inf.getBones().size(); - BoneWeightList& boneList = _boneSetVertexSet[i].getBones(); + 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 = inf.getBones()[b].getBoneName(); - float weight = inf.getBones()[b].getWeight(); + 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() ) { @@ -143,18 +181,18 @@ void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const Vert continue; } Bone* bone = it->second.get(); - boneList.push_back(BoneWeight(bone, weight)); + boneList.push_back(BonePtrWeight(bone, weight)); sumOfWeight += weight; } // if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0 // so we check it and renormalize the all weight bone - const double threshold = 1e-4; + /*const double threshold = 1e-4; if (!_boneSetVertexSet[i].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); - } - _boneSetVertexSet[i].getVertexes() = inf.getVertexes(); + }*/ + _uniqInfluenceSet2VertIDList[i].getVertexes() = vg.getVertexes(); } } diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index ad1686277..f5a983234 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -16,16 +16,21 @@ #include #include #include +#include using namespace osgAnimation; void VertexInfluenceSet::addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); } -const VertexInfluenceSet::VertexIndexToBoneWeightMap& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;} +const VertexInfluenceSet::VertIDToBoneWeightList& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;} // this class manage VertexInfluence database by mesh // reference bones per vertex ... -void VertexInfluenceSet::buildVertex2BoneList() + +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 VertexInfluence& vi = (*it); @@ -35,23 +40,25 @@ void VertexInfluenceSet::buildVertex2BoneList() VertexIndexWeight viw = vi[i]; int index = viw.first; float weight = viw.second; - if (vi.getName().empty()) + if (vi.getName().empty()){ OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; + } _vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight)); } } // normalize weight per vertex - for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it) + unsigned int vertid=0; + for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertid) { - BoneWeightList& bones = it->second; + 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 " << it->first << " seems to have 0 weight, skip normalize for this vertex" << std::endl; + OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " < UnifyBoneGroup; + typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; - for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it) + unsigned int vertexID=0; + for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID) { - BoneWeightList bones = it->second; - int vertexIndex = it->first; + BoneWeightList bones = *it; // sort the vector to have a consistent key std::sort(bones.begin(), bones.end(), SortByNameAndWeight()); @@ -128,10 +135,12 @@ void VertexInfluenceSet::buildUniqVertexSetToBoneSetList() UnifyBoneGroup::iterator result = unifyBuffer.find(bones); if (result == unifyBuffer.end()) unifyBuffer[bones].setBones(bones); - unifyBuffer[bones].getVertexes().push_back(vertexIndex); + 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 0729e883d843e78ae280e7533b72e073f087f024 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Sat, 26 Aug 2017 23:05:52 +0200 Subject: [PATCH 02/80] update serializers --- .../osgAnimation/AnimationManagerBase.cpp | 47 +++++++++++++-- .../osgAnimation/BasicAnimationManager.cpp | 59 +++++++++++++++++++ .../osgAnimation/MorphGeometry.cpp | 49 ++++++++++++++- .../serializers/osgAnimation/RigGeometry.cpp | 3 +- .../serializers/osgAnimation/RigTransform.cpp | 14 +++++ 5 files changed, 165 insertions(+), 7 deletions(-) diff --git a/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp b/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp index 06d2e353b..49a788fc5 100644 --- a/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp +++ b/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp @@ -5,7 +5,8 @@ #include #include #include - +namespace osgAnimation_AnimationManagerBaseWrapper +{ static bool checkAnimations( const osgAnimation::AnimationManagerBase& manager ) { return manager.getAnimationList().size()>0; @@ -13,7 +14,8 @@ static bool checkAnimations( const osgAnimation::AnimationManagerBase& manager ) static bool readAnimations( osgDB::InputStream& is, osgAnimation::AnimationManagerBase& manager ) { - unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; + unsigned int size = is.readSize(); + is >> is.BEGIN_BRACKET; for ( unsigned int i=0; i ani = is.readObjectOfType(); @@ -26,16 +28,48 @@ static bool readAnimations( osgDB::InputStream& is, osgAnimation::AnimationManag static bool writeAnimations( osgDB::OutputStream& os, const osgAnimation::AnimationManagerBase& manager ) { const osgAnimation::AnimationList& animations = manager.getAnimationList(); - os.writeSize(animations.size()); os << os.BEGIN_BRACKET << std::endl; + os.writeSize(animations.size()); + os << os.BEGIN_BRACKET << std::endl; for ( osgAnimation::AnimationList::const_iterator itr=animations.begin(); - itr!=animations.end(); ++itr ) + itr!=animations.end(); ++itr ) { os << itr->get(); } os << os.END_BRACKET << std::endl; return true; } +struct osgAnimation_AnimationManagerBasegetnumAnimations : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + osgAnimation::AnimationManagerBase* group = dynamic_cast(reinterpret_cast(objectPtr)); + outputParameters.push_back(new osg::UIntValueObject("return",group->getNumRegisteredAnimations())); + return true; + } +}; +struct osgAnimation_AnimationManagerBasegetAnimation : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + osg::Object* indexObject = inputParameters[0].get(); + + unsigned int index = 0; + osg::DoubleValueObject* dvo = dynamic_cast(indexObject); + if (dvo) index = static_cast(dvo->getValue()); + else + { + osg::UIntValueObject* uivo = dynamic_cast(indexObject); + if (uivo) index = uivo->getValue(); + } + osgAnimation::AnimationManagerBase* group = dynamic_cast(reinterpret_cast(objectPtr)); + outputParameters.push_back(group->getRegisteredAnimation(index)); + + + return true; + } +}; REGISTER_OBJECT_WRAPPER( osgAnimation_AnimationManagerBase, /*new osgAnimation::AnimationManagerBase*/NULL, osgAnimation::AnimationManagerBase, @@ -43,7 +77,10 @@ REGISTER_OBJECT_WRAPPER( osgAnimation_AnimationManagerBase, { ADD_USER_SERIALIZER( Animations ); // _animations ADD_BOOL_SERIALIZER( AutomaticLink, true ); // _automaticLink -} + ADD_METHOD_OBJECT( "getRegisteredAnimation", osgAnimation_AnimationManagerBasegetAnimation ); + ADD_METHOD_OBJECT( "getNumRegisteredAnimations", osgAnimation_AnimationManagerBasegetnumAnimations ); +} +} #undef OBJECT_CAST #define OBJECT_CAST static_cast diff --git a/src/osgWrappers/serializers/osgAnimation/BasicAnimationManager.cpp b/src/osgWrappers/serializers/osgAnimation/BasicAnimationManager.cpp index 22b913a0c..8aef704c8 100644 --- a/src/osgWrappers/serializers/osgAnimation/BasicAnimationManager.cpp +++ b/src/osgWrappers/serializers/osgAnimation/BasicAnimationManager.cpp @@ -5,12 +5,71 @@ #include #include #include +namespace osgAnimation_BasicAnimationManagerWrapper{ +struct BasicAnimationManagerIsplaying : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + osgAnimation::Animation* child = dynamic_cast(inputParameters[0].get()); + if (!child) return false; + osgAnimation::BasicAnimationManager* group = dynamic_cast(reinterpret_cast(objectPtr)); + outputParameters.push_back(new osg::BoolValueObject("return", group->isPlaying(child))); + return true; + } +}; +struct BasicAnimationManagerfindAnimation : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + + osgAnimation::Animation* child = dynamic_cast(inputParameters[0].get()); + if (!child) return false; + osgAnimation::BasicAnimationManager* group = dynamic_cast(reinterpret_cast(objectPtr)); + outputParameters.push_back(new osg::BoolValueObject("return",group->findAnimation(child))); + return true; + } +}; +struct BasicAnimationManagerPlayanimation : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + + osgAnimation::Animation* child = dynamic_cast(inputParameters[0].get()); + if (!child) return false; + osgAnimation::BasicAnimationManager* group = dynamic_cast(reinterpret_cast(objectPtr)); + group->playAnimation(child); + return true; + } +}; +struct BasicAnimationManagerStopanimation : public osgDB::MethodObject +{ + virtual bool run(void* objectPtr, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const + { + if (inputParameters.empty()) return false; + + osgAnimation::Animation* child = dynamic_cast(inputParameters[0].get()); + if (!child) return false; + osgAnimation::BasicAnimationManager* group = dynamic_cast(reinterpret_cast(objectPtr)); + group->stopAnimation(child); + return true; + } +}; REGISTER_OBJECT_WRAPPER( osgAnimation_BasicAnimationManager, new osgAnimation::BasicAnimationManager, osgAnimation::BasicAnimationManager, "osg::Object osg::NodeCallback osgAnimation::AnimationManagerBase osgAnimation::BasicAnimationManager" ) { + + ADD_METHOD_OBJECT( "isPlaying", BasicAnimationManagerIsplaying ); + ADD_METHOD_OBJECT( "findAnimation", BasicAnimationManagerfindAnimation ); + ADD_METHOD_OBJECT( "playAnimation", BasicAnimationManagerPlayanimation ); + ADD_METHOD_OBJECT( "stopAnimation", BasicAnimationManagerStopanimation ); + +} } #undef OBJECT_CAST diff --git a/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp index 8d3d3c58b..5479ebaf5 100644 --- a/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp @@ -36,10 +36,47 @@ static bool writeMorphTargets( osgDB::OutputStream& os, const osgAnimation::Morp return true; } +#define ADD_ARRAYDATA_FUNCTIONS( ORIGINAL_PROP, PROP ) \ + static bool check##ORIGINAL_PROP( const osgAnimation::MorphGeometry& geom ) \ + { return geom.get##PROP()!=0; } \ + static bool read##ORIGINAL_PROP( osgDB::InputStream& is, osgAnimation::MorphGeometry& geom ) { \ + is >> is.BEGIN_BRACKET; \ + osg::Array* array =is.readArray(); \ + geom.set##PROP((osg::Vec3Array*)array); \ + is >> is.END_BRACKET; \ + return true; \ + } \ + static bool write##ORIGINAL_PROP( osgDB::OutputStream& os, const osgAnimation::MorphGeometry& geom ) { \ + os << os.BEGIN_BRACKET << std::endl; \ + os.writeArray( geom.get##PROP()); \ + os << os.END_BRACKET << std::endl; \ + return true; \ + } +ADD_ARRAYDATA_FUNCTIONS( VertexData, VertexSource ) +ADD_ARRAYDATA_FUNCTIONS( NormalData, NormalSource ) + +struct FinishedObjectReadFillSourceIfRequiredCallback : public osgDB::FinishedObjectReadCallback +{ + virtual void objectRead(osgDB::InputStream&, osg::Object& obj) + { + + osgAnimation::MorphGeometry& geometry = static_cast(obj); + if((!geometry.getVertexSource() ||geometry.getVertexSource()->getNumElements()==0) + && dynamic_cast(geometry.getVertexArray())){ + geometry.setVertexSource((osg::Vec3Array* )geometry.getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ALL)); + } + if((!geometry.getNormalSource() ||geometry.getNormalSource()->getNumElements()==0) + && geometry.getNormalArray()){ + geometry.setNormalSource((osg::Vec3Array* )geometry.getNormalArray()->clone(osg::CopyOp::DEEP_COPY_ALL)); + } +} + +}; + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphGeometry, new osgAnimation::MorphGeometry, osgAnimation::MorphGeometry, - "osg::Object osg::Drawable osg::Geometry osgAnimation::MorphGeometry" ) + "osg::Object osg::Node osg::Drawable osg::Geometry osgAnimation::MorphGeometry" ) { BEGIN_ENUM_SERIALIZER( Method, NORMALIZED ); ADD_ENUM_VALUE( NORMALIZED ); @@ -48,4 +85,14 @@ REGISTER_OBJECT_WRAPPER( osgAnimation_MorphGeometry, ADD_USER_SERIALIZER( MorphTargets ); // _morphTargets ADD_BOOL_SERIALIZER( MorphNormals, true ); // _morphNormals + ADD_USER_SERIALIZER( VertexData ); // VertexSource + ADD_USER_SERIALIZER( NormalData ); // NormalSource + + + { + UPDATE_TO_VERSION_SCOPED( 147 ) + ADD_OBJECT_SERIALIZER( MorphTransformImplementation, osgAnimation::MorphTransform, NULL ); // _geometry + } + + wrapper->addFinishedObjectReadCallback( new FinishedObjectReadFillSourceIfRequiredCallback() ); } diff --git a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp index 2787ec91c..7c25e0376 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp @@ -2,7 +2,7 @@ #include #include #include - +namespace wrap_osgAnimationRigGeometry{ static bool checkInfluenceMap( const osgAnimation::RigGeometry& geom ) { return geom.getInfluenceMap()->size()>0; @@ -78,3 +78,4 @@ REGISTER_OBJECT_WRAPPER( osgAnimation_RigGeometry, ADD_OBJECT_SERIALIZER( RigTransformImplementation, osgAnimation::RigTransform, NULL ); // _geometry } } +} diff --git a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp index 82ba7b05d..8b1197f83 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -23,3 +24,16 @@ namespace wrap_osgAnimationRigTransformHardWare{ osgAnimation::RigTransformHardware, "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformHardware" ){} } + +namespace wrap_osgAnimationMorphTransform{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransform, + NULL, + osgAnimation::MorphTransform, + "osg::Object osgAnimation::MorphTransform" ){} +} +namespace wrap_osgAnimationMorphTransformSoftWare{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformSoftware, + new osgAnimation::MorphTransformSoftware, + osgAnimation::MorphTransformSoftware, + "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformSoftware" ){} +} From 4f0256bcc38e9a54b218b5c68bbab3b17c3f06ca Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Sun, 27 Aug 2017 00:10:52 +0200 Subject: [PATCH 03/80] remove unused code and remove a commented section --- src/osgAnimation/RigTransformSoftware.cpp | 45 ++--------------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 79224cdd1..4ab524cdb 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -34,45 +34,6 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const } -// sort by name and weight -struct SortByNameAndWeight : public std::less -{ - 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; - } -}; - bool RigTransformSoftware::init(RigGeometry& geom) { if (!geom.getSkeleton()) @@ -186,13 +147,13 @@ void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const Vert } // if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0 // so we check it and renormalize the all weight bone - /*const double threshold = 1e-4; - if (!_boneSetVertexSet[i].getBones().empty() && + 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 ca224c81dd9fb238d011efbcdee932b874cc0320 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Sun, 27 Aug 2017 02:14:12 +0200 Subject: [PATCH 04/80] replace VertexInfluence to BoneInfluenceList and VertexIndexWeight to IndexWeight fix in example --- .../osganimationhardware/osganimationhardware.cpp | 2 +- .../osganimationskinning/osganimationskinning.cpp | 6 +++--- include/osgAnimation/VertexInfluence | 14 +++++++------- src/osgAnimation/VertexInfluence.cpp | 6 +++--- src/osgPlugins/gles/AABBonBoneVisitor.cpp | 2 +- src/osgPlugins/gles/MostInfluencedGeometryByBone | 4 ++-- .../osgAnimation/ReaderWriter.cpp | 8 ++++---- .../serializers/osgAnimation/RigGeometry.cpp | 8 ++++---- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp index afd56015c..74aacb7ba 100644 --- a/examples/osganimationhardware/osganimationhardware.cpp +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -145,7 +145,7 @@ struct SetupRigGeometry : public osg::NodeVisitor if (_hardware) { osgAnimation::RigGeometry* rig = dynamic_cast(&geom); if (rig) - rig->setRigTransformImplementation(new MyRigTransformHardware); + rig->setRigTransformImplementation(new osgAnimation::RigTransformHardware); } #if 0 diff --git a/examples/osganimationskinning/osganimationskinning.cpp b/examples/osganimationskinning/osganimationskinning.cpp index 7bfa9b017..bbf4614fb 100644 --- a/examples/osganimationskinning/osganimationskinning.cpp +++ b/examples/osganimationskinning/osganimationskinning.cpp @@ -146,11 +146,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::VertexIndexWeight(i,1.0f)); + (*vim)[b0->getName()].push_back(osgAnimation::IndexWeight(i,1.0f)); else if ( val > 0.0f && val <= 1.0f) - (*vim)[b1->getName()].push_back(osgAnimation::VertexIndexWeight(i,1.0f)); + (*vim)[b1->getName()].push_back(osgAnimation::IndexWeight(i,1.0f)); else if ( val > 1.0f) - (*vim)[b2->getName()].push_back(osgAnimation::VertexIndexWeight(i,1.0f)); + (*vim)[b2->getName()].push_back(osgAnimation::IndexWeight(i,1.0f)); } geom->setInfluenceMap(vim); diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 345b25db4..0b777e283 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -25,9 +25,9 @@ namespace osgAnimation { // first is vertex index, and second the weight, the - typedef std::pair VertexIndexWeight; - typedef std::vector VertexList; - class OSGANIMATION_EXPORT VertexInfluence : public VertexList + typedef std::pair IndexWeight; + typedef std::vector VertexList; + class OSGANIMATION_EXPORT BoneInfluenceList : public VertexList { public: const std::string& getName() const { return _name;} @@ -38,14 +38,14 @@ namespace osgAnimation 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) {} }; @@ -56,7 +56,7 @@ namespace osgAnimation class OSGANIMATION_EXPORT VertexInfluenceSet { public: - typedef std::vector BoneToVertexList; + typedef std::vector BoneToVertexList; class BoneWeight { @@ -95,7 +95,7 @@ namespace osgAnimation void buildUniqVertexGroupList(); /** return a list of unique VertexGroups and their influences**/ const UniqVertexGroupList& getUniqVertexGroupList() const { return _uniqVertexSetToBoneSet;} - void addVertexInfluence(const VertexInfluence& v); + void addVertexInfluence(const BoneInfluenceList& v); void buildVertex2BoneList(unsigned int numvertices); void clear(); diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index f5a983234..b1b10fa26 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -20,7 +20,7 @@ using namespace osgAnimation; -void VertexInfluenceSet::addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); } +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 ... @@ -33,11 +33,11 @@ void VertexInfluenceSet::buildVertex2BoneList(unsigned int numvertices) for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); ++it) { - const VertexInfluence& vi = (*it); + const BoneInfluenceList& vi = (*it); int size = vi.size(); for (int i = 0; i < size; i++) { - VertexIndexWeight viw = vi[i]; + IndexWeight viw = vi[i]; int index = viw.first; float weight = viw.second; if (vi.getName().empty()){ diff --git a/src/osgPlugins/gles/AABBonBoneVisitor.cpp b/src/osgPlugins/gles/AABBonBoneVisitor.cpp index 0ea5302f7..5b3fc99dd 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::VertexInfluence vxtInf = (*itMap).second; + osgAnimation::BoneInfluenceList 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 024d87ddb..a5e8c5e97 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::VertexInfluence& vertexInfluence = (*vertexInfluencePair).second; + const osgAnimation::BoneInfluenceList& vertexInfluence = (*vertexInfluencePair).second; - for(osgAnimation::VertexInfluence::const_iterator vertexIndexWeight = vertexInfluence.begin(); vertexIndexWeight != vertexInfluence.end(); ++vertexIndexWeight) { + for(osgAnimation::BoneInfluenceList::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 add7f50fd..78824ad7c 100644 --- a/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgAnimation/ReaderWriter.cpp @@ -813,7 +813,7 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr) iteratorAdvanced = true; } - osgAnimation::VertexInfluence vi; + osgAnimation::BoneInfluenceList vi; vi.setName(name); vi.reserve(nbVertexes); for (int j = 0; j < nbVertexes; j++) @@ -827,7 +827,7 @@ bool RigGeometry_readLocalData(Object& obj, Input& fr) fr += 2; iteratorAdvanced = true; } - vi.push_back(osgAnimation::VertexIndexWeight(index, weight)); + vi.push_back(osgAnimation::IndexWeight(index, weight)); } if (fr.matchSequence("}")) { @@ -863,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::VertexInfluence& vi = it->second; - for (osgAnimation::VertexInfluence::const_iterator itv = vi.begin(); itv != vi.end(); itv++) + const osgAnimation::BoneInfluenceList& vi = it->second; + for (osgAnimation::BoneInfluenceList::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 7c25e0376..5259d1e95 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp @@ -20,7 +20,7 @@ static bool readInfluenceMap( osgDB::InputStream& is, osgAnimation::RigGeometry& is.readWrappedString(name); viSize = is.readSize(); is >> is.BEGIN_BRACKET; - osgAnimation::VertexInfluence vi; + osgAnimation::BoneInfluenceList vi; vi.setName( name ); vi.reserve( viSize ); for ( unsigned int j=0; j> index >> weight; - vi.push_back( osgAnimation::VertexIndexWeight(index, weight) ); + vi.push_back( osgAnimation::IndexWeight(index, weight) ); } (*map)[name] = vi; is >> is.END_BRACKET; @@ -47,14 +47,14 @@ static bool writeInfluenceMap( osgDB::OutputStream& os, const osgAnimation::RigG itr!=map->end(); ++itr ) { std::string name = itr->first; - const osgAnimation::VertexInfluence& vi = itr->second; + const osgAnimation::BoneInfluenceList& 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::VertexInfluence::const_iterator vitr=vi.begin(); + for ( osgAnimation::BoneInfluenceList::const_iterator vitr=vi.begin(); vitr != vi.end(); ++vitr ) { os << vitr->first << vitr->second << std::endl; From ed04e2735e1d3772640cc5bfbb733cb6126e792e Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 04:42:51 +0200 Subject: [PATCH 05/80] readd virtual void transformSoftwareMethod() for retrocompatibity --- include/osgAnimation/MorphGeometry | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index e8c89d22d..57d54ebfb 100644 --- a/include/osgAnimation/MorphGeometry +++ b/include/osgAnimation/MorphGeometry @@ -89,7 +89,7 @@ namespace osgAnimation /** Set source of vertices for this morph geometry */ inline void setVertexSource(osg::Vec3Array *v){ _positionSource=v;} - + /** Get source of vertices for this morph geometry */ inline osg::Vec3Array * getVertexSource()const{return _positionSource;} @@ -143,6 +143,8 @@ namespace osgAnimation inline void dirty(bool b=true) { _dirty = b; } inline bool isDirty()const { return _dirty; } + /** for retrocompatibility */ + virtual void transformSoftwareMethod(){ if (!_rigTransformImplementation.valid()_rigTransformImplementation = new MorphTransformSoftware();_rigTransformImplementation(*this);} protected: osg::ref_ptr _rigTransformImplementation; From 2b2a8f3d2e4c1df988b16550b2be9d6aa171d825 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 04:51:52 +0200 Subject: [PATCH 06/80] MorphTransformHardware using TBO added --- include/osgAnimation/MorphTransformHardware | 60 ++++++ src/osgAnimation/CMakeLists.txt | 2 + src/osgAnimation/MorphTransformHardware.cpp | 197 ++++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 include/osgAnimation/MorphTransformHardware create mode 100644 src/osgAnimation/MorphTransformHardware.cpp diff --git a/include/osgAnimation/MorphTransformHardware b/include/osgAnimation/MorphTransformHardware new file mode 100644 index 000000000..e75114a74 --- /dev/null +++ b/include/osgAnimation/MorphTransformHardware @@ -0,0 +1,60 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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 + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. + */ + +#ifndef OSGANIMATION_MORPH_TRANSFORM_HARDWARE +#define OSGANIMATION_MORPH_TRANSFORM_HARDWARE 1 + +#include +#include +#include +#include +#include +#include + +namespace osgAnimation +{ + class MorphGeometry; + + /// This class manage format for hardware morphing + class OSGANIMATION_EXPORT MorphTransformHardware : public MorphTransform + { + public: + + MorphTransformHardware(); + + MorphTransformHardware(const MorphTransformHardware& rth, const osg::CopyOp& copyop); + + META_Object(osgAnimation,MorphTransformHardware); + + + + + virtual void operator()(MorphGeometry&); + void setShader(osg::Shader*); + + + + protected: + + bool init(MorphGeometry&); + + + osg::ref_ptr _uniformTargetsWeight; + osg::ref_ptr _shader; + + bool _needInit; + }; +} + +#endif diff --git a/src/osgAnimation/CMakeLists.txt b/src/osgAnimation/CMakeLists.txt index dc199ef9c..7a79b914d 100644 --- a/src/osgAnimation/CMakeLists.txt +++ b/src/osgAnimation/CMakeLists.txt @@ -34,6 +34,7 @@ SET(TARGET_H ${HEADER_PATH}/RigTransform ${HEADER_PATH}/RigTransformHardware ${HEADER_PATH}/RigTransformSoftware + ${HEADER_PATH}/MorphTransformHardware ${HEADER_PATH}/MorphTransformSoftware ${HEADER_PATH}/Sampler ${HEADER_PATH}/Skeleton @@ -76,6 +77,7 @@ SET(TARGET_SRC RigGeometry.cpp RigTransformHardware.cpp RigTransformSoftware.cpp + MorphTransformHardware.cpp MorphTransformSoftware.cpp Skeleton.cpp StackedMatrixElement.cpp diff --git a/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp new file mode 100644 index 000000000..be37a470a --- /dev/null +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -0,0 +1,197 @@ +/* -*-c++-*- + * Copyleft 2016 Valentin Julien + * + * 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 + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. + */ + +#include +#include +#include +#include +#include + +///texture unit reserved for morphtarget TBO +#define MORPHTEXTUREUNIT 7 + +using namespace osgAnimation; + +MorphTransformHardware::MorphTransformHardware() +{ + _needInit = true; + +} + +MorphTransformHardware::MorphTransformHardware(const MorphTransformHardware& rth, const osg::CopyOp& copyop): + MorphTransform(rth, copyop), + _uniformTargetsWeight(rth._uniformTargetsWeight), + _shader(rth._shader), + _needInit(rth._needInit) +{ +} + +void MorphTransformHardware::setShader(osg::Shader* shader) +{ + _shader = shader; +} + +bool MorphTransformHardware::init(MorphGeometry& morphGeometry) +{ + osg::Vec3Array* pos = dynamic_cast(morphGeometry.getVertexArray()); + + osg::Vec3Array * vertexSource = (morphGeometry.getVertexSource()); + osg::Vec3Array * normalSource = (morphGeometry.getNormalSource()); + morphGeometry.setDataVariance(osg::Object::STATIC); + ///check for correct morph configuration + ///(blender osgexport doesn't set sources so assume morphgeom arrays are sources) + if(pos) + { + ///check if source is setted correctly + if (!vertexSource|| vertexSource->size() != pos->size()) + { + vertexSource =(static_cast( pos->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));//osg::Vec3Array(pos->begin(),pos->end()); + pos->setDataVariance(osg::Object::DYNAMIC); + } + osg::Vec3Array* normal = dynamic_cast(morphGeometry.getNormalArray()); + bool normalmorphable = morphGeometry.getMorphNormals() && normal; + if(!normalmorphable) { + OSG_WARN << "MorphTransformHardware::morph geometry "<size() != normal->size())) + { + normalSource =(static_cast( normal->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));//osg::Vec3Array(normal->begin(),normal->end()); + normal->setDataVariance(osg::Object::DYNAMIC); + } + } + ///end check + morphGeometry.setVertexArray(morphGeometry.getVertexSource()); + morphGeometry.setNormalArray(morphGeometry.getNormalSource(),osg::Array::BIND_PER_VERTEX); + morphGeometry.setDataVariance(osg::Object::STATIC); + + //create one TBO for all morphtargets (pack vertex/normal) + osg::Vec3Array * morphTargets=new osg::Vec3Array ; + MorphGeometry::MorphTargetList & morphlist=morphGeometry.getMorphTargetList(); + for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph) { + const osg::Geometry * morphtargetgeom= curmorph->getGeometry() ; + const osg::Vec3Array *varray=(osg::Vec3Array*)morphtargetgeom->getVertexArray(); + const osg::Vec3Array *narray=(osg::Vec3Array*)morphtargetgeom->getNormalArray(); + if(morphGeometry.getMethod()==MorphGeometry::RELATIVE){ + for(unsigned int i=0; igetNumElements(); ++i) { + morphTargets->push_back( (*varray)[i]); + morphTargets->push_back( (*narray)[i]); + } + }else{ + //convert to RELATIVE as it involve less math in the VS than NORMALIZED + const osg::Vec3Array *ovarray=(osg::Vec3Array*)morphGeometry.getVertexArray(); + const osg::Vec3Array *onarray=(osg::Vec3Array*)morphGeometry.getNormalArray(); + for(unsigned int i=0; igetNumElements(); ++i) { + morphTargets->push_back( (*varray)[i]- (*ovarray)[i] ); + morphTargets->push_back( (*narray)[i]- (*onarray)[i] ); + } + } + } + osg::TextureBuffer * morphTargetsTBO=new osg::TextureBuffer(); + morphTargetsTBO->setBufferData(morphTargets); + morphTargetsTBO->setInternalFormat( GL_RGB32F_ARB ); + + //create TBO Texture handle + osg::Uniform * morphTBOHandle=new osg::Uniform(osg::Uniform::SAMPLER_BUFFER,"morphTargets"); + morphTBOHandle->set(MORPHTEXTUREUNIT); + + //create dynamic uniform for morphtargets animation weights + _uniformTargetsWeight=new osg::Uniform(osg::Uniform::FLOAT,"morphWeights",morphlist.size()); + + + osg::ref_ptr program ; + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = morphGeometry.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("HardwareMorphing"); + //set default source if _shader is not user setted + if (!vertexshader.valid()){ + if (!_shader.valid()) + vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"morphing.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_MORPHWEIGHT"); + std::size_t start = str.find(toreplace); + if (std::string::npos == start){ + ///perhaps remanance from previous init (if saved after init) so reload shader + + vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"morphing.vert"); + if (!vertexshader.valid()) { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + str = vertexshader->getShaderSource(); + start = str.find(toreplace); + } + if (std::string::npos != start) { + std::stringstream ss; + ss << _uniformTargetsWeight->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); + } + else + { + OSG_WARN << "MAX_MORPHWEIGHT not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; + } + + + + program->addShader(vertexshader.get()); + //morphGeometry.setStateSet((osg::StateSet *) osg::CopyOp()(source.getOrCreateStateSet())); + + osg::ref_ptr ss = morphGeometry.getOrCreateStateSet(); + ss->addUniform(_uniformTargetsWeight); + ss->setTextureAttribute(MORPHTEXTUREUNIT,morphTargetsTBO); + ss->addUniform( morphTBOHandle); + ss->addUniform(new osg::Uniform("nbMorphVertex", morphGeometry.getVertexArray()->getNumElements())); + + ss->setAttributeAndModes(program.get()); + _needInit = false; + return true; +} +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(); +} From f46fdb4d4ec06f58fbeb038c62d9cfc64860e0aa Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 05:17:17 +0200 Subject: [PATCH 07/80] add a new prepareData method to the interface --- include/osgAnimation/RigTransform | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/osgAnimation/RigTransform b/include/osgAnimation/RigTransform index 184cdae0c..7be592035 100644 --- a/include/osgAnimation/RigTransform +++ b/include/osgAnimation/RigTransform @@ -33,6 +33,10 @@ namespace osgAnimation virtual void operator()(RigGeometry&) {} + /// to call manually when a skeleton is reacheable from the rig + /// in order to prepare technic data before rendering + virtual bool prepareData(RigGeometry&){} + protected: virtual ~RigTransform() {} From 6dc6bd5b922079c385d2333c6e186c095d72aeb4 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 05:22:14 +0200 Subject: [PATCH 08/80] fix a bug introduced when readding transformsoftwareMethod --- include/osgAnimation/MorphGeometry | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index 57d54ebfb..f74fdff85 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(){ if (!_rigTransformImplementation.valid()_rigTransformImplementation = new MorphTransformSoftware();_rigTransformImplementation(*this);} + virtual void transformSoftwareMethod(){ if (!_rigTransformImplementation.valid())_rigTransformImplementation = new MorphTransformSoftware();_rigTransformImplementation(*this);} protected: osg::ref_ptr _rigTransformImplementation; From 66aedbb0b365616659480fb32c167cf812adea48 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 05:22:14 +0200 Subject: [PATCH 09/80] fix a bug introduced when readding transformsoftwareMethod --- include/osgAnimation/MorphGeometry | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index 57d54ebfb..a1ec3f697 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(){ if (!_rigTransformImplementation.valid()_rigTransformImplementation = new MorphTransformSoftware();_rigTransformImplementation(*this);} + virtual void transformSoftwareMethod(){ if (!_rigTransformImplementation.valid())_rigTransformImplementation = new MorphTransformSoftware();(*_rigTransformImplementation.get())(*this);} protected: osg::ref_ptr _rigTransformImplementation; From e2168332864742cf4455c34e6f9efaadf4aadb85 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 14:23:15 +0200 Subject: [PATCH 10/80] 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 11/80] 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 12/80] 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 13/80] 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 14/80] 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 15/80] 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 16/80] 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 17/80] 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 18/80] 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 19/80] 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 20/80] 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 21/80] 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 22/80] 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 23/80] 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 24/80] 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 25/80] 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 26/80] 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 27/80] 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 28/80] 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 29/80] 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 30/80] 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 31/80] 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 32/80] 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 33/80] 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 34/80] 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 35/80] 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 36/80] 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 37/80] 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 38/80] 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 39/80] 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 40/80] 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 41/80] 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 42/80] 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 43/80] 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 44/80] 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 45/80] 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 46/80] 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)); } } From 5aa96727e90b54daee5e07c0c4b2ad7ee627220b Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Thu, 31 Aug 2017 16:35:05 +0200 Subject: [PATCH 47/80] clean and bugfixes --- include/osgAnimation/RigTransformHardware | 2 +- include/osgAnimation/VertexInfluence | 1 + src/osgAnimation/MorphTransformHardware.cpp | 20 ++--- src/osgAnimation/MorphTransformSoftware.cpp | 1 - src/osgAnimation/RigTransformHardware.cpp | 83 ++++++++++--------- src/osgAnimation/RigTransformSoftware.cpp | 2 + src/osgAnimation/VertexInfluence.cpp | 7 +- .../serializers/osgAnimation/RigGeometry.cpp | 1 + 8 files changed, 63 insertions(+), 54 deletions(-) diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index 5469fb299..674a6a66e 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -65,7 +65,7 @@ namespace osgAnimation // update rig if needed virtual void operator()(RigGeometry&); - // init animations data + // init/reset animations data virtual bool prepareData(RigGeometry& ); protected: diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index a521f13d7..bff9a11d9 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2008 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/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp index f0915bbf1..40ae94007 100644 --- a/src/osgAnimation/MorphTransformHardware.cpp +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -23,7 +23,9 @@ using namespace osgAnimation; -MorphTransformHardware::MorphTransformHardware():_needInit(true),_reservedTextureUnit(DEFAULTMORPHTEXTUREUNIT) +MorphTransformHardware::MorphTransformHardware(): + _needInit(true), + _reservedTextureUnit(DEFAULTMORPHTEXTUREUNIT) { } @@ -46,23 +48,22 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) ///check for correct morph configuration ///(blender osgexport doesn't set sources so assume morphgeom arrays are sources) if(pos) - { + { pos->setDataVariance(osg::Object::STATIC); ///check if source is setted correctly if (!vertexSource|| vertexSource->size() != pos->size()) { - vertexSource =(static_cast( pos->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));//osg::Vec3Array(pos->begin(),pos->end()); - pos->setDataVariance(osg::Object::DYNAMIC); + vertexSource =(static_cast( pos->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); } osg::Vec3Array* normal = dynamic_cast(morphGeometry.getNormalArray()); - bool normalmorphable = morphGeometry.getMorphNormals() && normal; + bool normalmorphable = morphGeometry.getMorphNormals() && normal&&(normal->getBinding()==osg::Array::BIND_PER_VERTEX); if(!normalmorphable) { - OSG_WARN << "MorphTransformHardware::morph geometry "<setDataVariance(osg::Object::STATIC); if (normalmorphable && (!normalSource || normalSource->size() != normal->size())) { - normalSource =(static_cast( normal->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));//osg::Vec3Array(normal->begin(),normal->end()); - normal->setDataVariance(osg::Object::DYNAMIC); + normalSource =(static_cast( normal->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); } } ///end check @@ -98,7 +99,7 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) //create TBO Texture handle osg::Uniform * morphTBOHandle=new osg::Uniform(osg::Uniform::SAMPLER_BUFFER,"morphTargets"); - morphTBOHandle->set(_reservedTextureUnit); + morphTBOHandle->set((int)_reservedTextureUnit); //create dynamic uniform for morphtargets animation weights _uniformTargetsWeight=new osg::Uniform(osg::Uniform::FLOAT,"morphWeights",morphlist.size()); @@ -139,7 +140,6 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) std::size_t start = str.find(toreplace); if (std::string::npos == start){ ///perhaps remanance from previous init (if saved after init) so reload shader - vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"morphing.vert"); if (!vertexshader.valid()) { OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; diff --git a/src/osgAnimation/MorphTransformSoftware.cpp b/src/osgAnimation/MorphTransformSoftware.cpp index 7080d8a4d..1965a5ed1 100644 --- a/src/osgAnimation/MorphTransformSoftware.cpp +++ b/src/osgAnimation/MorphTransformSoftware.cpp @@ -23,7 +23,6 @@ using namespace osgAnimation; bool MorphTransformSoftware::init(MorphGeometry& morphGeometry){ - morphGeometry.setDataVariance(osg::Object::DYNAMIC); osg::Vec3Array* pos = dynamic_cast(morphGeometry.getVertexArray()); osg::Vec3Array * vertexSource = (morphGeometry.getVertexSource()); diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index 85a32bdaa..b4eb7cdf1 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -21,12 +21,13 @@ using namespace osgAnimation; #define DEFAULT_FIRST_VERTATTRIB_TARGETTED 11 + 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), @@ -51,7 +52,7 @@ osg::Vec4Array* RigTransformHardware::getVertexAttrib(unsigned int index) void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry) { - for (unsigned int i = 0; i < _bonePalette.size(); i++) + for (unsigned int i = 0; i < _bonePalette.size(); ++i) { osg::ref_ptr bone = _bonePalette[i].get(); const osg::Matrixf& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); @@ -63,9 +64,6 @@ void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transf } } - -void createVertexAttribList(RigTransformHardware& rig,const std::vector > &perVertexInfluences,RigTransformHardware::BoneWeightAttribList & boneWeightAttribArrays); - // // create vertex attribute by 2 bones // vec4(boneIndex0, weight0, boneIndex1, weight1) @@ -76,12 +74,12 @@ void createVertexAttribList(RigTransformHardware& rig,const std::vector > PerVertexInfList; -void createVertexAttribList(RigTransformHardware& rig, +void createVertexAttribList(const RigTransformHardware& rig, const PerVertexInfList & perVertexInfluences, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) { - unsigned int nbVertices= rig.getNumVertexes(); - unsigned int maxbonepervertex=rig.getNumBonesPerVertex(); + unsigned int nbVertices = rig.getNumVertexes(); + unsigned int maxbonepervertex = rig.getNumBonesPerVertex(); unsigned int nbArray = static_cast(ceilf( ((float)maxbonepervertex) * 0.5f)); if (!nbArray) @@ -101,8 +99,6 @@ void createVertexAttribList(RigTransformHardware& rig, // it's convenient to init the second with a weight 0 unsigned int boneIndexInList = i*2 + b; unsigned int boneIndexInVec4 = b*2; - (*array)[j][0 + boneIndexInVec4] = 0; - (*array)[j][1 + boneIndexInVec4] = 0; if (boneIndexInList < perVertexInfluences[j].size()) { float boneIndex = static_cast(perVertexInfluences[j][boneIndexInList].getIndex()); @@ -110,6 +106,9 @@ void createVertexAttribList(RigTransformHardware& rig, // fill the vec4 (*array)[j][0 + boneIndexInVec4] = boneIndex; (*array)[j][1 + boneIndexInVec4] = boneWeight; + }else{ + (*array)[j][0 + boneIndexInVec4] = 0; + (*array)[j][1 + boneIndexInVec4] = 0; } } } @@ -133,6 +132,8 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) } rig.setSkeleton(finder._root.get()); } + if(!rig.getSkeleton()) + return false; BoneMapVisitor mapVisitor; rig.getSkeleton()->accept(mapVisitor); BoneMap boneMap = mapVisitor.getBoneMap(); @@ -154,7 +155,8 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) return true; } -bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry&rig) { +bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry&rig) +{ typedef std::map BoneNameCountMap; _nbVertexes = rig.getVertexArray()->getNumElements(); @@ -165,7 +167,7 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry IndexWeightList::size_type maxBonePerVertex=0; BoneNameCountMap boneNameCountMap; - const VertexInfluenceMap &vertexInfluenceMap=*rig.getInfluenceMap(); + const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); BoneNamePaletteIndex::iterator boneName2PaletteIndex; // init temp vertex attribute data @@ -173,14 +175,14 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry perVertexInfluences.resize(_nbVertexes); unsigned int paletteindex; - for (osgAnimation::VertexInfluenceMap::const_iterator boneinflistit = vertexInfluenceMap.begin(); + for (VertexInfluenceMap::const_iterator boneinflistit = vertexInfluenceMap.begin(); boneinflistit != vertexInfluenceMap.end(); ++boneinflistit) { const IndexWeightList& boneinflist = boneinflistit->second; const std::string& bonename = boneinflistit->first; BoneMap::const_iterator bonebyname; - if ((bonebyname=boneMap.find(bonename)) == boneMap.end()) + 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; @@ -213,10 +215,8 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry { 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()); } - 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) @@ -228,24 +228,27 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry } - ///normalize + ///normalize and get maxBonePerVertex unsigned int vertid=0; for(PerVertexInfList::iterator vertinfit=perVertexInfluences.begin(); vertinfit != perVertexInfluences.end(); ++vertinfit,++vertid) { + maxBonePerVertex = osg::maximum(maxBonePerVertex, vertinfit->size()); float sum=0; for(IndexWeightList::iterator iwit = vertinfit->begin(); iwit != vertinfit->end(); ++iwit) sum+=iwit->second; - if(sum< 1e-4){ + if(sum< 1e-4) + { OSG_WARN << "RigTransformHardware::buildPalette Warning: vertex with zero sum weights: " <begin();iwit!=vertinfit->end();++iwit) + for(IndexWeightList::iterator iwit=vertinfit->begin(); iwit!=vertinfit->end(); ++iwit) iwit->second*=sum; } } + OSG_INFO << "RigTransformHardware::buildPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); @@ -253,12 +256,16 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap ,const RigGeometry createVertexAttribList(*this,perVertexInfluences,this->_boneWeightAttribArrays); -return true; + _needInit = true; + + return true; } -bool RigTransformHardware::init(RigGeometry& rig){ - if(_bonesPerVertex>0){ - ///data seams prepared +bool RigTransformHardware::init(RigGeometry& rig) +{ + //if animdata seams prepared + if(_uniformMatrixPalette.valid()) + { osg::ref_ptr program ; osg::ref_ptr vertexshader; osg::ref_ptr stateset = rig.getOrCreateStateSet(); @@ -267,24 +274,28 @@ bool RigTransformHardware::init(RigGeometry& rig){ 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) { + if(program->getShader(i)->getType()==osg::Shader::VERTEX) + { vertexshader=program->getShader(i); program->removeShader(vertexshader); - } - } else { + } + else + { program = new osg::Program; program->setName("HardwareSkinning"); } //set default source if _shader is not user setted - if (!vertexshader.valid()) { + if (!vertexshader.valid()) + { if (!_shader.valid()) vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); else vertexshader=_shader; } - if (!vertexshader.valid()) { + if (!vertexshader.valid()) + { OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; return false; } @@ -294,7 +305,8 @@ bool RigTransformHardware::init(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) { + if (std::string::npos != start) + { std::stringstream ss; ss << getMatrixPaletteUniform()->getNumElements(); str.replace(start, toreplace.size(), ss.str()); @@ -302,28 +314,22 @@ bool RigTransformHardware::init(RigGeometry& rig){ } else { - OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl; + OSG_WARN<< "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"); @@ -333,11 +339,10 @@ bool RigTransformHardware::init(RigGeometry& rig){ stateset->addUniform(_uniformMatrixPalette); stateset->removeAttribute(osg::StateAttribute::PROGRAM); - if(!stateset->getAttribute(osg::StateAttribute::PROGRAM)) - stateset->setAttributeAndModes(program.get()); + stateset->setAttributeAndModes(program.get()); _needInit = false; - return false; + return true; } else prepareData(rig); return false; diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 403033da3..4d8be913c 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -139,6 +139,8 @@ bool RigTransformSoftware::prepareData(RigGeometry&rig) { } rig.setSkeleton(finder._root.get()); } + if(!rig.getSkeleton()) + return false; ///get bonemap from skeleton BoneMapVisitor mapVisitor; rig.getSkeleton()->accept(mapVisitor); diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index d0bba7599..ee42b53c4 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -1,5 +1,6 @@ /* -*-c++-*- * Copyright (C) 2008 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 @@ -72,7 +73,7 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert for(IndexWeightList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) { VertexIndexWeight& inf=*curinf; if( bonename.empty()) { - OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << inf.first << " is not assigned to a bone" << std::endl; + OSG_WARN << "VertexInfluenceSet::cullInfluenceCountPerVertex warning vertex " << inf.first << " is not assigned to a bone" << std::endl; } else if(inf.second>minweight)tempVec2Bones[inf.first].insert(BoneWeight(bonename, inf.second)); } @@ -161,7 +162,7 @@ struct SortByBoneWeightList : public std::less return false; } }; -void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector&uniqVertexGroupList,unsigned int numvert)const +void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& uniqVertexGroupList, unsigned int numvert)const { uniqVertexGroupList.clear(); std::vector vertex2Bones; @@ -182,7 +183,7 @@ void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& unifyBuffer[boneweightlist].vertIDs().push_back(vertexID); } if(vertex2Bones.size()==unifyBuffer.size()) { - OSG_WARN << "VertexInfluenceSet::buildmap is useless no duplicate VertexGroup" << std::endl; + OSG_WARN << "VertexInfluenceMap::computeMinimalVertexGroupList is useless no duplicate VertexGroup" << std::endl; } uniqVertexGroupList.reserve(unifyBuffer.size()); for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) diff --git a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp index 10b14d0f1..be47b97b1 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigGeometry.cpp @@ -2,6 +2,7 @@ #include #include #include + namespace wrap_osgAnimationRigGeometry{ static bool checkInfluenceMap( const osgAnimation::RigGeometry& geom ) { From dee9dc216464a65456121cec0c81a109f1ee1bfb Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Fri, 1 Sep 2017 01:43:00 +0200 Subject: [PATCH 48/80] a functional cleanup --- .../osganimationhardware.cpp | 2 +- include/osgAnimation/RigTransformHardware | 4 +- src/osgAnimation/RigTransformHardware.cpp | 122 ++++++++++-------- 3 files changed, 68 insertions(+), 60 deletions(-) diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp index acc2bf2f8..03735b2da 100644 --- a/examples/osganimationhardware/osganimationhardware.cpp +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -145,7 +145,7 @@ struct MyRigTransformHardware : public osgAnimation::RigTransformHardware ss << "boneWeight" << i; program->addBindAttribLocation(ss.str(), attribIndex + i); - if(getVertexAttrib(i)->getNumElements()!=_nbVertexes) + if(getVertexAttrib(i)->getNumElements()!=_nbVertices) OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; rig.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); OSG_INFO << "set vertex attrib " << ss.str() << std::endl; diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index 674a6a66e..2f7ea868b 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -54,7 +54,7 @@ namespace osgAnimation unsigned int getNumVertexAttrib() const {return _boneWeightAttribArrays.size();} const unsigned int &getNumBonesPerVertex() const{ return _bonesPerVertex; } - const unsigned int &getNumVertexes() const { return _nbVertexes; } + const unsigned int &getNumVertexes() const { return _nbVertices; } const BoneNamePaletteIndex& getBoneNameToPalette(){ return _boneNameToPalette; } const BonePalette& getBonePalette() { return _bonePalette; } @@ -71,7 +71,7 @@ namespace osgAnimation protected: unsigned int _bonesPerVertex; - unsigned int _nbVertexes; + unsigned int _nbVertices; BonePalette _bonePalette; BoneNamePaletteIndex _boneNameToPalette; diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index b4eb7cdf1..427cd313d 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -24,7 +24,7 @@ using namespace osgAnimation; RigTransformHardware::RigTransformHardware(): _bonesPerVertex (0), - _nbVertexes (0), + _nbVertices (0), _needInit (true), _minAttribIndex(DEFAULT_FIRST_VERTATTRIB_TARGETTED) {} @@ -32,7 +32,7 @@ RigTransformHardware::RigTransformHardware(): RigTransformHardware::RigTransformHardware(const RigTransformHardware& rth, const osg::CopyOp& copyop): RigTransform(rth, copyop), _bonesPerVertex(rth._bonesPerVertex), - _nbVertexes(rth._nbVertexes), + _nbVertices(rth._nbVertices), _bonePalette(rth._bonePalette), _boneNameToPalette(rth._boneNameToPalette), _boneWeightAttribArrays(rth._boneWeightAttribArrays), @@ -74,46 +74,75 @@ void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transf // typedef std::vector > PerVertexInfList; -void createVertexAttribList(const 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)); + +///create normalized a set of Vertex Attribs given a PerVertexInfList and return the max num bone per vertex +unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences, + RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays){ + short boneIndexInVec4; + unsigned int vertid = 0, + boneIndexInList; + IndexWeightList::size_type maxBonePerVertex = 0; + ///build vertex attrib arrays + //get maxBonePerVertex + for(PerVertexInfList::const_iterator vertinfit = perVertexInfluences.begin(); vertinfit != perVertexInfluences.end(); ++vertinfit) + maxBonePerVertex = osg::maximum(maxBonePerVertex, vertinfit->size()); + + OSG_INFO << "RigTransformHardware::createVertexAttribList maximum number of bone per vertex is " << maxBonePerVertex << std::endl; + + unsigned int nbArray = static_cast(ceilf( ((float)maxBonePerVertex) * 0.5f)); if (!nbArray) - return ; + return 0; + ///create vertex attrib arrays boneWeightAttribArrays.resize(nbArray); - for (unsigned int i = 0; i < nbArray; i++) + for(unsigned int j=0; j< nbArray; ++j) { - osg::ref_ptr array = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); - boneWeightAttribArrays[i] = array; - array->resize( nbVertices); - for (unsigned int j = 0; j < nbVertices; j++) + boneWeightAttribArrays[j] = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); + boneWeightAttribArrays[j]->resize(perVertexInfluences.size()); + } + + ///populate vertex attrib arrays + for(PerVertexInfList::const_iterator vertinfit=perVertexInfluences.begin(); vertinfit != perVertexInfluences.end(); ++vertinfit,++vertid) + { + //sum for normalization + float sum=0; + for(IndexWeightList::const_iterator iwit = vertinfit->begin(); iwit != vertinfit->end(); ++iwit) + sum+=iwit->second; + + if(sum< 1e-4) { - for (unsigned int b = 0; b < 2; b++) + OSG_WARN << "RigTransformHardware::buildPalette Warning: vertex with zero sum weights: " <(perVertexInfluences[j][boneIndexInList].getIndex()); - float boneWeight = perVertexInfluences[j][boneIndexInList].getWeight(); - // fill the vec4 - (*array)[j][0 + boneIndexInVec4] = boneIndex; - (*array)[j][1 + boneIndexInVec4] = boneWeight; - }else{ - (*array)[j][0 + boneIndexInVec4] = 0; - (*array)[j][1 + boneIndexInVec4] = 0; + boneIndexInVec4 = b*2; + boneIndexInList = j*2 + b; + if (boneIndexInList < (*vertinfit).size()) + { + float boneIndex = static_cast((*vertinfit)[boneIndexInList].getIndex()); + ///normalization here + float boneWeight = (*vertinfit)[boneIndexInList].getWeight()*sum; + dest[0 + boneIndexInVec4] = boneIndex; + dest[1 + boneIndexInVec4] = boneWeight; + } + else + { + dest[0 + boneIndexInVec4] = 0; + dest[1 + boneIndexInVec4] = 0; + } } } } } - return; + return maxBonePerVertex; } bool RigTransformHardware::prepareData(RigGeometry& rig) @@ -155,11 +184,12 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) return true; } + bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry&rig) { typedef std::map BoneNameCountMap; - _nbVertexes = rig.getVertexArray()->getNumElements(); + _nbVertices = rig.getVertexArray()->getNumElements(); _boneWeightAttribArrays.resize(0); _bonePalette.clear(); _boneNameToPalette.clear(); @@ -172,7 +202,7 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry& // init temp vertex attribute data std::vector perVertexInfluences; - perVertexInfluences.resize(_nbVertexes); + perVertexInfluences.resize(_nbVertices); unsigned int paletteindex; for (VertexInfluenceMap::const_iterator boneinflistit = vertexInfluenceMap.begin(); @@ -205,7 +235,7 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry& const VertexIndexWeight& iw = *infit; const unsigned int &index = iw.getIndex(); const float &weight = iw.getWeight(); - IndexWeightList & iwlist=perVertexInfluences[index]; + IndexWeightList & iwlist = perVertexInfluences[index]; if(fabs(weight) > 1e-4) // don't use bone with weight too small { @@ -228,34 +258,12 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry& } - ///normalize and get maxBonePerVertex - unsigned int vertid=0; - for(PerVertexInfList::iterator vertinfit=perVertexInfluences.begin(); vertinfit != perVertexInfluences.end(); ++vertinfit,++vertid) - { - maxBonePerVertex = osg::maximum(maxBonePerVertex, vertinfit->size()); - float sum=0; - for(IndexWeightList::iterator iwit = vertinfit->begin(); iwit != vertinfit->end(); ++iwit) - sum+=iwit->second; - if(sum< 1e-4) - { - OSG_WARN << "RigTransformHardware::buildPalette Warning: vertex with zero sum weights: " <begin(); iwit!=vertinfit->end(); ++iwit) - iwit->second*=sum; - } - } - OSG_INFO << "RigTransformHardware::buildPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; + if( (_bonesPerVertex = createVertexAttribList(perVertexInfluences, _boneWeightAttribArrays) ) < 1 ) + return false; _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); - _bonesPerVertex = maxBonePerVertex; - - createVertexAttribList(*this,perVertexInfluences,this->_boneWeightAttribArrays); - _needInit = true; return true; From 8b74b04de0b59ef510037198bd33857126188d01 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Fri, 1 Sep 2017 15:12:10 +0200 Subject: [PATCH 49/80] cleanup --- src/osgAnimation/MorphTransformHardware.cpp | 3 ++- src/osgAnimation/RigTransformHardware.cpp | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp index 40ae94007..48119c813 100644 --- a/src/osgAnimation/MorphTransformHardware.cpp +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -48,7 +48,8 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) ///check for correct morph configuration ///(blender osgexport doesn't set sources so assume morphgeom arrays are sources) if(pos) - { pos->setDataVariance(osg::Object::STATIC); + { + pos->setDataVariance(osg::Object::STATIC); ///check if source is setted correctly if (!vertexSource|| vertexSource->size() != pos->size()) { diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index 427cd313d..e474cde00 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -346,8 +346,7 @@ bool RigTransformHardware::init(RigGeometry& rig) stateset->removeUniform("matrixPalette"); stateset->addUniform(_uniformMatrixPalette); - stateset->removeAttribute(osg::StateAttribute::PROGRAM); - stateset->setAttributeAndModes(program.get()); + stateset->setAttribute(program.get()); _needInit = false; return true; From 0d02dfbbbd95e2a23d325b866d8fa4b7e3fd54c8 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Fri, 1 Sep 2017 16:23:49 +0200 Subject: [PATCH 50/80] remove utility classes BoneWeight and IndexWeight in order to avoid unnecessary symbols (but decrease a bit clarity of the code) --- include/osgAnimation/VertexInfluence | 22 ++++------------- src/osgAnimation/RigTransformHardware.cpp | 13 +++++----- src/osgAnimation/RigTransformSoftware.cpp | 4 +-- src/osgAnimation/VertexInfluence.cpp | 30 +++++++++++------------ 4 files changed, 28 insertions(+), 41 deletions(-) diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index bff9a11d9..2ddd39ebe 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -25,26 +25,14 @@ 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;} - }; + typedef std::pair BoneWeight; // first is vertex index, and second the weight - struct VertexIndexWeight: public std::pair - { - 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::pair VertexIndexWeight; + // list of IndexWeight typedef std::vector IndexWeightList; + // list of IndexWeight typedef std::vector BoneWeightList; + // list of Index typedef std::vector IndexList; //Bone influence list diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index e474cde00..c34ec2831 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -127,9 +127,9 @@ unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences boneIndexInList = j*2 + b; if (boneIndexInList < (*vertinfit).size()) { - float boneIndex = static_cast((*vertinfit)[boneIndexInList].getIndex()); + float boneIndex = static_cast((*vertinfit)[boneIndexInList].first); ///normalization here - float boneWeight = (*vertinfit)[boneIndexInList].getWeight()*sum; + float boneWeight = (*vertinfit)[boneIndexInList].second*sum; dest[0 + boneIndexInVec4] = boneIndex; dest[1 + boneIndexInVec4] = boneWeight; } @@ -233,8 +233,8 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry& for(IndexWeightList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) { const VertexIndexWeight& iw = *infit; - const unsigned int &index = iw.getIndex(); - const float &weight = iw.getWeight(); + const unsigned int &index = iw.first; + const float &weight = iw.second; IndexWeightList & iwlist = perVertexInfluences[index]; if(fabs(weight) > 1e-4) // don't use bone with weight too small @@ -327,14 +327,13 @@ bool RigTransformHardware::init(RigGeometry& rig) OSG_INFO << "Shader " << str << std::endl; } - unsigned int attribIndex = _minAttribIndex; unsigned int nbAttribs = getNumVertexAttrib(); for (unsigned int i = 0; i < nbAttribs; i++) { std::stringstream ss; ss << "boneWeight" << i; - program->addBindAttribLocation(ss.str(), attribIndex + i); - rig.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + program->addBindAttribLocation(ss.str(), _minAttribIndex + i); + rig.setVertexAttribArray(_minAttribIndex + i, getVertexAttrib(i)); OSG_INFO << "set vertex attrib " << ss.str() << std::endl; } diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 4d8be913c..ccb1a0a11 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -68,8 +68,8 @@ void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const R for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) { const VertexIndexWeight &iw = *infit; - const unsigned int &index = iw.getIndex(); - float weight = iw.getWeight(); + const unsigned int &index = iw.first; + float weight = iw.second; perVertexInfluences[index].push_back(BonePtrWeight(bone, weight)); } } diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index ee42b53c4..3c2c50c42 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -25,9 +25,9 @@ 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() bw2.second)return true; + if (bw1.second < bw2.second)return false; + return(bw1.firstnewsize)bwset.erase(*bwset.rbegin()); if(renormalize){ for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) - sum+=bwit->getWeight(); + sum+=bwit->second; if(sum>1e-4){ sum=1.0f/sum; for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { - VertexInfluence & inf= (*this)[bwit->getBoneName()]; - inf.push_back(VertexIndexWeight(mapit->first, bwit->getWeight()*sum)); - inf.setName(bwit->getBoneName()); + VertexInfluence & inf= (*this)[bwit->first]; + inf.push_back(VertexIndexWeight(mapit->first, bwit->second*sum)); + inf.setName(bwit->first); } } }else{ for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { - VertexInfluence & inf= (*this)[bwit->getBoneName()]; - inf.push_back(VertexIndexWeight(mapit->first,bwit->getWeight())); - inf.setName(bwit->getBoneName()); + VertexInfluence & inf= (*this)[bwit->first]; + inf.push_back(VertexIndexWeight(mapit->first,bwit->second)); + inf.setName(bwit->first); } } @@ -120,8 +120,8 @@ void VertexInfluenceMap::computePerVertexInfluenceList(std::vectorfirst, weight));; } } @@ -133,11 +133,11 @@ struct SortByNameAndWeight : public std::less bool operator()(const BoneWeight& b0, const BoneWeight& b1) const { - if (b0.getBoneName() < b1.getBoneName()) + if (b0.first < b1.first) return true; - else if (b0.getBoneName() > b1.getBoneName()) + else if (b0.first> b1.first) return false; - return (b0.getWeight() < b1.getWeight()); + return (b0.second < b1.second); } }; From 78dd81a8b4ffcd2e92125eb04d448c7d1c13647b Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Fri, 1 Sep 2017 17:48:28 +0200 Subject: [PATCH 51/80] add void InfluenceMap::removeUnexpressedBones(Skeleton &skel) const; a bit experimental but work well without further process on my test set --- include/osgAnimation/VertexInfluence | 5 + src/osgAnimation/VertexInfluence.cpp | 147 +++++++++++++++++++++++---- 2 files changed, 132 insertions(+), 20 deletions(-) diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 2ddd39ebe..eb2956b72 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -24,6 +24,8 @@ namespace osgAnimation { + class Skeleton; + // first is bonename, and second the weight typedef std::pair BoneWeight; // first is vertex index, and second the weight @@ -77,6 +79,9 @@ namespace osgAnimation /// compute the minimal VertexGroup Set in which vertices shares the same influence set void computeMinimalVertexGroupList(std::vector&uniqVertexGroupList, unsigned int numvert)const; + + //Experimental removal of unexpressed bone from the skeleton + void removeUnexpressedBones(Skeleton &skel) const; }; } diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 3c2c50c42..2548d6ed9 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -14,6 +14,8 @@ */ #include +#include +#include #include #include #include @@ -31,14 +33,17 @@ struct invweight_ordered } }; -void VertexInfluenceMap::normalize(unsigned int numvert) { +void VertexInfluenceMap::normalize(unsigned int numvert) +{ typedef std::pair > PerVertWeights; std::vector localstore; localstore.resize(numvert); - for(VertexInfluenceMap::iterator mapit=this->begin(); mapit!=this->end(); ++mapit) { + for(VertexInfluenceMap::iterator mapit=this->begin(); mapit!=this->end(); ++mapit) + { IndexWeightList &curvecinf=mapit->second; - for(IndexWeightList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) { + for(IndexWeightList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) + { VertexIndexWeight& inf=*curinf; localstore[inf.first].first+=inf.second; localstore[inf.first].second.push_back(&inf.second); @@ -46,7 +51,8 @@ void VertexInfluenceMap::normalize(unsigned int numvert) { } } unsigned int vertid=0; - for(std::vector::iterator itvert=localstore.begin(); itvert!=localstore.end(); ++itvert, ++vertid) { + for(std::vector::iterator itvert=localstore.begin(); itvert!=localstore.end(); ++itvert, ++vertid) + { PerVertWeights & weights=*itvert; if(weights.first< 1e-4) { @@ -62,41 +68,51 @@ void VertexInfluenceMap::normalize(unsigned int numvert) { } ///remove weakest influences in order to fit targetted numbonepervertex -void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervertex,float minweight, bool renormalize) { +void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervertex,float minweight, bool renormalize) +{ - typedef std::set BoneWeightOrdered; - std::map tempVec2Bones; + typedef std::set BoneWeightOrdered; + std::map tempVec2Bones; 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) { + for(IndexWeightList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) + { VertexIndexWeight& inf=*curinf; - if( bonename.empty()) { + if( bonename.empty()) + { OSG_WARN << "VertexInfluenceSet::cullInfluenceCountPerVertex warning vertex " << inf.first << " is not assigned to a bone" << std::endl; } else if(inf.second>minweight)tempVec2Bones[inf.first].insert(BoneWeight(bonename, inf.second)); } } this->clear(); - for( std::map::iterator mapit=tempVec2Bones.begin(); mapit!=tempVec2Bones.end(); ++mapit) { + 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){ + if(renormalize) + { for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) sum+=bwit->second; - if(sum>1e-4){ + if(sum>1e-4) + { sum=1.0f/sum; - for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { + for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) + { VertexInfluence & inf= (*this)[bwit->first]; inf.push_back(VertexIndexWeight(mapit->first, bwit->second*sum)); inf.setName(bwit->first); } } - }else{ - for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) { + } + else + { + for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) + { VertexInfluence & inf= (*this)[bwit->first]; inf.push_back(VertexIndexWeight(mapit->first,bwit->second)); inf.setName(bwit->first); @@ -108,13 +124,14 @@ 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(); + vertex2Bones.resize(numvert); + for (osgAnimation::VertexInfluenceMap::const_iterator it = begin(); it != end(); ++it) { const IndexWeightList& inflist = it->second; - if (it->first.empty()) { + if (it->first.empty()) + { OSG_WARN << "VertexInfluenceMap::computePerVertexInfluenceList contains unamed bone IndexWeightList" << std::endl; } for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) @@ -135,7 +152,7 @@ struct SortByNameAndWeight : public std::less { if (b0.first < b1.first) return true; - else if (b0.first> b1.first) + else if (b0.first > b1.first) return false; return (b0.second < b1.second); } @@ -182,7 +199,8 @@ void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& unifyBuffer[boneweightlist].setBoneWeights(boneweightlist); unifyBuffer[boneweightlist].vertIDs().push_back(vertexID); } - if(vertex2Bones.size()==unifyBuffer.size()) { + if(vertex2Bones.size()==unifyBuffer.size()) + { OSG_WARN << "VertexInfluenceMap::computeMinimalVertexGroupList is useless no duplicate VertexGroup" << std::endl; } uniqVertexGroupList.reserve(unifyBuffer.size()); @@ -191,3 +209,92 @@ void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& uniqVertexGroupList.push_back(it->second); } } + + +//Expermental +typedef std::vector RigList; +class CollectRigVisitor : public osg::NodeVisitor +{ +public: + META_NodeVisitor(osgAnimation, CollectRigVisitor) + CollectRigVisitor(); + + //void apply(osg::Node&); + void apply(osg::Geometry& node); + const RigList& getRigList() const; + +protected: + RigList _map; +}; +CollectRigVisitor::CollectRigVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + +//void CollectRigVisitor::apply(osg::Node&) { return; } +void CollectRigVisitor::apply(osg::Geometry& node) +{ + RigGeometry* bone = dynamic_cast(&node); + if (bone) + { + _map.push_back( bone); + traverse(node); + } + Skeleton* skeleton = dynamic_cast(&node); + if (skeleton) + traverse(node); +} + +const RigList& CollectRigVisitor::getRigList() const +{ + return _map; +} + +void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const +{ + BoneMapVisitor mapVisitor; + skel.accept(mapVisitor); + + CollectRigVisitor rigvis; + skel.accept(rigvis); + + RigList rigs=rigvis.getRigList(); + BoneMap boneMap = mapVisitor.getBoneMap(); + Bone* child,*par; + + for(BoneMap::iterator bmit=boneMap.begin(); bmit!=boneMap.end();) + { + if( this->find(bmit->first) == this->end()) + { + bool isusless=true; + for(RigList::iterator rigit=rigs.begin(); rigit != rigs.end(); ++rigit) + { + if( ((*rigit)->getInfluenceMap()->find(bmit->first) !=(*rigit)->getInfluenceMap()->end())) + { + isusless=false; + break; + } + } + if(!isusless||!(par=bmit->second->getBoneParent())) + { + ++bmit; + continue; + } + + ///Bone can be removed + Bone * bone2rm=bmit->second; + for(unsigned int numchild=0; numchildgetNumChildren(); numchild++) + { + if( (child = dynamic_cast(bone2rm->getChild(numchild))) ) + { + par->addChild(child); + bone2rm->removeChild(child); + } + } + par->removeChild(bone2rm); + ///rebuild bonemap after bone removal + skel.accept(mapVisitor); + boneMap = mapVisitor.getBoneMap(); + bmit=boneMap.begin(); + } + else ++bmit; + } + +} From 95605487223421b51530808f1f77418ad99400fa Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Fri, 1 Sep 2017 18:08:37 +0200 Subject: [PATCH 52/80] add MorphTransformHardware serializer --- src/osgWrappers/serializers/osgAnimation/RigTransform.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp index 8b1197f83..c3e40ca30 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -37,3 +38,9 @@ namespace wrap_osgAnimationMorphTransformSoftWare{ osgAnimation::MorphTransformSoftware, "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformSoftware" ){} } +namespace wrap_osgAnimationMorphTransformHardware{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformHardware, + new osgAnimation::MorphTransformHardware, + osgAnimation::MorphTransformHardware, + "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware" ){} +} From a73c20d7f5abe0cbc3b3daa9b6779c40ca16f67b Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Fri, 1 Sep 2017 19:13:01 +0200 Subject: [PATCH 53/80] update serializer with new properties --- include/osgAnimation/MorphTransformHardware | 12 ++++++++---- include/osgAnimation/RigTransformHardware | 5 ++++- src/osgAnimation/MorphTransformHardware.cpp | 5 +---- src/osgAnimation/RigTransformHardware.cpp | 4 +--- .../serializers/osgAnimation/RigTransform.cpp | 14 ++++++++++---- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/osgAnimation/MorphTransformHardware b/include/osgAnimation/MorphTransformHardware index b061cccae..650f62efd 100644 --- a/include/osgAnimation/MorphTransformHardware +++ b/include/osgAnimation/MorphTransformHardware @@ -22,6 +22,9 @@ #include #include +///texture unit reserved for morphtarget TBO +#define MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT 7 + namespace osgAnimation { class MorphGeometry; @@ -39,12 +42,13 @@ namespace osgAnimation virtual void operator()(MorphGeometry&); - inline void setShader(osg::Shader*s){_shader=s;} - inline osg::Shader * getShader()const{return _shader;} + inline void setShader( osg::Shader*s ) { _shader=s; } + inline const osg::Shader * getShader() const{ return _shader; } + inline osg::Shader * getShader() { return _shader; } ///texture unit reserved for morphtarget TBO default is 7 - void setReservedTextureUnit(unsigned int t){_reservedTextureUnit=t;} - unsigned int getReservedTextureUnit() const {return _reservedTextureUnit;} + void setReservedTextureUnit(unsigned int t) { _reservedTextureUnit=t; } + unsigned int getReservedTextureUnit() const { return _reservedTextureUnit;} protected: diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index 2f7ea868b..f27aa0506 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -23,6 +23,8 @@ #include #include +#define RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED 11 + namespace osgAnimation { class RigGeometry; @@ -48,7 +50,8 @@ namespace osgAnimation unsigned int getFirstVertexAttributeTarget()const { return _minAttribIndex;} void setShader(osg::Shader* shader) { _shader = shader; } - osg::Shader* getShader() const { return _shader; } + const osg::Shader* getShader() const { return _shader; } + osg::Shader* getShader() { return _shader; } osg::Vec4Array* getVertexAttrib(unsigned int index); unsigned int getNumVertexAttrib() const {return _boneWeightAttribArrays.size();} diff --git a/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp index 48119c813..a275d5680 100644 --- a/src/osgAnimation/MorphTransformHardware.cpp +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -18,14 +18,11 @@ #include #include -///texture unit reserved for morphtarget TBO -#define DEFAULTMORPHTEXTUREUNIT 7 - using namespace osgAnimation; MorphTransformHardware::MorphTransformHardware(): _needInit(true), - _reservedTextureUnit(DEFAULTMORPHTEXTUREUNIT) + _reservedTextureUnit(MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT) { } diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index c34ec2831..31a0d7631 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -20,13 +20,11 @@ using namespace osgAnimation; -#define DEFAULT_FIRST_VERTATTRIB_TARGETTED 11 - RigTransformHardware::RigTransformHardware(): _bonesPerVertex (0), _nbVertices (0), _needInit (true), - _minAttribIndex(DEFAULT_FIRST_VERTATTRIB_TARGETTED) + _minAttribIndex(RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED) {} RigTransformHardware::RigTransformHardware(const RigTransformHardware& rth, const osg::CopyOp& copyop): diff --git a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp index c3e40ca30..f89bd0d6a 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp @@ -2,8 +2,8 @@ #include #include #include -#include -#include + #include + #include #include #include @@ -23,7 +23,10 @@ namespace wrap_osgAnimationRigTransformHardWare{ REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformHardware, new osgAnimation::RigTransformHardware, osgAnimation::RigTransformHardware, - "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformHardware" ){} + "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformHardware" ){ + ADD_OBJECT_SERIALIZER(Shader,osg::Shader,NULL); + ADD_UINT_SERIALIZER(FirstVertexAttributeTarget,RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED); + } } namespace wrap_osgAnimationMorphTransform{ @@ -42,5 +45,8 @@ namespace wrap_osgAnimationMorphTransformHardware{ REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformHardware, new osgAnimation::MorphTransformHardware, osgAnimation::MorphTransformHardware, - "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware" ){} + "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware" ){ + ADD_OBJECT_SERIALIZER(Shader,osg::Shader,NULL); + ADD_UINT_SERIALIZER(ReservedTextureUnit,MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT); + } } From 041a2a6e72cce2a910d168bb09fd38c073e018f7 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Sun, 3 Sep 2017 17:37:06 +0200 Subject: [PATCH 54/80] make preparedata skeleton independant (as it was with the Rig::buildInfluenceSet) no more divergence with master i think --- include/osgAnimation/RigGeometry | 3 +- include/osgAnimation/RigTransformHardware | 1 + include/osgAnimation/RigTransformSoftware | 27 +- src/osgAnimation/RigTransformHardware.cpp | 355 +++++++++++----------- src/osgAnimation/RigTransformSoftware.cpp | 140 +++++---- 5 files changed, 290 insertions(+), 236 deletions(-) diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index 805e9c779..dc96c98f4 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -145,9 +145,8 @@ namespace osgAnimation osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << geom->getName() << " )" << std::endl; return; } - geom->setSkeleton(finder._root.get()); - geom->getRigTransformImplementation()->prepareData(*geom); + geom->setSkeleton(finder._root.get()); } if(!geom->getSkeleton()) diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index f27aa0506..cf506580f 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -89,6 +89,7 @@ namespace osgAnimation //on first update virtual bool init(RigGeometry& ); + std::vector _perVertexInfluences; }; } diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index ac97f527a..109bf5b85 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -40,22 +40,28 @@ namespace osgAnimation //to call when a skeleton is reacheable from the rig to prepare technic data virtual bool prepareData(RigGeometry&); - class BonePtrWeight: std::pair< osg::observer_ptr< Bone >, float> + typedef std::pair LocalBoneIDWeight; + class BonePtrWeight: LocalBoneIDWeight { public: - 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()) {} - - inline const Bone * getBonePtr() const {return first.get();} - inline void setBonePtr(Bone*b){first=b;} + BonePtrWeight(unsigned int id,float weight, Bone*bone=0 ): LocalBoneIDWeight(id,weight), _boneptr(bone){} + BonePtrWeight(const BonePtrWeight &bw2): LocalBoneIDWeight(bw2.getBoneID(),bw2.getWeight()), _boneptr(bw2._boneptr.get()){} inline const float & getWeight() const {return second;} inline void setWeight(float b) {second=b;} + inline const unsigned int & getBoneID() const {return first;} + inline void setBoneID(unsigned int b) {first=b;} inline bool operator<(const BonePtrWeight &b1) const{ if (second > b1.second)return true; if (second < b1.second)return false; - return (first.get() > b1.first.get()); + return (first > b1.first); } + ///set Bone pointer + inline const Bone * getBonePtr() const {return _boneptr.get();} + inline void setBonePtr(Bone*b){_boneptr=b;} + protected: + osg::observer_ptr< Bone > _boneptr; }; + typedef std::vector BonePtrWeightList; /// map a set of boneinfluence to a list of vertex indices sharing this set @@ -144,7 +150,6 @@ namespace osgAnimation } } - template inline void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) { @@ -166,12 +171,14 @@ namespace osgAnimation bool _needInit; + virtual bool init(RigGeometry&); + std::map _invalidInfluence; typedef std::vector VertexGroupList; - VertexGroupList _uniqVertexGroupList; - void buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig ); + + void buildMinimumUpdateSet(const RigGeometry&rig ); }; } diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index 31a0d7631..c8312a96d 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -75,10 +75,11 @@ typedef std::vector > PerVertexInfList; ///create normalized a set of Vertex Attribs given a PerVertexInfList and return the max num bone per vertex unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences, - RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays){ + RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays) +{ short boneIndexInVec4; unsigned int vertid = 0, - boneIndexInList; + boneIndexInList; IndexWeightList::size_type maxBonePerVertex = 0; ///build vertex attrib arrays //get maxBonePerVertex @@ -110,7 +111,7 @@ unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences if(sum< 1e-4) { - OSG_WARN << "RigTransformHardware::buildPalette Warning: vertex with zero sum weights: " < 1) - osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << rig.getName() << " )" << std::endl; - rig.getParents()[0]->accept(finder); + _nbVertices = rig.getSourceGeometry()->getVertexArray()->getNumElements(); + const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); + _perVertexInfluences.resize(_nbVertices); - if(!finder._root.valid()) + unsigned int localboneid=0; + for (VertexInfluenceMap::const_iterator boneinflistit = vertexInfluenceMap.begin(); + boneinflistit != vertexInfluenceMap.end(); + ++boneinflistit, ++localboneid) + { + const IndexWeightList& boneinflist = boneinflistit->second; + const std::string& bonename = boneinflistit->first; + + for(IndexWeightList::const_iterator infit = boneinflist.begin(); infit!=boneinflist.end(); ++infit) { - osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << rig.getName() << " )" << std::endl; - return false; + const VertexIndexWeight& iw = *infit; + const unsigned int &index = iw.first; + const float &weight = iw.second; + IndexWeightList & iwlist = _perVertexInfluences[index]; + + if(fabs(weight) > 1e-4) // don't use bone with weight too small + { + iwlist.push_back(VertexIndexWeight(localboneid,weight)); + } + else + { + OSG_WARN << "RigTransformHardware::prepareData Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl; + } } - rig.setSkeleton(finder._root.get()); + } + return true; +} + + +bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry&rig) +{ + + typedef std::map BoneNameCountMap; + _boneWeightAttribArrays.resize(0); + _bonePalette.clear(); + _boneNameToPalette.clear(); + + IndexWeightList::size_type maxBonePerVertex=0; + BoneNameCountMap boneNameCountMap; + + const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); + BoneNamePaletteIndex::iterator boneName2PaletteIndex; + + ///create local boneid to paletteindex + unsigned int paletteindex; + std::vector localid2bone; + localid2bone.reserve(vertexInfluenceMap.size()); + for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin(); + perBoneinfit != vertexInfluenceMap.end(); + ++perBoneinfit) + { + const std::string& bonename = perBoneinfit->first; + + if (bonename.empty()) + { + OSG_WARN << "RigTransformHardware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; + } + BoneMap::const_iterator bmit = boneMap.find(bonename); + if (bmit == boneMap.end() ) + { + OSG_WARN << "RigTransformHardware Bone " << bonename << " not found, skip the influence group " << std::endl; + localid2bone.push_back(-1); + 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(bmit->second); + } + localid2bone.push_back(paletteindex); + } + 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::buildPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; + } + + OSG_INFO << "RigTransformHardware::buildPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; + + ///set paletteindices + for( std::vector::iterator idwlistit=_perVertexInfluences.begin(); idwlistit!=_perVertexInfluences.end(); ++idwlistit) + { + for( IndexWeightList::iterator idwit=idwlistit->begin(); idwit!=idwlistit->end();) + { + if(localid2bone[idwit->first]<0)idwit=idwlistit->erase(idwit); + else{ + idwit->first=localid2bone[idwit->first]; + ++idwit; + } + } + } + if( (_bonesPerVertex = createVertexAttribList(_perVertexInfluences, _boneWeightAttribArrays) ) < 1 ) + return false; + + _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); + + _needInit = true; + return true; +} + +bool RigTransformHardware::init(RigGeometry& rig) +{ + if(_perVertexInfluences.empty()) + { + prepareData(rig); + return false; } if(!rig.getSkeleton()) return false; + BoneMapVisitor mapVisitor; rig.getSkeleton()->accept(mapVisitor); BoneMap boneMap = mapVisitor.getBoneMap(); @@ -179,178 +286,82 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) // copy shallow from source geometry to rig rig.copyFrom(source); - return true; -} + osg::ref_ptr program ; + osg::ref_ptr vertexshader; + osg::ref_ptr stateset = rig.getOrCreateStateSet(); - -bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry&rig) -{ - - typedef std::map BoneNameCountMap; - _nbVertices = rig.getVertexArray()->getNumElements(); - _boneWeightAttribArrays.resize(0); - _bonePalette.clear(); - _boneNameToPalette.clear(); - - IndexWeightList::size_type maxBonePerVertex=0; - BoneNameCountMap boneNameCountMap; - - const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); - BoneNamePaletteIndex::iterator boneName2PaletteIndex; - - // init temp vertex attribute data - std::vector perVertexInfluences; - perVertexInfluences.resize(_nbVertices); - - unsigned int paletteindex; - for (VertexInfluenceMap::const_iterator boneinflistit = vertexInfluenceMap.begin(); - boneinflistit != vertexInfluenceMap.end(); - ++boneinflistit) + //grab geom source program and vertex shader if _shader is not setted + if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM))) { - const IndexWeightList& boneinflist = boneinflistit->second; - const std::string& bonename = boneinflistit->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 VertexIndexWeight& iw = *infit; - const unsigned int &index = iw.first; - const float &weight = iw.second; - IndexWeightList & iwlist = perVertexInfluences[index]; - - if(fabs(weight) > 1e-4) // don't use bone with weight too small + for(unsigned int i=0; igetNumShaders(); ++i) + if(program->getShader(i)->getType()==osg::Shader::VERTEX) { - iwlist.push_back(VertexIndexWeight(paletteindex,weight)); + vertexshader=program->getShader(i); + program->removeShader(vertexshader); } - 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 matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; - - for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it) - { - OSG_INFO << "RigTransformHardware::buildPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; - } - - OSG_INFO << "RigTransformHardware::buildPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; - + } + 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( (_bonesPerVertex = createVertexAttribList(perVertexInfluences, _boneWeightAttribArrays) ) < 1 ) - return false; - - _uniformMatrixPalette = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); - - _needInit = true; - - return true; -} - -bool RigTransformHardware::init(RigGeometry& rig) -{ - //if animdata seams prepared - if(_uniformMatrixPalette.valid()) + if (!vertexshader.valid()) { - osg::ref_ptr program ; - osg::ref_ptr vertexshader; - osg::ref_ptr stateset = rig.getOrCreateStateSet(); + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } - //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_WARN<< "MAX_MATRIX not found in Shader! " << str << std::endl; - } - OSG_INFO << "Shader " << str << std::endl; - } - - unsigned int nbAttribs = getNumVertexAttrib(); - for (unsigned int i = 0; i < nbAttribs; i++) + // 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 << "boneWeight" << i; - program->addBindAttribLocation(ss.str(), _minAttribIndex + i); - rig.setVertexAttribArray(_minAttribIndex + i, getVertexAttrib(i)); - OSG_INFO << "set vertex attrib " << ss.str() << std::endl; + ss << getMatrixPaletteUniform()->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); } - - program->addShader(vertexshader.get()); - - stateset->removeUniform("nbBonesPerVertex"); - stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex)); - - stateset->removeUniform("matrixPalette"); - stateset->addUniform(_uniformMatrixPalette); - - stateset->setAttribute(program.get()); - - _needInit = false; - return true; + else + { + OSG_WARN<< "MAX_MATRIX not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; } - else prepareData(rig); - return false; + + unsigned int nbAttribs = getNumVertexAttrib(); + for (unsigned int i = 0; i < nbAttribs; i++) + { + std::stringstream ss; + ss << "boneWeight" << i; + program->addBindAttribLocation(ss.str(), _minAttribIndex + i); + rig.setVertexAttribArray(_minAttribIndex + 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(_uniformMatrixPalette); + + stateset->setAttribute(program.get()); + + _needInit = false; + return true; } + void RigTransformHardware::operator()(RigGeometry& geom) { if (_needInit) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index ccb1a0a11..ca78e6c79 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -38,39 +38,31 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const typedef std::vector BonePtrWeightList; -void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const RigGeometry&rig ){ - +void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) +{ ///1 Create Index2Vec const VertexInfluenceMap &vertexInfluenceMap=*rig.getInfluenceMap(); std::vector perVertexInfluences; perVertexInfluences.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements()); + unsigned int vimapBoneID = 0; for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin(); perBoneinfit != vertexInfluenceMap.end(); - ++perBoneinfit) + ++perBoneinfit,++vimapBoneID) { const IndexWeightList& inflist = perBoneinfit->second; const std::string& bonename = perBoneinfit->first; - if (bonename.empty()) { + if (bonename.empty()) + { OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; } - BoneMap::const_iterator bmit = boneMap.find(bonename); - if (bmit == boneMap.end() ) - { - 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(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) { const VertexIndexWeight &iw = *infit; const unsigned int &index = iw.first; float weight = iw.second; - perVertexInfluences[index].push_back(BonePtrWeight(bone, weight)); + perVertexInfluences[index].push_back(BonePtrWeight(vimapBoneID, weight)); } } @@ -80,7 +72,7 @@ void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const R { BonePtrWeightList& bones = *it; float sum = 0; - for(BonePtrWeightList::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) { @@ -89,7 +81,7 @@ void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const R else { float mult = 1.0/sum; - for(BonePtrWeightList::iterator bwit=bones.begin();bwit!=bones.end();++bwit) + for(BonePtrWeightList::iterator bwit=bones.begin(); bwit!=bones.end(); ++bwit) bwit->setWeight(bwit->getWeight() * mult); } } @@ -123,37 +115,13 @@ void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const R OSG_INFO << "uniq groups " << _uniqVertexGroupList.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; - 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()); - } - if(!rig.getSkeleton()) - return false; - ///get bonemap from skeleton - BoneMapVisitor mapVisitor; - rig.getSkeleton()->accept(mapVisitor); - BoneMap boneMap = mapVisitor.getBoneMap(); - - /// build minimal set of VertexGroup - buildMinimumUpdateSet(boneMap,rig); +bool RigTransformSoftware::prepareData(RigGeometry&rig) +{ ///set geom as it source if (rig.getSourceGeometry()) rig.copyFrom(*rig.getSourceGeometry()); - osg::Vec3Array* normalSrc = dynamic_cast(rig.getSourceGeometry()->getNormalArray()); osg::Vec3Array* positionSrc = dynamic_cast(rig.getSourceGeometry()->getVertexArray()); @@ -169,24 +137,92 @@ bool RigTransformSoftware::prepareData(RigGeometry&rig) { *positionDst=*positionSrc; positionDst->setDataVariance(osg::Object::DYNAMIC); - if(normalSrc) { + 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; + /// build minimal set of VertexGroup + buildMinimumUpdateSet(rig); + return true; } +bool RigTransformSoftware::init(RigGeometry&rig) +{ + ///test if dataprepared + if(_uniqVertexGroupList.empty()) + { + prepareData(rig); + return false; + } + + if(!rig.getSkeleton()) + return false; + ///get bonemap from skeleton + BoneMapVisitor mapVisitor; + rig.getSkeleton()->accept(mapVisitor); + BoneMap boneMap = mapVisitor.getBoneMap(); + VertexInfluenceMap & vertexInfluenceMap= *rig.getInfluenceMap(); + + ///create local bonemap + std::vector localid2bone; + localid2bone.reserve(vertexInfluenceMap.size()); + for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin(); + perBoneinfit != vertexInfluenceMap.end(); + ++perBoneinfit) + { + const std::string& bonename = perBoneinfit->first; + + if (bonename.empty()) + { + OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; + } + BoneMap::const_iterator bmit = boneMap.find(bonename); + if (bmit == boneMap.end() ) + { + if (_invalidInfluence.find(bonename) != _invalidInfluence.end()) + { + _invalidInfluence[bonename] = true; + OSG_WARN << "RigTransformSoftware Bone " << bonename << " not found, skip the influence group " << std::endl; + } + + localid2bone.push_back(0); + continue; + } + Bone* bone = bmit->second.get(); + localid2bone.push_back(bone); + } + + ///fill bone ptr in the _uniqVertexGroupList + for(VertexGroupList::iterator itvg=_uniqVertexGroupList.begin(); itvg!=_uniqVertexGroupList.end(); ++itvg) + { + VertexGroup& uniq = *itvg; + for(BonePtrWeightList::iterator bwit= uniq.getBoneWeights().begin(); bwit!=uniq.getBoneWeights().end(); ) + { + Bone * b=localid2bone[bwit->getBoneID()]; + if(!b) + bwit=uniq.getBoneWeights().erase(bwit); + else + bwit++->setBonePtr(b); + } + } + + _needInit = false; + + return true; +} void RigTransformSoftware::operator()(RigGeometry& geom) { if (_needInit) - if (!prepareData(geom)) + if (!init(geom)) return; - if (!geom.getSourceGeometry()) { + if (!geom.getSourceGeometry()) + { OSG_WARN << this << " RigTransformSoftware no source geometry found on RigGeometry" << std::endl; return; } @@ -209,11 +245,11 @@ void RigTransformSoftware::operator()(RigGeometry& geom) if (normalSrc ) { - computeNormal(geom.getMatrixFromSkeletonToGeometry(), - geom.getInvMatrixFromSkeletonToGeometry(), - &normalSrc->front(), - &normalDst->front()); - normalDst->dirty(); + computeNormal(geom.getMatrixFromSkeletonToGeometry(), + geom.getInvMatrixFromSkeletonToGeometry(), + &normalSrc->front(), + &normalDst->front()); + normalDst->dirty(); } } From 7da072b43365fb956b131936a32a284231c9cd52 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 4 Sep 2017 02:27:54 +0200 Subject: [PATCH 55/80] cleanup --- src/osgAnimation/RigTransformHardware.cpp | 55 ++++++++------ src/osgAnimation/RigTransformSoftware.cpp | 46 ++++++------ src/osgAnimation/VertexInfluence.cpp | 90 +++++++++++------------ 3 files changed, 101 insertions(+), 90 deletions(-) diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp index c8312a96d..38d592a55 100644 --- a/src/osgAnimation/RigTransformHardware.cpp +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -94,18 +94,23 @@ unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences return 0; ///create vertex attrib arrays + boneWeightAttribArrays.reserve(nbArray); boneWeightAttribArrays.resize(nbArray); - for(unsigned int j=0; j< nbArray; ++j) + for(unsigned int j = 0; j< nbArray; ++j) { - boneWeightAttribArrays[j] = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); - boneWeightAttribArrays[j]->resize(perVertexInfluences.size()); + osg::Vec4Array* vecattr = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); + vecattr->reserve(perVertexInfluences.size()); + vecattr->resize(perVertexInfluences.size()); + boneWeightAttribArrays[j] = vecattr; } ///populate vertex attrib arrays - for(PerVertexInfList::const_iterator vertinfit=perVertexInfluences.begin(); vertinfit != perVertexInfluences.end(); ++vertinfit,++vertid) + for(PerVertexInfList::const_iterator vertinfit = perVertexInfluences.begin(); + vertinfit != perVertexInfluences.end(); + ++vertinfit, ++vertid) { //sum for normalization - float sum=0; + float sum = 0; for(IndexWeightList::const_iterator iwit = vertinfit->begin(); iwit != vertinfit->end(); ++iwit) sum+=iwit->second; @@ -116,10 +121,10 @@ unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences } else { - sum=1.0f/sum; + sum = 1.0f/sum; for (unsigned int j = 0; j < nbArray; ++j) { - osg::Vec4& dest=(* boneWeightAttribArrays[j])[vertid]; + osg::Vec4& dest = (* boneWeightAttribArrays[j])[vertid]; for (unsigned int b = 0; b < 2; ++b) { boneIndexInVec4 = b*2; @@ -148,9 +153,10 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) { _nbVertices = rig.getSourceGeometry()->getVertexArray()->getNumElements(); const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); + _perVertexInfluences.reserve(_nbVertices); _perVertexInfluences.resize(_nbVertices); - unsigned int localboneid=0; + unsigned int localboneid = 0; for (VertexInfluenceMap::const_iterator boneinflistit = vertexInfluenceMap.begin(); boneinflistit != vertexInfluenceMap.end(); ++boneinflistit, ++localboneid) @@ -179,7 +185,7 @@ bool RigTransformHardware::prepareData(RigGeometry& rig) } -bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry&rig) +bool RigTransformHardware::buildPalette(const BoneMap& boneMap, const RigGeometry& rig) { typedef std::map BoneNameCountMap; @@ -187,7 +193,7 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry& _bonePalette.clear(); _boneNameToPalette.clear(); - IndexWeightList::size_type maxBonePerVertex=0; + IndexWeightList::size_type maxBonePerVertex = 0; BoneNameCountMap boneNameCountMap; const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); @@ -214,37 +220,37 @@ bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry& localid2bone.push_back(-1); continue; } - if ((boneName2PaletteIndex= _boneNameToPalette.find(bonename)) != _boneNameToPalette.end()) + if ( (boneName2PaletteIndex = _boneNameToPalette.find(bonename)) != _boneNameToPalette.end()) { boneNameCountMap[bonename]++; - paletteindex= boneName2PaletteIndex->second ; + paletteindex = boneName2PaletteIndex->second ; } else { boneNameCountMap[bonename] = 1; // for stats _boneNameToPalette[bonename] = _bonePalette.size() ; - paletteindex= _bonePalette.size() ; + paletteindex = _bonePalette.size() ; _bonePalette.push_back(bmit->second); } localid2bone.push_back(paletteindex); } 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::buildPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; } - OSG_INFO << "RigTransformHardware::buildPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; ///set paletteindices - for( std::vector::iterator idwlistit=_perVertexInfluences.begin(); idwlistit!=_perVertexInfluences.end(); ++idwlistit) + for( std::vector::iterator idwlistit = _perVertexInfluences.begin(); idwlistit!=_perVertexInfluences.end(); ++idwlistit) { - for( IndexWeightList::iterator idwit=idwlistit->begin(); idwit!=idwlistit->end();) + for( IndexWeightList::iterator idwit = idwlistit->begin(); idwit!=idwlistit->end();) { - if(localid2bone[idwit->first]<0)idwit=idwlistit->erase(idwit); - else{ - idwit->first=localid2bone[idwit->first]; + if(localid2bone[idwit->first]<0) + idwit = idwlistit->erase(idwit); + else + { + idwit->first = localid2bone[idwit->first]; ++idwit; } } @@ -277,6 +283,7 @@ bool RigTransformHardware::init(RigGeometry& rig) 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; @@ -293,10 +300,10 @@ bool RigTransformHardware::init(RigGeometry& rig) //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) + for(unsigned int i = 0; igetNumShaders(); ++i) + if(program->getShader(i)->getType() == osg::Shader::VERTEX) { - vertexshader=program->getShader(i); + vertexshader = program->getShader(i); program->removeShader(vertexshader); } } @@ -310,7 +317,7 @@ bool RigTransformHardware::init(RigGeometry& rig) { if (!_shader.valid()) vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); - else vertexshader=_shader; + else vertexshader = _shader; } if (!vertexshader.valid()) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index ca78e6c79..955f42424 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -36,14 +36,14 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const } -typedef std::vector BonePtrWeightList; - void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) { ///1 Create Index2Vec - const VertexInfluenceMap &vertexInfluenceMap=*rig.getInfluenceMap(); + unsigned int nbVertices=rig.getSourceGeometry()->getVertexArray()->getNumElements(); + const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap(); std::vector perVertexInfluences; - perVertexInfluences.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements()); + perVertexInfluences.reserve(nbVertices); + perVertexInfluences.resize(nbVertices); unsigned int vimapBoneID = 0; for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin(); @@ -57,7 +57,7 @@ void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) { OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl; } - for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) + for(IndexWeightList::const_iterator infit = inflist.begin(); infit!=inflist.end(); ++infit) { const VertexIndexWeight &iw = *infit; const unsigned int &index = iw.first; @@ -67,12 +67,14 @@ void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) } // normalize _vertex2Bones weight per vertex - unsigned vertexID=0; - for (std::vector::iterator it = perVertexInfluences.begin(); it != perVertexInfluences.end(); ++it, ++vertexID) + unsigned vertexID = 0; + for (std::vector::iterator it = perVertexInfluences.begin(); + it != perVertexInfluences.end(); + ++it, ++vertexID) { BonePtrWeightList& bones = *it; float sum = 0; - for(BonePtrWeightList::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) { @@ -81,7 +83,7 @@ void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) else { float mult = 1.0/sum; - for(BonePtrWeightList::iterator bwit=bones.begin(); bwit!=bones.end(); ++bwit) + for(BonePtrWeightList::iterator bwit = bones.begin(); bwit != bones.end(); ++bwit) bwit->setWeight(bwit->getWeight() * mult); } } @@ -92,8 +94,10 @@ void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; - vertexID=0; - for (std::vector::iterator perVertinfit = perVertexInfluences.begin(); perVertinfit!=perVertexInfluences.end(); ++perVertinfit,++vertexID) + vertexID = 0; + for (std::vector::iterator perVertinfit = perVertexInfluences.begin(); + perVertinfit!=perVertexInfluences.end(); + ++perVertinfit,++vertexID) { BonePtrWeightList &boneinfs = *perVertinfit; // sort the vector to have a consistent key @@ -127,20 +131,20 @@ bool RigTransformSoftware::prepareData(RigGeometry&rig) if(!(positionSrc) || positionSrc->empty() ) return false; - if(normalSrc&& normalSrc->size()!=positionSrc->size()) + 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; + osg::Vec3Array* positionDst = new osg::Vec3Array; rig.setVertexArray(positionDst); - *positionDst=*positionSrc; + *positionDst = *positionSrc; positionDst->setDataVariance(osg::Object::DYNAMIC); if(normalSrc) { - osg::Vec3Array* normalDst =new osg::Vec3Array; - *normalDst=*normalSrc; + osg::Vec3Array* normalDst = new osg::Vec3Array; + *normalDst = *normalSrc; rig.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX); normalDst->setDataVariance(osg::Object::DYNAMIC); } @@ -166,7 +170,7 @@ bool RigTransformSoftware::init(RigGeometry&rig) BoneMapVisitor mapVisitor; rig.getSkeleton()->accept(mapVisitor); BoneMap boneMap = mapVisitor.getBoneMap(); - VertexInfluenceMap & vertexInfluenceMap= *rig.getInfluenceMap(); + VertexInfluenceMap & vertexInfluenceMap = *rig.getInfluenceMap(); ///create local bonemap std::vector localid2bone; @@ -198,14 +202,14 @@ bool RigTransformSoftware::init(RigGeometry&rig) } ///fill bone ptr in the _uniqVertexGroupList - for(VertexGroupList::iterator itvg=_uniqVertexGroupList.begin(); itvg!=_uniqVertexGroupList.end(); ++itvg) + for(VertexGroupList::iterator itvg = _uniqVertexGroupList.begin(); itvg != _uniqVertexGroupList.end(); ++itvg) { VertexGroup& uniq = *itvg; - for(BonePtrWeightList::iterator bwit= uniq.getBoneWeights().begin(); bwit!=uniq.getBoneWeights().end(); ) + for(BonePtrWeightList::iterator bwit= uniq.getBoneWeights().begin(); bwit != uniq.getBoneWeights().end(); ) { - Bone * b=localid2bone[bwit->getBoneID()]; + Bone * b = localid2bone[bwit->getBoneID()]; if(!b) - bwit=uniq.getBoneWeights().erase(bwit); + bwit = uniq.getBoneWeights().erase(bwit); else bwit++->setBonePtr(b); } diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 2548d6ed9..42ca1f254 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -29,7 +29,7 @@ struct invweight_ordered { if (bw1.second > bw2.second)return true; if (bw1.second < bw2.second)return false; - return(bw1.first > PerVertWeights; std::vector localstore; localstore.resize(numvert); - for(VertexInfluenceMap::iterator mapit=this->begin(); mapit!=this->end(); ++mapit) + for(VertexInfluenceMap::iterator mapit = this->begin(); mapit != this->end(); ++mapit) { - IndexWeightList &curvecinf=mapit->second; - for(IndexWeightList::iterator curinf=curvecinf.begin(); curinf!=curvecinf.end(); ++curinf) + IndexWeightList &curvecinf = mapit->second; + for(IndexWeightList::iterator curinf = curvecinf.begin(); curinf != curvecinf.end(); ++curinf) { - VertexIndexWeight& inf=*curinf; - localstore[inf.first].first+=inf.second; + VertexIndexWeight& 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) + unsigned int vertid = 0; + for(std::vector::iterator itvert = localstore.begin(); + itvert != localstore.end(); + ++itvert, ++vertid) { - PerVertWeights & weights=*itvert; + 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; + for (std::vector::iterator itf = weights.second.begin(); itf != weights.second.end(); ++itf) + **itf *= mult; } } @@ -73,13 +75,13 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert typedef std::set BoneWeightOrdered; std::map tempVec2Bones; - for(VertexInfluenceMap::iterator mapit=this->begin(); mapit!=this->end(); ++mapit) + 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) + const std::string& bonename = mapit->first; + IndexWeightList &curvecinf = mapit->second; + for(IndexWeightList::iterator curinf = curvecinf.begin(); curinf != curvecinf.end(); ++curinf) { - VertexIndexWeight& inf=*curinf; + VertexIndexWeight& inf = *curinf; if( bonename.empty()) { OSG_WARN << "VertexInfluenceSet::cullInfluenceCountPerVertex warning vertex " << inf.first << " is not assigned to a bone" << std::endl; @@ -88,22 +90,22 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert } } this->clear(); - for( std::map::iterator mapit=tempVec2Bones.begin(); mapit!=tempVec2Bones.end(); ++mapit) + for( std::map::iterator mapit = tempVec2Bones.begin(); mapit != tempVec2Bones.end(); ++mapit) { - BoneWeightOrdered& bwset=mapit->second; - unsigned int newsize=numbonepervertexsecond; + unsigned int newsize = numbonepervertexnewsize)bwset.erase(*bwset.rbegin()); if(renormalize) { - for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) - sum+=bwit->second; - if(sum>1e-4) + for(BoneWeightOrdered::iterator bwit = bwset.begin(); bwit != bwset.end(); ++bwit) + sum += bwit->second; + if(sum > 1e-4) { - sum=1.0f/sum; - for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) + sum = 1.0f/sum; + for(BoneWeightOrdered::iterator bwit = bwset.begin(); bwit != bwset.end(); ++bwit) { - VertexInfluence & inf= (*this)[bwit->first]; + VertexInfluence & inf = (*this)[bwit->first]; inf.push_back(VertexIndexWeight(mapit->first, bwit->second*sum)); inf.setName(bwit->first); } @@ -111,9 +113,9 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert } else { - for(BoneWeightOrdered::iterator bwit=bwset.begin(); bwit!=bwset.end(); ++bwit) + for(BoneWeightOrdered::iterator bwit = bwset.begin(); bwit != bwset.end(); ++bwit) { - VertexInfluence & inf= (*this)[bwit->first]; + VertexInfluence & inf = (*this)[bwit->first]; inf.push_back(VertexIndexWeight(mapit->first,bwit->second)); inf.setName(bwit->first); } @@ -125,16 +127,14 @@ 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) + for (osgAnimation::VertexInfluenceMap::const_iterator it = begin(); it != end(); ++it) { const IndexWeightList& inflist = it->second; if (it->first.empty()) { OSG_WARN << "VertexInfluenceMap::computePerVertexInfluenceList contains unamed bone IndexWeightList" << std::endl; } - for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit) + for(IndexWeightList::const_iterator infit = inflist.begin(); infit != inflist.end(); ++infit) { const VertexIndexWeight &iw = *infit; const unsigned int &index = iw.first; @@ -179,7 +179,7 @@ struct SortByBoneWeightList : public std::less return false; } }; -void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& uniqVertexGroupList, unsigned int numvert)const +void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& uniqVertexGroupList, unsigned int numvert) const { uniqVertexGroupList.clear(); std::vector vertex2Bones; @@ -187,7 +187,7 @@ void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; - unsigned int vertexID=0; + unsigned int vertexID = 0; for (std::vector::iterator it = vertex2Bones.begin(); it != vertex2Bones.end(); ++it,++vertexID) { BoneWeightList &boneweightlist = *it; @@ -199,7 +199,7 @@ void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& unifyBuffer[boneweightlist].setBoneWeights(boneweightlist); unifyBuffer[boneweightlist].vertIDs().push_back(vertexID); } - if(vertex2Bones.size()==unifyBuffer.size()) + if(vertex2Bones.size() == unifyBuffer.size()) { OSG_WARN << "VertexInfluenceMap::computeMinimalVertexGroupList is useless no duplicate VertexGroup" << std::endl; } @@ -255,32 +255,32 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const CollectRigVisitor rigvis; skel.accept(rigvis); - RigList rigs=rigvis.getRigList(); + RigList rigs = rigvis.getRigList(); BoneMap boneMap = mapVisitor.getBoneMap(); Bone* child,*par; - for(BoneMap::iterator bmit=boneMap.begin(); bmit!=boneMap.end();) + for(BoneMap::iterator bmit = boneMap.begin(); bmit != boneMap.end();) { if( this->find(bmit->first) == this->end()) { - bool isusless=true; - for(RigList::iterator rigit=rigs.begin(); rigit != rigs.end(); ++rigit) + bool isusless = true; + for(RigList::iterator rigit = rigs.begin(); rigit != rigs.end(); ++rigit) { - if( ((*rigit)->getInfluenceMap()->find(bmit->first) !=(*rigit)->getInfluenceMap()->end())) + if( ((*rigit)->getInfluenceMap()->find(bmit->first) != (*rigit)->getInfluenceMap()->end())) { - isusless=false; + isusless = false; break; } } - if(!isusless||!(par=bmit->second->getBoneParent())) + if(!isusless || !(par = bmit->second->getBoneParent())) { ++bmit; continue; } ///Bone can be removed - Bone * bone2rm=bmit->second; - for(unsigned int numchild=0; numchildgetNumChildren(); numchild++) + Bone * bone2rm = bmit->second; + for(unsigned int numchild = 0; numchild < bone2rm->getNumChildren(); numchild++) { if( (child = dynamic_cast(bone2rm->getChild(numchild))) ) { @@ -292,7 +292,7 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const ///rebuild bonemap after bone removal skel.accept(mapVisitor); boneMap = mapVisitor.getBoneMap(); - bmit=boneMap.begin(); + bmit = boneMap.begin(); } else ++bmit; } From 0a93569b9ef83136307b48981eb23f61a2750f46 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 4 Sep 2017 12:04:37 +0200 Subject: [PATCH 56/80] add DSO scope in modified XXXTransformHardware serializers --- .../serializers/osgAnimation/RigTransform.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp index f89bd0d6a..5b69cdcd1 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp @@ -24,8 +24,11 @@ namespace wrap_osgAnimationRigTransformHardWare{ new osgAnimation::RigTransformHardware, osgAnimation::RigTransformHardware, "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformHardware" ){ - ADD_OBJECT_SERIALIZER(Shader,osg::Shader,NULL); - ADD_UINT_SERIALIZER(FirstVertexAttributeTarget,RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED); + { + UPDATE_TO_VERSION_SCOPED(150) + ADD_OBJECT_SERIALIZER(Shader, osg::Shader, NULL); + ADD_UINT_SERIALIZER(FirstVertexAttributeTarget, RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED); + } } } @@ -46,7 +49,10 @@ namespace wrap_osgAnimationMorphTransformHardware{ new osgAnimation::MorphTransformHardware, osgAnimation::MorphTransformHardware, "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware" ){ - ADD_OBJECT_SERIALIZER(Shader,osg::Shader,NULL); - ADD_UINT_SERIALIZER(ReservedTextureUnit,MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT); + { + UPDATE_TO_VERSION_SCOPED(150) + ADD_OBJECT_SERIALIZER(Shader, osg::Shader, NULL); + ADD_UINT_SERIALIZER(ReservedTextureUnit, MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT); + } } } From d2162717b8185620e55d2f0df344a1a3f9d46b5a Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Wed, 4 Oct 2017 05:42:33 +0200 Subject: [PATCH 57/80] fix normalization bug (happen too early ) minor bug bla --- include/osgAnimation/RigTransformSoftware | 1 + src/osgAnimation/RigTransformSoftware.cpp | 42 +++++++++-------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 109bf5b85..243c635d2 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -124,6 +124,7 @@ namespace osgAnimation accummulateMatrix(invBindMatrix, matrix, w); } } + void normalize(); inline const osg::Matrix& getMatrix() const { return _result;} protected: BonePtrWeightList _boneweights; diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 955f42424..4be4ca6c5 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -66,35 +66,13 @@ void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) } } - // normalize _vertex2Bones weight per vertex - unsigned vertexID = 0; - for (std::vector::iterator it = perVertexInfluences.begin(); - it != perVertexInfluences.end(); - ++it, ++vertexID) - { - BonePtrWeightList& bones = *it; - float sum = 0; - for(BonePtrWeightList::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(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 _uniqVertexGroupList.clear(); typedef std::map UnifyBoneGroup; UnifyBoneGroup unifyBuffer; - vertexID = 0; + unsigned int vertexID = 0; for (std::vector::iterator perVertinfit = perVertexInfluences.begin(); perVertinfit!=perVertexInfluences.end(); ++perVertinfit,++vertexID) @@ -188,7 +166,7 @@ bool RigTransformSoftware::init(RigGeometry&rig) BoneMap::const_iterator bmit = boneMap.find(bonename); if (bmit == boneMap.end() ) { - if (_invalidInfluence.find(bonename) != _invalidInfluence.end()) + if (_invalidInfluence.find(bonename) == _invalidInfluence.end()) { _invalidInfluence[bonename] = true; OSG_WARN << "RigTransformSoftware Bone " << bonename << " not found, skip the influence group " << std::endl; @@ -214,11 +192,25 @@ bool RigTransformSoftware::init(RigGeometry&rig) bwit++->setBonePtr(b); } } - + for(VertexGroupList::iterator itvg = _uniqVertexGroupList.begin(); itvg != _uniqVertexGroupList.end(); ++itvg) + itvg->normalize(); _needInit = false; return true; } + +void RigTransformSoftware::VertexGroup::normalize(){ + osg::Matrix::value_type sum=0; + for(BonePtrWeightList::iterator bwit = _boneweights.begin(); bwit != _boneweights.end(); ++bwit ) + sum+=bwit->getWeight(); + if (sum < 1e-4) + { + OSG_WARN << "RigTransformSoftware::VertexGroup: warning try to normalize a zero sum vertexgroup" << std::endl; + }else + for(BonePtrWeightList::iterator bwit = _boneweights.begin(); bwit != _boneweights.end(); ++bwit ) + bwit->setWeight(bwit->getWeight()/sum); +} + void RigTransformSoftware::operator()(RigGeometry& geom) { if (_needInit) From 7868b42ef2a1d19f943096253fa1e25b5b499a67 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 5 Oct 2017 16:56:30 +0100 Subject: [PATCH 58/80] Improved the readability of recent changes by adding spaces, {} and moving { onto separate lines to keep things consistent with the rest of the OSG. --- src/osgAnimation/RigTransformSoftware.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 4be4ca6c5..35993817a 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -183,7 +183,7 @@ bool RigTransformSoftware::init(RigGeometry&rig) for(VertexGroupList::iterator itvg = _uniqVertexGroupList.begin(); itvg != _uniqVertexGroupList.end(); ++itvg) { VertexGroup& uniq = *itvg; - for(BonePtrWeightList::iterator bwit= uniq.getBoneWeights().begin(); bwit != uniq.getBoneWeights().end(); ) + for(BonePtrWeightList::iterator bwit = uniq.getBoneWeights().begin(); bwit != uniq.getBoneWeights().end(); ) { Bone * b = localid2bone[bwit->getBoneID()]; if(!b) @@ -192,23 +192,36 @@ bool RigTransformSoftware::init(RigGeometry&rig) bwit++->setBonePtr(b); } } + for(VertexGroupList::iterator itvg = _uniqVertexGroupList.begin(); itvg != _uniqVertexGroupList.end(); ++itvg) + { itvg->normalize(); + } + _needInit = false; return true; } -void RigTransformSoftware::VertexGroup::normalize(){ +void RigTransformSoftware::VertexGroup::normalize() +{ osg::Matrix::value_type sum=0; for(BonePtrWeightList::iterator bwit = _boneweights.begin(); bwit != _boneweights.end(); ++bwit ) - sum+=bwit->getWeight(); + { + sum += bwit->getWeight(); + } + if (sum < 1e-4) { OSG_WARN << "RigTransformSoftware::VertexGroup: warning try to normalize a zero sum vertexgroup" << std::endl; - }else + } + else + { for(BonePtrWeightList::iterator bwit = _boneweights.begin(); bwit != _boneweights.end(); ++bwit ) + { bwit->setWeight(bwit->getWeight()/sum); + } + } } void RigTransformSoftware::operator()(RigGeometry& geom) From 2b6ffad99a9c487937cd90a5a13dec8d883830c7 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 27 Oct 2017 13:48:52 +0100 Subject: [PATCH 59/80] Build fix for when compiling with OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION set to OFF --- src/osgText/Glyph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osgText/Glyph.cpp b/src/osgText/Glyph.cpp index 17776780c..7c1dba18a 100644 --- a/src/osgText/Glyph.cpp +++ b/src/osgText/Glyph.cpp @@ -167,7 +167,7 @@ void GlyphTexture::addGlyph(Glyph* glyph, int posX, int posY) glyph->setTextureInfo(_shaderTechnique, info.get()); - copyGlyphImage(glyph, info); + copyGlyphImage(glyph, info.get()); } void GlyphTexture::copyGlyphImage(Glyph* glyph, Glyph::TextureInfo* info) From c61e4fb15c626f256addeb0ac6bfe92f62952c4d Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Fri, 27 Oct 2017 14:41:29 +0200 Subject: [PATCH 60/80] fix InfluenceMap "remove useless bones" method --- src/osgAnimation/VertexInfluence.cpp | 93 ++++++++++++++++------------ 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 42ca1f254..46460a8c0 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -210,8 +210,7 @@ void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& } } - -//Expermental +//Experimental Bone removal stuff typedef std::vector RigList; class CollectRigVisitor : public osg::NodeVisitor { @@ -219,32 +218,33 @@ public: META_NodeVisitor(osgAnimation, CollectRigVisitor) CollectRigVisitor(); - //void apply(osg::Node&); void apply(osg::Geometry& node); - const RigList& getRigList() const; + inline const RigList& getRigList() const{return _map;} protected: RigList _map; }; + CollectRigVisitor::CollectRigVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} -//void CollectRigVisitor::apply(osg::Node&) { return; } void CollectRigVisitor::apply(osg::Geometry& node) { - RigGeometry* bone = dynamic_cast(&node); - if (bone) - { - _map.push_back( bone); - traverse(node); - } - Skeleton* skeleton = dynamic_cast(&node); - if (skeleton) - traverse(node); + RigGeometry* rig = dynamic_cast(&node); + if ( rig ) + _map.push_back(rig); } -const RigList& CollectRigVisitor::getRigList() const -{ - return _map; +bool recursiveisUsefull( Bone* bone, std::set foundnames) { + for(unsigned int i=0; igetNumChildren(); ++i) { + Bone* child = dynamic_cast< Bone* >(bone->getChild(i)); + if(child){ + if( foundnames.find(child->getName()) != foundnames.end() ) + return true; + if( recursiveisUsefull(child,foundnames) ) + return true; + } + } + return false; } void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const @@ -257,44 +257,61 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const RigList rigs = rigvis.getRigList(); BoneMap boneMap = mapVisitor.getBoneMap(); - Bone* child,*par; - for(BoneMap::iterator bmit = boneMap.begin(); bmit != boneMap.end();) - { - if( this->find(bmit->first) == this->end()) - { - bool isusless = true; - for(RigList::iterator rigit = rigs.begin(); rigit != rigs.end(); ++rigit) - { - if( ((*rigit)->getInfluenceMap()->find(bmit->first) != (*rigit)->getInfluenceMap()->end())) - { - isusless = false; - break; - } - } - if(!isusless || !(par = bmit->second->getBoneParent())) + unsigned int removed=0; + Bone* child, *par; + + std::set usebones; + for(RigList::iterator rigit = rigs.begin(); rigit != rigs.end(); ++rigit) { + for(VertexInfluenceMap::iterator mapit = (*rigit)->getInfluenceMap()->begin(); + mapit != (*rigit)->getInfluenceMap()->end(); + ++mapit) { + usebones.insert((*mapit).first); + } + } + + for(BoneMap::iterator bmit = boneMap.begin(); bmit != boneMap.end();) { + if(usebones.find(bmit->second->getName()) == usebones.end()) { + if( !(par = bmit->second->getBoneParent()) ) { ++bmit; continue; } - ///Bone can be removed Bone * bone2rm = bmit->second; + + if( recursiveisUsefull(bone2rm,usebones)) { + ++bmit; + continue; + } + + ///Bone can be removed + ++ removed; + OSG_INFO<<"removing useless bone: "<< bone2rm->getName() <getNumChildren(); numchild++) { if( (child = dynamic_cast(bone2rm->getChild(numchild))) ) { - par->addChild(child); - bone2rm->removeChild(child); + if(par!=child &&child!=bone2rm) { + par->addChild(child); + nodes.push_back(child); + } } } + for(unsigned int i=0; iremoveChild(nodes[i]); par->removeChild(bone2rm); + ///rebuild bonemap after bone removal - skel.accept(mapVisitor); - boneMap = mapVisitor.getBoneMap(); - bmit = boneMap.begin(); + BoneMapVisitor mapVis ; + skel.accept(mapVis); + boneMap = mapVis.getBoneMap(); + bmit = boneMap.begin(); + } else ++bmit; } + OSG_WARN<<"Number of bone removed "< Date: Fri, 27 Oct 2017 14:19:13 +0100 Subject: [PATCH 61/80] Fixed build errors when compiling with OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION set to OFF --- include/osgAnimation/MorphGeometry | 4 ++-- include/osgAnimation/MorphTransformHardware | 4 ++-- include/osgAnimation/RigTransformHardware | 6 +++--- src/osgAnimation/MorphGeometry.cpp | 2 +- src/osgAnimation/RigGeometry.cpp | 2 +- src/osgAnimation/VertexInfluence.cpp | 2 +- src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index cf4b06228..f1401b6b1 100644 --- a/include/osgAnimation/MorphGeometry +++ b/include/osgAnimation/MorphGeometry @@ -91,13 +91,13 @@ namespace osgAnimation inline void setVertexSource(osg::Vec3Array *v){ _positionSource=v;} /** Get source of vertices for this morph geometry */ - inline osg::Vec3Array * getVertexSource()const{return _positionSource;} + inline osg::Vec3Array * getVertexSource()const{return _positionSource.get();} /** Set source of normals for this morph geometry */ inline void setNormalSource(osg::Vec3Array *n){ _normalSource=n;} /** Get source of normals for this morph geometry */ - inline osg::Vec3Array * getNormalSource()const{return _normalSource;} + inline osg::Vec3Array * getNormalSource() const {return _normalSource.get();} /** Add a \c MorphTarget to the \c MorphGeometry. * If \c MorphTarget is not \c NULL and is not contained in the \c MorphGeometry diff --git a/include/osgAnimation/MorphTransformHardware b/include/osgAnimation/MorphTransformHardware index 650f62efd..bc0eebe8b 100644 --- a/include/osgAnimation/MorphTransformHardware +++ b/include/osgAnimation/MorphTransformHardware @@ -43,8 +43,8 @@ namespace osgAnimation virtual void operator()(MorphGeometry&); inline void setShader( osg::Shader*s ) { _shader=s; } - inline const osg::Shader * getShader() const{ return _shader; } - inline osg::Shader * getShader() { return _shader; } + inline const osg::Shader * getShader() const{ return _shader.get(); } + inline osg::Shader * getShader() { return _shader.get(); } ///texture unit reserved for morphtarget TBO default is 7 void setReservedTextureUnit(unsigned int t) { _reservedTextureUnit=t; } diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index cf506580f..c71f2ae16 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -50,8 +50,8 @@ namespace osgAnimation unsigned int getFirstVertexAttributeTarget()const { return _minAttribIndex;} void setShader(osg::Shader* shader) { _shader = shader; } - const osg::Shader* getShader() const { return _shader; } - osg::Shader* getShader() { return _shader; } + const osg::Shader* getShader() const { return _shader.get(); } + osg::Shader* getShader() { return _shader.get(); } osg::Vec4Array* getVertexAttrib(unsigned int index); unsigned int getNumVertexAttrib() const {return _boneWeightAttribArrays.size();} @@ -61,7 +61,7 @@ namespace osgAnimation const BoneNamePaletteIndex& getBoneNameToPalette(){ return _boneNameToPalette; } const BonePalette& getBonePalette() { return _bonePalette; } - osg::Uniform* getMatrixPaletteUniform() { return _uniformMatrixPalette; } + osg::Uniform* getMatrixPaletteUniform() { return _uniformMatrixPalette.get(); } void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry); diff --git a/src/osgAnimation/MorphGeometry.cpp b/src/osgAnimation/MorphGeometry.cpp index 07a86d1a6..5f499716c 100644 --- a/src/osgAnimation/MorphGeometry.cpp +++ b/src/osgAnimation/MorphGeometry.cpp @@ -47,7 +47,7 @@ MorphGeometry::MorphGeometry(const osg::Geometry& g) : MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop) : osg::Geometry(b,copyop), - _morphTransformImplementation((MorphTransform*)copyop(b._morphTransformImplementation)), + _morphTransformImplementation(osg::clone(b._morphTransformImplementation.get(), copyop)), _dirty(b._dirty), _method(b._method), _morphTargets(b._morphTargets), diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index c176cf9df..6884b6c12 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -67,7 +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)), + _rigTransformImplementation(osg::clone(_rigTransformImplementation.get(), copyop)), _vertexInfluenceMap(b._vertexInfluenceMap), _needToComputeMatrix(b._needToComputeMatrix) { diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 42ca1f254..444651ce4 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -279,7 +279,7 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const } ///Bone can be removed - Bone * bone2rm = bmit->second; + Bone * bone2rm = bmit->second.get(); for(unsigned int numchild = 0; numchild < bone2rm->getNumChildren(); numchild++) { if( (child = dynamic_cast(bone2rm->getChild(numchild))) ) diff --git a/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp b/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp index 5479ebaf5..d2af644a9 100644 --- a/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp +++ b/src/osgWrappers/serializers/osgAnimation/MorphGeometry.cpp @@ -41,8 +41,8 @@ static bool writeMorphTargets( osgDB::OutputStream& os, const osgAnimation::Morp { return geom.get##PROP()!=0; } \ static bool read##ORIGINAL_PROP( osgDB::InputStream& is, osgAnimation::MorphGeometry& geom ) { \ is >> is.BEGIN_BRACKET; \ - osg::Array* array =is.readArray(); \ - geom.set##PROP((osg::Vec3Array*)array); \ + osg::ref_ptr array = is.readArray(); \ + geom.set##PROP(dynamic_cast(array.get())); \ is >> is.END_BRACKET; \ return true; \ } \ From 6530b16fc73694a3475f81151e470e288bf0573a Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 27 Oct 2017 18:14:04 +0100 Subject: [PATCH 62/80] Fixed build error when building wiht OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION=OFF --- src/osgAnimation/VertexInfluence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index ad575662c..69941853d 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -278,7 +278,7 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const continue; } - Bone * bone2rm = bmit->second; + Bone * bone2rm = bmit->second.get(); if( recursiveisUsefull(bone2rm,usebones)) { ++bmit; From 6e79ce348d2d2f5ba87fa32645d1b5842890780d Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Fri, 27 Oct 2017 21:02:43 +0200 Subject: [PATCH 63/80] reformat with the help of AStyle reformat tool (codeblocks) --- include/osgAnimation/MorphGeometry | 50 ++++++++++++--------- include/osgAnimation/MorphTransformHardware | 11 +++-- include/osgAnimation/MorphTransformSoftware | 4 +- include/osgAnimation/RigGeometry | 26 +++++------ include/osgAnimation/RigTransform | 26 +++++------ include/osgAnimation/RigTransformHardware | 24 +++++----- include/osgAnimation/RigTransformSoftware | 28 ++++++------ include/osgAnimation/VertexInfluence | 16 +++---- 8 files changed, 95 insertions(+), 90 deletions(-) diff --git a/include/osgAnimation/MorphGeometry b/include/osgAnimation/MorphGeometry index f1401b6b1..ab6c1bc8f 100644 --- a/include/osgAnimation/MorphGeometry +++ b/include/osgAnimation/MorphGeometry @@ -29,7 +29,8 @@ namespace osgAnimation public: - enum Method { + enum Method + { NORMALIZED, RELATIVE }; @@ -61,7 +62,7 @@ namespace osgAnimation virtual const char* className() const { return "MorphGeometry"; } // set implementation of rig method - inline void setMorphTransformImplementation(MorphTransform*mt) { _morphTransformImplementation=mt; } + inline void setMorphTransformImplementation(MorphTransform*mt) { _morphTransformImplementation=mt; } inline MorphTransform* getMorphTransformImplementation() { return _morphTransformImplementation.get(); } inline const MorphTransform* getMorphTransformImplementation() const { return _morphTransformImplementation.get(); } @@ -88,16 +89,16 @@ namespace osgAnimation inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; } /** Set source of vertices for this morph geometry */ - inline void setVertexSource(osg::Vec3Array *v){ _positionSource=v;} + inline void setVertexSource(osg::Vec3Array *v) { _positionSource=v; } /** Get source of vertices for this morph geometry */ - inline osg::Vec3Array * getVertexSource()const{return _positionSource.get();} + inline osg::Vec3Array * getVertexSource() const { return _positionSource.get(); } /** Set source of normals for this morph geometry */ - inline void setNormalSource(osg::Vec3Array *n){ _normalSource=n;} + inline void setNormalSource(osg::Vec3Array *n) { _normalSource=n; } /** Get source of normals for this morph geometry */ - inline osg::Vec3Array * getNormalSource() const {return _normalSource.get();} + inline osg::Vec3Array * getNormalSource() const { return _normalSource.get(); } /** Add a \c MorphTarget to the \c MorphGeometry. * If \c MorphTarget is not \c NULL and is not contained in the \c MorphGeometry @@ -108,20 +109,30 @@ namespace osgAnimation * @param weight The weight to be added to the \c MorphGeometry. * @return \c true for success; \c false otherwise. */ - virtual void addMorphTarget( osg::Geometry *morphTarget, float weight = 1.0 ) { _morphTargets.push_back(MorphTarget(morphTarget, weight)); _dirty = true; } + virtual void addMorphTarget( osg::Geometry *morphTarget, float weight = 1.0 ) + { + _morphTargets.push_back(MorphTarget(morphTarget, weight)); + _dirty = true; + } - virtual void removeMorphTarget( osg::Geometry *morphTarget ) { - for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) { - if(iterator->getGeometry() == morphTarget) { + virtual void removeMorphTarget( osg::Geometry *morphTarget ) + { + for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) + { + if(iterator->getGeometry() == morphTarget) + { _morphTargets.erase(iterator); break; } } } - virtual void removeMorphTarget( const std::string& name ) { - for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) { - if(iterator->getGeometry() && iterator->getGeometry()->getName() == name) { + virtual void removeMorphTarget( const std::string& name ) + { + for(MorphTargetList::iterator iterator = _morphTargets.begin() ; iterator != _morphTargets.end() ; ++ iterator) + { + if(iterator->getGeometry() && iterator->getGeometry()->getName() == name) + { _morphTargets.erase(iterator); break; } @@ -141,10 +152,10 @@ namespace osgAnimation /** Set the MorphGeometry dirty.*/ inline void dirty(bool b=true) { _dirty = b; } - inline bool isDirty()const { return _dirty; } + inline bool isDirty() const { return _dirty; } /** for retrocompatibility */ - void transformSoftwareMethod(){(*_morphTransformImplementation.get())(*this);} + void transformSoftwareMethod() { (*_morphTransformImplementation.get())(*this); } protected: osg::ref_ptr _morphTransformImplementation; @@ -175,7 +186,8 @@ namespace osgAnimation void addTarget(const std::string& name) { _targetNames.push_back(name); } unsigned int getNumTarget() const { return _targetNames.size(); } const std::string& getTargetName(unsigned int index) { return _targetNames[index]; } - void removeTarget(const std::string& name) { + void removeTarget(const std::string& name) + { TargetNames::iterator found = std::find(_targetNames.begin(), _targetNames.end(), name); if(found != _targetNames.end()) _targetNames.erase(found); @@ -185,9 +197,7 @@ namespace osgAnimation const std::vector& getTargetNames() const { return _targetNames; } std::vector& getTargetNames() { return _targetNames; } - void setTargetNames(const TargetNames& targetNames) { - _targetNames.assign(targetNames.begin(), targetNames.end()); - } + void setTargetNames(const TargetNames& targetNames) { _targetNames.assign(targetNames.begin(), targetNames.end()); } /** Callback method called by the NodeVisitor when visiting a node.*/ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); @@ -226,8 +236,6 @@ namespace osgAnimation (implementation)(*geom); } }; - - } #endif diff --git a/include/osgAnimation/MorphTransformHardware b/include/osgAnimation/MorphTransformHardware index bc0eebe8b..838fc99cf 100644 --- a/include/osgAnimation/MorphTransformHardware +++ b/include/osgAnimation/MorphTransformHardware @@ -42,19 +42,18 @@ namespace osgAnimation virtual void operator()(MorphGeometry&); - inline void setShader( osg::Shader*s ) { _shader=s; } - inline const osg::Shader * getShader() const{ return _shader.get(); } - inline osg::Shader * getShader() { return _shader.get(); } + inline void setShader( osg::Shader*s ) { _shader=s; } + inline const osg::Shader * getShader() const { return _shader.get(); } + inline osg::Shader * getShader() { return _shader.get(); } ///texture unit reserved for morphtarget TBO default is 7 - void setReservedTextureUnit(unsigned int t) { _reservedTextureUnit=t; } - unsigned int getReservedTextureUnit() const { return _reservedTextureUnit;} + void setReservedTextureUnit(unsigned int t) { _reservedTextureUnit=t; } + unsigned int getReservedTextureUnit() const { return _reservedTextureUnit; } protected: bool init(MorphGeometry&); - osg::ref_ptr _uniformTargetsWeight; osg::ref_ptr _shader; diff --git a/include/osgAnimation/MorphTransformSoftware b/include/osgAnimation/MorphTransformSoftware index 1130cdedc..50546501a 100644 --- a/include/osgAnimation/MorphTransformSoftware +++ b/include/osgAnimation/MorphTransformSoftware @@ -29,8 +29,8 @@ namespace osgAnimation class OSGANIMATION_EXPORT MorphTransformSoftware : public MorphTransform { public: - MorphTransformSoftware():_needInit(true){} - MorphTransformSoftware(const MorphTransformSoftware& rts,const osg::CopyOp& copyop): MorphTransform(rts, copyop), _needInit(true){} + MorphTransformSoftware():_needInit(true) {} + MorphTransformSoftware(const MorphTransformSoftware& rts,const osg::CopyOp& copyop): MorphTransform(rts, copyop), _needInit(true) {} META_Object(osgAnimation,MorphTransformSoftware) diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index dc96c98f4..f9a2b1887 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -23,7 +23,6 @@ namespace osgAnimation { - // The idea is to compute a bounding box with a factor x of the first step we compute the bounding box class OSGANIMATION_EXPORT RigComputeBoundingBoxCallback : public osg::Drawable::ComputeBoundingBoxCallback { @@ -37,8 +36,8 @@ namespace osgAnimation META_Object(osgAnimation, RigComputeBoundingBoxCallback); - void reset() { _computed = false; } + virtual osg::BoundingBox computeBound(const osg::Drawable& drawable) const; protected: mutable bool _computed; @@ -58,16 +57,16 @@ namespace osgAnimation META_Object(osgAnimation, RigGeometry); inline void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } - inline const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();} - inline VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();} + inline const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get(); } + inline VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get(); } inline const Skeleton* getSkeleton() const { return _root.get(); } inline Skeleton* getSkeleton() { return _root.get(); } // will be used by the update callback to init correctly the rig mesh - inline void setSkeleton(Skeleton* root){ _root = root;} + inline void setSkeleton(Skeleton* root) { _root = root; } - void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;} - bool getNeedToComputeMatrix() const { return _needToComputeMatrix;} + void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state; } + bool getNeedToComputeMatrix() const { return _needToComputeMatrix; } void computeMatrixFromRootSkeleton(); @@ -78,9 +77,10 @@ namespace osgAnimation void update(); - void buildVertexInfluenceSet(){_rigTransformImplementation->prepareData(*this);} + void buildVertexInfluenceSet() { _rigTransformImplementation->prepareData(*this); } const osg::Matrix& getMatrixFromSkeletonToGeometry() const; + const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const; inline osg::Geometry* getSourceGeometry() { return _geometry.get(); } @@ -106,7 +106,6 @@ namespace osgAnimation osg::ref_ptr _geometry; osg::ref_ptr _rigTransformImplementation; - osg::ref_ptr _vertexInfluenceMap; osg::Matrix _matrixFromSkeletonToGeometry; @@ -114,8 +113,7 @@ namespace osgAnimation osg::observer_ptr _root; bool _needToComputeMatrix; - - }; + }; struct UpdateRigGeometry : public osg::Drawable::UpdateCallback @@ -129,7 +127,8 @@ namespace osgAnimation META_Object(osgAnimation, UpdateRigGeometry); - virtual void update(osg::NodeVisitor* nv, osg::Drawable* drw) { + virtual void update(osg::NodeVisitor* nv, osg::Drawable* drw) + { RigGeometry* geom = dynamic_cast(drw); if(!geom) return; @@ -155,7 +154,8 @@ namespace osgAnimation if(geom->getNeedToComputeMatrix()) geom->computeMatrixFromRootSkeleton(); - if(geom->getSourceGeometry()) { + if(geom->getSourceGeometry()) + { osg::Drawable::UpdateCallback * up = dynamic_cast(geom->getSourceGeometry()->getUpdateCallback()); if(up) up->update(nv, geom->getSourceGeometry()); diff --git a/include/osgAnimation/RigTransform b/include/osgAnimation/RigTransform index 9a6a0e367..ba41b8db1 100644 --- a/include/osgAnimation/RigTransform +++ b/include/osgAnimation/RigTransform @@ -1,15 +1,15 @@ - /* -*-c++-*- - * Copyright (C) 2009 Cedric Pinson - * - * 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 - * (at your option) any later version. The full license is in LICENSE file - * included with this distribution, and on the openscenegraph.org website. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * OpenSceneGraph Public License for more details. +/* -*-c++-*- +* Copyright (C) 2009 Cedric Pinson +* +* 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 +* (at your option) any later version. The full license is in LICENSE file +* included with this distribution, and on the openscenegraph.org website. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* OpenSceneGraph Public License for more details. */ #ifndef 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&){return true;} + virtual bool prepareData(RigGeometry&) { return true; } protected: virtual ~RigTransform() {} diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware index c71f2ae16..5b020f4a4 100644 --- a/include/osgAnimation/RigTransformHardware +++ b/include/osgAnimation/RigTransformHardware @@ -46,22 +46,22 @@ namespace osgAnimation typedef std::vector MatrixPalette; ///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 setFirstVertexAttributeTarget(unsigned int i) { _minAttribIndex=i; } + unsigned int getFirstVertexAttributeTarget()const { return _minAttribIndex; } - void setShader(osg::Shader* shader) { _shader = shader; } - const osg::Shader* getShader() const { return _shader.get(); } - osg::Shader* getShader() { return _shader.get(); } + void setShader(osg::Shader* shader) { _shader = shader; } + const osg::Shader* getShader() const { return _shader.get(); } + osg::Shader* getShader() { return _shader.get(); } osg::Vec4Array* getVertexAttrib(unsigned int index); - unsigned int getNumVertexAttrib() const {return _boneWeightAttribArrays.size();} + unsigned int getNumVertexAttrib() const { return _boneWeightAttribArrays.size(); } - const unsigned int &getNumBonesPerVertex() const{ return _bonesPerVertex; } - const unsigned int &getNumVertexes() const { return _nbVertices; } + const unsigned int &getNumBonesPerVertex() const { return _bonesPerVertex; } + const unsigned int &getNumVertexes() const { return _nbVertices; } - const BoneNamePaletteIndex& getBoneNameToPalette(){ return _boneNameToPalette; } - const BonePalette& getBonePalette() { return _bonePalette; } - osg::Uniform* getMatrixPaletteUniform() { return _uniformMatrixPalette.get(); } + const BoneNamePaletteIndex& getBoneNameToPalette() { return _boneNameToPalette; } + const BonePalette& getBonePalette() { return _bonePalette; } + osg::Uniform* getMatrixPaletteUniform() { return _uniformMatrixPalette.get(); } void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry); @@ -84,7 +84,7 @@ namespace osgAnimation bool _needInit; unsigned int _minAttribIndex; - bool buildPalette(const BoneMap& boneMap ,const RigGeometry& rig); + bool buildPalette(const BoneMap& boneMap,const RigGeometry& rig); //on first update virtual bool init(RigGeometry& ); diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware index 243c635d2..4424498ba 100644 --- a/include/osgAnimation/RigTransformSoftware +++ b/include/osgAnimation/RigTransformSoftware @@ -44,20 +44,20 @@ namespace osgAnimation class BonePtrWeight: LocalBoneIDWeight { public: - BonePtrWeight(unsigned int id,float weight, Bone*bone=0 ): LocalBoneIDWeight(id,weight), _boneptr(bone){} - BonePtrWeight(const BonePtrWeight &bw2): LocalBoneIDWeight(bw2.getBoneID(),bw2.getWeight()), _boneptr(bw2._boneptr.get()){} - inline const float & getWeight() const {return second;} - inline void setWeight(float b) {second=b;} - inline const unsigned int & getBoneID() const {return first;} - inline void setBoneID(unsigned int b) {first=b;} - inline bool operator<(const BonePtrWeight &b1) const{ - if (second > b1.second)return true; - if (second < b1.second)return false; - return (first > b1.first); + BonePtrWeight(unsigned int id,float weight, Bone*bone=0 ): LocalBoneIDWeight(id,weight), _boneptr(bone) {} + BonePtrWeight(const BonePtrWeight &bw2): LocalBoneIDWeight(bw2.getBoneID(),bw2.getWeight()), _boneptr(bw2._boneptr.get()) {} + inline const float & getWeight() const { return second; } + inline void setWeight(float b) { second=b; } + inline const unsigned int & getBoneID() const { return first; } + inline void setBoneID(unsigned int b) { first=b; } + inline bool operator< (const BonePtrWeight &b1) const { + if (second > b1.second) return true; + if (second < b1.second) return false; + return (first > b1.first); } ///set Bone pointer - inline const Bone * getBonePtr() const {return _boneptr.get();} - inline void setBonePtr(Bone*b){_boneptr=b;} + inline const Bone * getBonePtr() const { return _boneptr.get(); } + inline void setBonePtr(Bone*b) { _boneptr=b; } protected: osg::observer_ptr< Bone > _boneptr; }; @@ -110,7 +110,7 @@ namespace osgAnimation } resetMatrix(); - for(BonePtrWeightList::iterator bwit=_boneweights.begin();bwit!=_boneweights.end();++bwit ) + for(BonePtrWeightList::iterator bwit=_boneweights.begin(); bwit!=_boneweights.end(); ++bwit ) { const Bone* bone = bwit->getBonePtr(); if (!bone) @@ -125,7 +125,7 @@ namespace osgAnimation } } void normalize(); - inline const osg::Matrix& getMatrix() const { return _result;} + inline const osg::Matrix& getMatrix() const { return _result; } protected: BonePtrWeightList _boneweights; IndexList _vertexes; diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index eb2956b72..256d9c198 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -41,15 +41,14 @@ namespace osgAnimation class OSGANIMATION_EXPORT VertexInfluence : public IndexWeightList { public: - const std::string& getName() const { return _name;} - void setName(const std::string& name) { _name = name;} - + const std::string& getName() const { return _name; } + void setName(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); @@ -57,8 +56,8 @@ namespace osgAnimation VertexInfluenceMap() {} VertexInfluenceMap(const osgAnimation::VertexInfluenceMap& org, const osg::CopyOp& copyop): std::map(org), - osg::Object(org, copyop) - {} + osg::Object(org, copyop) {} + ///normalize per vertex weights given numvert of the attached mesh void normalize(unsigned int numvert); @@ -72,8 +71,8 @@ namespace osgAnimation class VertexGroup: public std::pair { public: - inline const BoneWeightList& getBoneWeights()const { return first; } - inline void setBoneWeights( BoneWeightList& o ) { first=o; } + inline const BoneWeightList& getBoneWeights() const { return first; } + inline void setBoneWeights( BoneWeightList& o ) { first=o; } inline IndexList& vertIDs() { return second; } }; @@ -83,7 +82,6 @@ namespace osgAnimation //Experimental removal of unexpressed bone from the skeleton void removeUnexpressedBones(Skeleton &skel) const; }; - } #endif From bd3262e07f5d836f6b842b831870aa39f5ff636d Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 30 Oct 2017 14:22:10 +0000 Subject: [PATCH 64/80] From Raymond de Vires, Windows build fix --- src/osgAnimation/VertexInfluence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 69941853d..1f77be6aa 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -25,7 +25,7 @@ using namespace osgAnimation; struct invweight_ordered { - inline bool operator() (const BoneWeight& bw1, const BoneWeight& bw2) + inline bool operator() (const BoneWeight& bw1, const BoneWeight& bw2) const { if (bw1.second > bw2.second)return true; if (bw1.second < bw2.second)return false; From e196b2372362e40f7efde5447a3cc0430599b23e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 30 Oct 2017 14:36:41 +0000 Subject: [PATCH 65/80] From Raymond de Vires, added support for 2018 and 2016 versions of FBX. --- CMakeModules/FindFBX.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeModules/FindFBX.cmake b/CMakeModules/FindFBX.cmake index ab0a2c2d8..b2f2ac1cb 100644 --- a/CMakeModules/FindFBX.cmake +++ b/CMakeModules/FindFBX.cmake @@ -60,9 +60,13 @@ SET(FBX_LIBNAME_DEBUG ${FBX_LIBNAME}d) SET( FBX_SEARCH_PATHS $ENV{FBX_DIR} + "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2018.1.1" + "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2018.1.1" "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2017.1" "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2017.1" "/Applications/Autodesk/FBX SDK/2017.1" + "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2016.1.2" + "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2016.1.2" "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2016.1.1" "$ENV{PROGRAMFILES}/Autodesk/FBX/FBX SDK/2016.1.1" "$ENV{ProgramW6432}/Autodesk/FBX/FBX SDK/2015.1" From 47c4ef510d02ddbee4b78a0023ec31b6f215efc5 Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Tue, 31 Oct 2017 18:00:06 +0100 Subject: [PATCH 66/80] update example to use a common program --- .../osganimationhardware.cpp | 122 +++++++----------- 1 file changed, 47 insertions(+), 75 deletions(-) diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp index 03735b2da..a377bbd4d 100644 --- a/examples/osganimationhardware/osganimationhardware.cpp +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -42,27 +42,22 @@ static unsigned int getRandomValueinRange(unsigned int v) } -//osg::ref_ptr program; +osg::ref_ptr CommonProgram; // show how to override the default RigTransformHardware for customized usage struct MyRigTransformHardware : public osgAnimation::RigTransformHardware { - + int _maxmatrix; + MyRigTransformHardware() : _maxmatrix(99){} virtual bool init(osgAnimation::RigGeometry& rig) { - if(!rig.getSkeleton() && !rig.getParents().empty()) + if(_perVertexInfluences.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); - - 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()); + prepareData(rig); + return false; } + if(!rig.getSkeleton()) + return false; + osgAnimation::BoneMapVisitor mapVisitor; rig.getSkeleton()->accept(mapVisitor); osgAnimation::BoneMap boneMap = mapVisitor.getBoneMap(); @@ -72,6 +67,7 @@ struct MyRigTransformHardware : public osgAnimation::RigTransformHardware 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; @@ -81,86 +77,62 @@ struct MyRigTransformHardware : public osgAnimation::RigTransformHardware // copy shallow from source geometry to rig rig.copyFrom(source); - osg::ref_ptr program ; osg::ref_ptr vertexshader; osg::ref_ptr stateset = rig.getOrCreateStateSet(); + if(!CommonProgram.valid()){ + CommonProgram = new osg::Program; + CommonProgram->setName("HardwareSkinning"); - //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) + //set default source if _shader is not user setted + if (!vertexshader.valid()) + { + vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); + } + + 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) { - vertexshader=program->getShader(i); - program->removeShader(vertexshader); - + std::stringstream ss; + ss << _maxmatrix;//getMatrixPaletteUniform()->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); } - } - 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::stringstream ss; - ss << getMatrixPaletteUniform()->getNumElements(); - str.replace(start, toreplace.size(), ss.str()); - vertexshader->setShaderSource(str); + else + { + OSG_WARN<< "MAX_MATRIX not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; } - else - { - OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl; - } - OSG_INFO << "Shader " << str << std::endl; + CommonProgram->addShader(vertexshader.get()); } - - 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()!=_nbVertices) - OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl; - rig.setVertexAttribArray(attribIndex + i, getVertexAttrib(i)); + CommonProgram->addBindAttribLocation(ss.str(), _minAttribIndex + i); + rig.setVertexAttribArray(_minAttribIndex + 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()); + stateset->removeUniform("matrixPalette"); + stateset->addUniform(_uniformMatrixPalette); + + stateset->setAttribute(CommonProgram.get()); _needInit = false; return true; From 826c139ef39f6b4315f0ad64ba0469d1c416a482 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 10 Nov 2017 12:41:21 +0000 Subject: [PATCH 67/80] Fixed crash in copy constructor due to copy and paste/typo. --- src/osgAnimation/RigGeometry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index 6884b6c12..1f3764b48 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -67,7 +67,7 @@ RigGeometry::RigGeometry() RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) : osg::Geometry(b,copyop), _geometry(b._geometry), - _rigTransformImplementation(osg::clone(_rigTransformImplementation.get(), copyop)), + _rigTransformImplementation(osg::clone(b._rigTransformImplementation.get(), copyop)), _vertexInfluenceMap(b._vertexInfluenceMap), _needToComputeMatrix(b._needToComputeMatrix) { From 4753b8b2b9e52a1a1307eba37dab04dd959ae5f1 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:24:27 +0000 Subject: [PATCH 68/80] coding style fix --- src/osgAnimation/AnimationManagerBase.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/osgAnimation/AnimationManagerBase.cpp b/src/osgAnimation/AnimationManagerBase.cpp index d5a95b421..24209d08b 100644 --- a/src/osgAnimation/AnimationManagerBase.cpp +++ b/src/osgAnimation/AnimationManagerBase.cpp @@ -101,7 +101,8 @@ void AnimationManagerBase::registerAnimation (Animation* animation) buildTargetReference(); } -void AnimationManagerBase::removeRegisteredAnimation(Animation* animation){ +void AnimationManagerBase::removeRegisteredAnimation(Animation* animation) +{ unregisterAnimation(animation); } void AnimationManagerBase::unregisterAnimation(Animation* animation) From 252c28d5161f3d12733ab18c17717827655faea7 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:27:56 +0000 Subject: [PATCH 69/80] coding style/readability fixes --- examples/osganimationhardware/osganimationhardware.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp index a377bbd4d..f8d7be4da 100644 --- a/examples/osganimationhardware/osganimationhardware.cpp +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -79,7 +79,8 @@ struct MyRigTransformHardware : public osgAnimation::RigTransformHardware osg::ref_ptr vertexshader; osg::ref_ptr stateset = rig.getOrCreateStateSet(); - if(!CommonProgram.valid()){ + if(!CommonProgram.valid()) + { CommonProgram = new osg::Program; CommonProgram->setName("HardwareSkinning"); @@ -115,6 +116,7 @@ struct MyRigTransformHardware : public osgAnimation::RigTransformHardware } CommonProgram->addShader(vertexshader.get()); } + unsigned int nbAttribs = getNumVertexAttrib(); for (unsigned int i = 0; i < nbAttribs; i++) { @@ -144,6 +146,7 @@ struct MyRigTransformHardware : public osgAnimation::RigTransformHardware struct SetupRigGeometry : public osg::NodeVisitor { bool _hardware; + SetupRigGeometry( bool hardware = true) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _hardware(hardware) {} void apply(osg::Geode& geode) @@ -156,7 +159,8 @@ 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); @@ -266,7 +270,6 @@ int main (int argc, char* argv[]) { for (double j = 0.0; j < yChar; j++) { - osg::ref_ptr c = createCharacterInstance(root.get(), hardware); osg::MatrixTransform* tr = new osg::MatrixTransform; tr->setMatrix(osg::Matrix::translate( 2.0 * (i - xChar * .5), @@ -278,7 +281,6 @@ int main (int argc, char* argv[]) } std::cout << "created " << xChar * yChar << " instance" << std::endl; - return viewer.run(); } From ca5ce00783cad46abbc4e95e10cc7ed85a1eb5c4 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:29:45 +0000 Subject: [PATCH 70/80] coding style/readability fixes --- include/osgAnimation/AnimationManagerBase | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/osgAnimation/AnimationManagerBase b/include/osgAnimation/AnimationManagerBase index 15b4617ab..0c5b8ec36 100644 --- a/include/osgAnimation/AnimationManagerBase +++ b/include/osgAnimation/AnimationManagerBase @@ -43,9 +43,10 @@ namespace osgAnimation AnimationList& getAnimationList() { return _animations;} //uniformisation of the API - inline Animation * getRegisteredAnimation(unsigned int i){return _animations[i].get();} - inline unsigned int getNumRegisteredAnimations()const{return _animations.size();} - inline void addRegisteredAnimation(Animation* animation){ + inline Animation * getRegisteredAnimation(unsigned int i) { return _animations[i].get();} + inline unsigned int getNumRegisteredAnimations() const { return _animations.size();} + inline void addRegisteredAnimation(Animation* animation) + { _needToLink = true; _animations.push_back(animation); buildTargetReference(); @@ -59,7 +60,6 @@ namespace osgAnimation this Operation must be done each frame */ void clearTargets(); - LinkVisitor* getOrCreateLinkVisitor(); void setLinkVisitor(LinkVisitor*); From b23cc720379ec7623b5f121160e2fac62194e49a Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:33:44 +0000 Subject: [PATCH 71/80] coding style/readability fixes --- src/osgAnimation/MorphGeometry.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/osgAnimation/MorphGeometry.cpp b/src/osgAnimation/MorphGeometry.cpp index 5f499716c..964ff35a2 100644 --- a/src/osgAnimation/MorphGeometry.cpp +++ b/src/osgAnimation/MorphGeometry.cpp @@ -63,7 +63,8 @@ UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) : osg::Object(apc, copyop), osg::Callback(apc, copyop), AnimationUpdateCallback(apc, copyop) -{_targetNames=apc._targetNames; +{ + _targetNames=apc._targetNames; } UpdateMorph::UpdateMorph(const std::string& name) : AnimationUpdateCallback(name) @@ -106,8 +107,6 @@ void UpdateMorph::operator()(osg::Node* node, osg::NodeVisitor* nv) traverse(node,nv); } - - bool UpdateMorph::needLink() const { // the idea is to return true if nothing is linked From 8ee8550aac8d94f6df581844bc08f5cf84cb897f Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:42:34 +0000 Subject: [PATCH 72/80] Fix of incorrect Program assignment bug and coding style --- src/osgAnimation/MorphTransformHardware.cpp | 105 ++++++++++++-------- 1 file changed, 63 insertions(+), 42 deletions(-) diff --git a/src/osgAnimation/MorphTransformHardware.cpp b/src/osgAnimation/MorphTransformHardware.cpp index a275d5680..ad2a6859d 100644 --- a/src/osgAnimation/MorphTransformHardware.cpp +++ b/src/osgAnimation/MorphTransformHardware.cpp @@ -54,7 +54,8 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) } osg::Vec3Array* normal = dynamic_cast(morphGeometry.getNormalArray()); bool normalmorphable = morphGeometry.getMorphNormals() && normal&&(normal->getBinding()==osg::Array::BIND_PER_VERTEX); - if(!normalmorphable) { + if(!normalmorphable) + { OSG_WARN << "MorphTransformHardware::morph geometry "<( normal->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); } } + ///end check morphGeometry.setVertexArray(morphGeometry.getVertexSource()); morphGeometry.setNormalArray(morphGeometry.getNormalSource(),osg::Array::BIND_PER_VERTEX); @@ -72,25 +74,32 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) //create one TBO for all morphtargets (pack vertex/normal) osg::Vec3Array * morphTargets=new osg::Vec3Array ; MorphGeometry::MorphTargetList & morphlist=morphGeometry.getMorphTargetList(); - for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph) { + for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph) + { const osg::Geometry * morphtargetgeom= curmorph->getGeometry() ; const osg::Vec3Array *varray=(osg::Vec3Array*)morphtargetgeom->getVertexArray(); const osg::Vec3Array *narray=(osg::Vec3Array*)morphtargetgeom->getNormalArray(); - if(morphGeometry.getMethod()==MorphGeometry::RELATIVE){ - for(unsigned int i=0; igetNumElements(); ++i) { + if(morphGeometry.getMethod()==MorphGeometry::RELATIVE) + { + for(unsigned int i=0; igetNumElements(); ++i) + { morphTargets->push_back( (*varray)[i]); morphTargets->push_back( (*narray)[i]); } - }else{ + } + else + { //convert to RELATIVE as it involve less math in the VS than NORMALIZED const osg::Vec3Array *ovarray=(osg::Vec3Array*)morphGeometry.getVertexArray(); const osg::Vec3Array *onarray=(osg::Vec3Array*)morphGeometry.getNormalArray(); - for(unsigned int i=0; igetNumElements(); ++i) { + for(unsigned int i=0; igetNumElements(); ++i) + { morphTargets->push_back( (*varray)[i]- (*ovarray)[i] ); morphTargets->push_back( (*narray)[i]- (*onarray)[i] ); } } } + osg::TextureBuffer * morphTargetsTBO=new osg::TextureBuffer(); morphTargetsTBO->setBufferData(morphTargets); morphTargetsTBO->setInternalFormat( GL_RGB32F_ARB ); @@ -110,56 +119,66 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) 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){ + { + if(program->getShader(i)->getType()==osg::Shader::VERTEX) + { // vertexshader=program->getShader(i); program->removeShader(vertexshader); } - }else { - - } program = new osg::Program; + } + } + + if (!program) + { + program = new osg::Program; + } + program->setName("HardwareMorphing"); //set default source if _shader is not user setted - if (!vertexshader.valid()){ + if (!vertexshader.valid()) + { if (!_shader.valid()) vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"morphing.vert"); - else vertexshader=_shader; + else + vertexshader=_shader; } - - if (!vertexshader.valid()) { + 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_MORPHWEIGHT"); - std::size_t start = str.find(toreplace); - if (std::string::npos == start){ - ///perhaps remanance from previous init (if saved after init) so reload shader - vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"morphing.vert"); - if (!vertexshader.valid()) { - OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; - return false; + std::string str = vertexshader->getShaderSource(); + std::string toreplace = std::string("MAX_MORPHWEIGHT"); + std::size_t start = str.find(toreplace); + if (std::string::npos == start) + { + // perhaps remanance from previous init (if saved after init) so reload shader + vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"morphing.vert"); + if (!vertexshader.valid()) + { + OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + str = vertexshader->getShaderSource(); + start = str.find(toreplace); } - str = vertexshader->getShaderSource(); - start = str.find(toreplace); + if (std::string::npos != start) + { + std::stringstream ss; + ss << _uniformTargetsWeight->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + vertexshader->setShaderSource(str); + } + else + { + OSG_WARN << "MAX_MORPHWEIGHT not found in Shader! " << str << std::endl; + } + OSG_INFO << "Shader " << str << std::endl; } - if (std::string::npos != start) { - std::stringstream ss; - ss << _uniformTargetsWeight->getNumElements(); - str.replace(start, toreplace.size(), ss.str()); - vertexshader->setShaderSource(str); - } - else - { - OSG_WARN << "MAX_MORPHWEIGHT not found in Shader! " << str << std::endl; - } - OSG_INFO << "Shader " << str << std::endl; - } - - program->addShader(vertexshader.get()); //morphGeometry.setStateSet((osg::StateSet *) osg::CopyOp()(source.getOrCreateStateSet())); @@ -174,18 +193,20 @@ bool MorphTransformHardware::init(MorphGeometry& morphGeometry) _needInit = false; return true; } + void MorphTransformHardware::operator()(MorphGeometry& geom) { - if (_needInit) - if (!init(geom)) - return; + if (_needInit && !init(geom)) return; + 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 a5f6e4b0c43e1a795b37a6b1a6b13c697d61a101 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:45:55 +0000 Subject: [PATCH 73/80] Small readability improvements --- include/osgAnimation/VertexInfluence | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index 256d9c198..1bf1e6e01 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -65,7 +65,7 @@ namespace osgAnimation void cullInfluenceCountPerVertex(unsigned int maxnumbonepervertex, float minweight=0, bool renormalize=true); //compute PerVertexInfluenceList - void computePerVertexInfluenceList(std::vector& perVertexInfluenceList, 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 @@ -77,7 +77,7 @@ namespace osgAnimation }; /// compute the minimal VertexGroup Set in which vertices shares the same influence set - void computeMinimalVertexGroupList(std::vector&uniqVertexGroupList, unsigned int numvert)const; + void computeMinimalVertexGroupList(std::vector&uniqVertexGroupList, unsigned int numvert) const; //Experimental removal of unexpressed bone from the skeleton void removeUnexpressedBones(Skeleton &skel) const; From f59efe0bfe0f15b9748530cff36df0730dd5b33e Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:46:48 +0000 Subject: [PATCH 74/80] Code readability improvement --- src/osgAnimation/AnimationManagerBase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/osgAnimation/AnimationManagerBase.cpp b/src/osgAnimation/AnimationManagerBase.cpp index 24209d08b..237b44203 100644 --- a/src/osgAnimation/AnimationManagerBase.cpp +++ b/src/osgAnimation/AnimationManagerBase.cpp @@ -105,6 +105,7 @@ void AnimationManagerBase::removeRegisteredAnimation(Animation* animation) { unregisterAnimation(animation); } + void AnimationManagerBase::unregisterAnimation(Animation* animation) { AnimationList::iterator it = std::find(_animations.begin(), _animations.end(), animation); From 8e55ed59235cec296d2690ce54795b1a185d7684 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:54:28 +0000 Subject: [PATCH 75/80] Code readability improvements --- src/osgAnimation/RigTransformSoftware.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp index 35993817a..56f6c6477 100644 --- a/src/osgAnimation/RigTransformSoftware.cpp +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -91,9 +91,12 @@ void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig ) vg.getVertices().push_back(vertexID); } } + _uniqVertexGroupList.reserve(unifyBuffer.size()); for (UnifyBoneGroup::const_iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) + { _uniqVertexGroupList.push_back(it->second); + } OSG_INFO << "uniq groups " << _uniqVertexGroupList.size() << " for " << rig.getName() << std::endl; } @@ -144,6 +147,7 @@ bool RigTransformSoftware::init(RigGeometry&rig) if(!rig.getSkeleton()) return false; + ///get bonemap from skeleton BoneMapVisitor mapVisitor; rig.getSkeleton()->accept(mapVisitor); @@ -175,6 +179,7 @@ bool RigTransformSoftware::init(RigGeometry&rig) localid2bone.push_back(0); continue; } + Bone* bone = bmit->second.get(); localid2bone.push_back(bone); } @@ -226,15 +231,14 @@ void RigTransformSoftware::VertexGroup::normalize() void RigTransformSoftware::operator()(RigGeometry& geom) { - if (_needInit) - if (!init(geom)) - return; + if (_needInit && !init(geom)) return; if (!geom.getSourceGeometry()) { OSG_WARN << this << " RigTransformSoftware no source geometry found on RigGeometry" << std::endl; return; } + osg::Geometry& source = *geom.getSourceGeometry(); osg::Geometry& destination = geom; @@ -247,11 +251,9 @@ void RigTransformSoftware::operator()(RigGeometry& geom) compute(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry(), &positionSrc->front(), - &positionDst->front()); + &positionDst->front()); positionDst->dirty(); - - if (normalSrc ) { computeNormal(geom.getMatrixFromSkeletonToGeometry(), From 4977939c054a93e1f90c7f7e2fa447965e21e2e0 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 12:58:52 +0000 Subject: [PATCH 76/80] Code readability improvements --- src/osgAnimation/VertexInfluence.cpp | 57 ++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index 1f77be6aa..e2d9482e8 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -50,6 +50,7 @@ void VertexInfluenceMap::normalize(unsigned int numvert) } } + unsigned int vertid = 0; for(std::vector::iterator itvert = localstore.begin(); itvert != localstore.end(); @@ -64,7 +65,9 @@ void VertexInfluenceMap::normalize(unsigned int numvert) { float mult = 1.0/weights.first; for (std::vector::iterator itf = weights.second.begin(); itf != weights.second.end(); ++itf) + { **itf *= mult; + } } } @@ -86,7 +89,10 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert { OSG_WARN << "VertexInfluenceSet::cullInfluenceCountPerVertex warning vertex " << inf.first << " is not assigned to a bone" << std::endl; } - else if(inf.second>minweight)tempVec2Bones[inf.first].insert(BoneWeight(bonename, inf.second)); + else if(inf.second>minweight) + { + tempVec2Bones[inf.first].insert(BoneWeight(bonename, inf.second)); + } } } this->clear(); @@ -99,7 +105,10 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert if(renormalize) { for(BoneWeightOrdered::iterator bwit = bwset.begin(); bwit != bwset.end(); ++bwit) + { sum += bwit->second; + } + if(sum > 1e-4) { sum = 1.0f/sum; @@ -119,7 +128,6 @@ void VertexInfluenceMap::cullInfluenceCountPerVertex(unsigned int numbonepervert inf.push_back(VertexIndexWeight(mapit->first,bwit->second)); inf.setName(bwit->first); } - } } } @@ -134,6 +142,7 @@ void VertexInfluenceMap::computePerVertexInfluenceList(std::vector { - bool operator()(const BoneWeight& b0, - const BoneWeight& b1) const + bool operator()(const BoneWeight& b0, const BoneWeight& b1) const { if (b0.first < b1.first) return true; else if (b0.first > b1.first) return false; + return (b0.second < b1.second); } }; @@ -193,16 +202,22 @@ void VertexInfluenceMap::computeMinimalVertexGroupList(std::vector& 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()) + { unifyBuffer[boneweightlist].setBoneWeights(boneweightlist); + } + unifyBuffer[boneweightlist].vertIDs().push_back(vertexID); } + if(vertex2Bones.size() == unifyBuffer.size()) { OSG_WARN << "VertexInfluenceMap::computeMinimalVertexGroupList is useless no duplicate VertexGroup" << std::endl; } + uniqVertexGroupList.reserve(unifyBuffer.size()); for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it) { @@ -234,10 +249,13 @@ void CollectRigVisitor::apply(osg::Geometry& node) _map.push_back(rig); } -bool recursiveisUsefull( Bone* bone, std::set foundnames) { - for(unsigned int i=0; igetNumChildren(); ++i) { +bool recursiveisUsefull( Bone* bone, std::set foundnames) +{ + for(unsigned int i=0; igetNumChildren(); ++i) + { Bone* child = dynamic_cast< Bone* >(bone->getChild(i)); - if(child){ + if(child) + { if( foundnames.find(child->getName()) != foundnames.end() ) return true; if( recursiveisUsefull(child,foundnames) ) @@ -262,16 +280,20 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const Bone* child, *par; std::set usebones; - for(RigList::iterator rigit = rigs.begin(); rigit != rigs.end(); ++rigit) { + for(RigList::iterator rigit = rigs.begin(); rigit != rigs.end(); ++rigit) + { for(VertexInfluenceMap::iterator mapit = (*rigit)->getInfluenceMap()->begin(); - mapit != (*rigit)->getInfluenceMap()->end(); - ++mapit) { + mapit != (*rigit)->getInfluenceMap()->end(); + ++mapit) + { usebones.insert((*mapit).first); } } - for(BoneMap::iterator bmit = boneMap.begin(); bmit != boneMap.end();) { - if(usebones.find(bmit->second->getName()) == usebones.end()) { + for(BoneMap::iterator bmit = boneMap.begin(); bmit != boneMap.end();) + { + if(usebones.find(bmit->second->getName()) == usebones.end()) + { if( !(par = bmit->second->getBoneParent()) ) { ++bmit; @@ -280,7 +302,8 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const Bone * bone2rm = bmit->second.get(); - if( recursiveisUsefull(bone2rm,usebones)) { + if( recursiveisUsefull(bone2rm,usebones)) + { ++bmit; continue; } @@ -301,7 +324,9 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const } } for(unsigned int i=0; iremoveChild(nodes[i]); + } par->removeChild(bone2rm); ///rebuild bonemap after bone removal @@ -311,8 +336,10 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const bmit = boneMap.begin(); } - else ++bmit; + else + { + ++bmit; + } } OSG_WARN<<"Number of bone removed "< Date: Sat, 11 Nov 2017 13:00:56 +0000 Subject: [PATCH 77/80] Code readability improvements --- src/osgAnimation/VertexInfluence.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index e2d9482e8..75a7b22a6 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -47,14 +47,13 @@ void VertexInfluenceMap::normalize(unsigned int numvert) VertexIndexWeight& 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) + itvert != localstore.end(); + ++itvert, ++vertid) { PerVertWeights & weights = *itvert; if(weights.first< 1e-4) @@ -317,12 +316,14 @@ void VertexInfluenceMap::removeUnexpressedBones(Skeleton &skel) const { if( (child = dynamic_cast(bone2rm->getChild(numchild))) ) { - if(par!=child &&child!=bone2rm) { + if(par!=child &&child!=bone2rm) + { par->addChild(child); nodes.push_back(child); } } } + for(unsigned int i=0; iremoveChild(nodes[i]); From 3567e3100944c233b2f14d42baae1272be3295f6 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 13:04:34 +0000 Subject: [PATCH 78/80] Added versioning to the new serialization additions --- .../serializers/osgAnimation/AnimationManagerBase.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp b/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp index 49a788fc5..65ec91c3c 100644 --- a/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp +++ b/src/osgWrappers/serializers/osgAnimation/AnimationManagerBase.cpp @@ -77,9 +77,13 @@ REGISTER_OBJECT_WRAPPER( osgAnimation_AnimationManagerBase, { ADD_USER_SERIALIZER( Animations ); // _animations ADD_BOOL_SERIALIZER( AutomaticLink, true ); // _automaticLink + + { + UPDATE_TO_VERSION_SCOPED( 152 ) - ADD_METHOD_OBJECT( "getRegisteredAnimation", osgAnimation_AnimationManagerBasegetAnimation ); - ADD_METHOD_OBJECT( "getNumRegisteredAnimations", osgAnimation_AnimationManagerBasegetnumAnimations ); + ADD_METHOD_OBJECT( "getRegisteredAnimation", osgAnimation_AnimationManagerBasegetAnimation ); + ADD_METHOD_OBJECT( "getNumRegisteredAnimations", osgAnimation_AnimationManagerBasegetnumAnimations ); + } } } #undef OBJECT_CAST From 729680714c538c79a9dd034bb8e138a44d3b21b2 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 13:08:42 +0000 Subject: [PATCH 79/80] Readbility improvements and updating version to 152 --- .../serializers/osgAnimation/RigTransform.cpp | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp index 5b69cdcd1..4eb5f3341 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp @@ -7,52 +7,64 @@ #include #include -namespace wrap_osgAnimationRigTransform{ - REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransform, +namespace wrap_osgAnimationRigTransform +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransform, NULL, osgAnimation::RigTransform, "osg::Object osgAnimation::RigTransform" ){} } -namespace wrap_osgAnimationRigTransformSoftWare{ - REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformSoftware, + +namespace wrap_osgAnimationRigTransformSoftWare +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformSoftware, new osgAnimation::RigTransformSoftware, osgAnimation::RigTransformSoftware, "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformSoftware" ){} } -namespace wrap_osgAnimationRigTransformHardWare{ - REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformHardware, + +namespace wrap_osgAnimationRigTransformHardWare +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_RigTransformHardware, new osgAnimation::RigTransformHardware, osgAnimation::RigTransformHardware, - "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformHardware" ){ - { - UPDATE_TO_VERSION_SCOPED(150) - ADD_OBJECT_SERIALIZER(Shader, osg::Shader, NULL); - ADD_UINT_SERIALIZER(FirstVertexAttributeTarget, RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED); - } - } + "osg::Object osgAnimation::RigTransform osgAnimation::RigTransformHardware" ) + { + { + UPDATE_TO_VERSION_SCOPED(152) + ADD_OBJECT_SERIALIZER(Shader, osg::Shader, NULL); + ADD_UINT_SERIALIZER(FirstVertexAttributeTarget, RIGTRANSHW_DEFAULT_FIRST_VERTATTRIB_TARGETTED); + } + } } -namespace wrap_osgAnimationMorphTransform{ - REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransform, +namespace wrap_osgAnimationMorphTransform +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransform, NULL, osgAnimation::MorphTransform, "osg::Object osgAnimation::MorphTransform" ){} } -namespace wrap_osgAnimationMorphTransformSoftWare{ - REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformSoftware, + +namespace wrap_osgAnimationMorphTransformSoftWare +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformSoftware, new osgAnimation::MorphTransformSoftware, osgAnimation::MorphTransformSoftware, "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformSoftware" ){} } -namespace wrap_osgAnimationMorphTransformHardware{ - REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformHardware, + +namespace wrap_osgAnimationMorphTransformHardware +{ + REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformHardware, new osgAnimation::MorphTransformHardware, osgAnimation::MorphTransformHardware, - "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware" ){ - { - UPDATE_TO_VERSION_SCOPED(150) - ADD_OBJECT_SERIALIZER(Shader, osg::Shader, NULL); - ADD_UINT_SERIALIZER(ReservedTextureUnit, MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT); - } - } + "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware" + { + { + UPDATE_TO_VERSION_SCOPED(152) + ADD_OBJECT_SERIALIZER(Shader, osg::Shader, NULL); + ADD_UINT_SERIALIZER(ReservedTextureUnit, MORPHTRANSHW_DEFAULTMORPHTEXTUREUNIT); + } + } } From 8d5a9e84fc0b562b5abab23ac68df56d605e4c88 Mon Sep 17 00:00:00 2001 From: OpenSceneGraph git repository Date: Sat, 11 Nov 2017 13:27:43 +0000 Subject: [PATCH 80/80] Build fix --- src/osgWrappers/serializers/osgAnimation/RigTransform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp index 4eb5f3341..61d4fbd88 100644 --- a/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp +++ b/src/osgWrappers/serializers/osgAnimation/RigTransform.cpp @@ -59,7 +59,7 @@ namespace wrap_osgAnimationMorphTransformHardware REGISTER_OBJECT_WRAPPER( osgAnimation_MorphTransformHardware, new osgAnimation::MorphTransformHardware, osgAnimation::MorphTransformHardware, - "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware" + "osg::Object osgAnimation::MorphTransform osgAnimation::MorphTransformHardware") { { UPDATE_TO_VERSION_SCOPED(152)