From da1d2b67f7b21ce976538acd49f129da805ea74a Mon Sep 17 00:00:00 2001 From: Julien Valentin Date: Mon, 28 Aug 2017 16:46:01 +0200 Subject: [PATCH] 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(); - } -}