make preparedata skeleton independant (as it was with the Rig::buildInfluenceSet)
no more divergence with master i think
This commit is contained in:
parent
381c2150d4
commit
041a2a6e72
@ -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())
|
||||
|
@ -89,6 +89,7 @@ namespace osgAnimation
|
||||
//on first update
|
||||
virtual bool init(RigGeometry& );
|
||||
|
||||
std::vector<IndexWeightList> _perVertexInfluences;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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<unsigned int, float> 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<BonePtrWeight> BonePtrWeightList;
|
||||
|
||||
/// map a set of boneinfluence to a list of vertex indices sharing this set
|
||||
@ -144,7 +150,6 @@ namespace osgAnimation
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class V>
|
||||
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<std::string,bool> _invalidInfluence;
|
||||
|
||||
typedef std::vector<VertexGroup> VertexGroupList;
|
||||
|
||||
VertexGroupList _uniqVertexGroupList;
|
||||
void buildMinimumUpdateSet(const BoneMap&boneMap,const RigGeometry&rig );
|
||||
|
||||
void buildMinimumUpdateSet(const RigGeometry&rig );
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -75,10 +75,11 @@ typedef std::vector<std::vector<VertexIndexWeight> > 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: " <<vertid<< std::endl;
|
||||
OSG_WARN << "RigTransformHardware::createVertexAttribList Warning: vertex with zero sum weights: " <<vertid<< std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@ -145,22 +146,128 @@ unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences
|
||||
|
||||
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);
|
||||
_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<std::string, int> 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<int> 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<IndexWeightList>::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<osg::Program> program ;
|
||||
osg::ref_ptr<osg::Shader> vertexshader;
|
||||
osg::ref_ptr<osg::StateSet> stateset = rig.getOrCreateStateSet();
|
||||
|
||||
|
||||
bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry&rig)
|
||||
{
|
||||
|
||||
typedef std::map<std::string, int> 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<IndexWeightList > 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; i<program->getNumShaders(); ++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<osg::Program> program ;
|
||||
osg::ref_ptr<osg::Shader> vertexshader;
|
||||
osg::ref_ptr<osg::StateSet> 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; i<program->getNumShaders(); ++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)
|
||||
|
@ -38,39 +38,31 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const
|
||||
|
||||
typedef std::vector<RigTransformSoftware::BonePtrWeight> BonePtrWeightList;
|
||||
|
||||
void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const RigGeometry&rig ){
|
||||
|
||||
void RigTransformSoftware::buildMinimumUpdateSet( const RigGeometry&rig )
|
||||
{
|
||||
///1 Create Index2Vec<BoneWeight>
|
||||
const VertexInfluenceMap &vertexInfluenceMap=*rig.getInfluenceMap();
|
||||
std::vector<BonePtrWeightList> 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<osg::Vec3Array*>(rig.getSourceGeometry()->getNormalArray());
|
||||
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(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<Bone*> 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<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
|
||||
geom.getInvMatrixFromSkeletonToGeometry(),
|
||||
&normalSrc->front(),
|
||||
&normalDst->front());
|
||||
normalDst->dirty();
|
||||
computeNormal<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
|
||||
geom.getInvMatrixFromSkeletonToGeometry(),
|
||||
&normalSrc->front(),
|
||||
&normalDst->front());
|
||||
normalDst->dirty();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user