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;