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 ) {