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;
|
osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << geom->getName() << " )" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
geom->setSkeleton(finder._root.get());
|
|
||||||
|
|
||||||
geom->getRigTransformImplementation()->prepareData(*geom);
|
geom->getRigTransformImplementation()->prepareData(*geom);
|
||||||
|
geom->setSkeleton(finder._root.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!geom->getSkeleton())
|
if(!geom->getSkeleton())
|
||||||
|
@ -89,6 +89,7 @@ namespace osgAnimation
|
|||||||
//on first update
|
//on first update
|
||||||
virtual bool init(RigGeometry& );
|
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
|
//to call when a skeleton is reacheable from the rig to prepare technic data
|
||||||
virtual bool prepareData(RigGeometry&);
|
virtual bool prepareData(RigGeometry&);
|
||||||
|
|
||||||
class BonePtrWeight: std::pair< osg::observer_ptr< Bone >, float>
|
typedef std::pair<unsigned int, float> LocalBoneIDWeight;
|
||||||
|
class BonePtrWeight: LocalBoneIDWeight
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BonePtrWeight(Bone*bone, float weight) :std::pair< osg::observer_ptr< Bone >, float>(bone,weight) {}
|
BonePtrWeight(unsigned int id,float weight, Bone*bone=0 ): LocalBoneIDWeight(id,weight), _boneptr(bone){}
|
||||||
BonePtrWeight(const BonePtrWeight &bw2) : std::pair< osg::observer_ptr< Bone >, float>(bw2.first.get(),bw2.getWeight()) {}
|
BonePtrWeight(const BonePtrWeight &bw2): LocalBoneIDWeight(bw2.getBoneID(),bw2.getWeight()), _boneptr(bw2._boneptr.get()){}
|
||||||
|
|
||||||
inline const Bone * getBonePtr() const {return first.get();}
|
|
||||||
inline void setBonePtr(Bone*b){first=b;}
|
|
||||||
inline const float & getWeight() const {return second;}
|
inline const float & getWeight() const {return second;}
|
||||||
inline void setWeight(float b) {second=b;}
|
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{
|
inline bool operator<(const BonePtrWeight &b1) const{
|
||||||
if (second > b1.second)return true;
|
if (second > b1.second)return true;
|
||||||
if (second < b1.second)return false;
|
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;
|
typedef std::vector<BonePtrWeight> BonePtrWeightList;
|
||||||
|
|
||||||
/// map a set of boneinfluence to a list of vertex indices sharing this set
|
/// map a set of boneinfluence to a list of vertex indices sharing this set
|
||||||
@ -144,7 +150,6 @@ namespace osgAnimation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class V>
|
template <class V>
|
||||||
inline void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
|
inline void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
|
||||||
{
|
{
|
||||||
@ -166,12 +171,14 @@ namespace osgAnimation
|
|||||||
|
|
||||||
bool _needInit;
|
bool _needInit;
|
||||||
|
|
||||||
|
virtual bool init(RigGeometry&);
|
||||||
|
|
||||||
std::map<std::string,bool> _invalidInfluence;
|
std::map<std::string,bool> _invalidInfluence;
|
||||||
|
|
||||||
typedef std::vector<VertexGroup> VertexGroupList;
|
typedef std::vector<VertexGroup> VertexGroupList;
|
||||||
|
|
||||||
VertexGroupList _uniqVertexGroupList;
|
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
|
///create normalized a set of Vertex Attribs given a PerVertexInfList and return the max num bone per vertex
|
||||||
unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences,
|
unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences,
|
||||||
RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays){
|
RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays)
|
||||||
|
{
|
||||||
short boneIndexInVec4;
|
short boneIndexInVec4;
|
||||||
unsigned int vertid = 0,
|
unsigned int vertid = 0,
|
||||||
boneIndexInList;
|
boneIndexInList;
|
||||||
IndexWeightList::size_type maxBonePerVertex = 0;
|
IndexWeightList::size_type maxBonePerVertex = 0;
|
||||||
///build vertex attrib arrays
|
///build vertex attrib arrays
|
||||||
//get maxBonePerVertex
|
//get maxBonePerVertex
|
||||||
@ -110,7 +111,7 @@ unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences
|
|||||||
|
|
||||||
if(sum< 1e-4)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -145,22 +146,128 @@ unsigned int createVertexAttribList(const PerVertexInfList & perVertexInfluences
|
|||||||
|
|
||||||
bool RigTransformHardware::prepareData(RigGeometry& rig)
|
bool RigTransformHardware::prepareData(RigGeometry& rig)
|
||||||
{
|
{
|
||||||
if(!rig.getSkeleton() && !rig.getParents().empty())
|
_nbVertices = rig.getSourceGeometry()->getVertexArray()->getNumElements();
|
||||||
{
|
const VertexInfluenceMap &vertexInfluenceMap = *rig.getInfluenceMap();
|
||||||
RigGeometry::FindNearestParentSkeleton finder;
|
_perVertexInfluences.resize(_nbVertices);
|
||||||
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())
|
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;
|
const VertexIndexWeight& iw = *infit;
|
||||||
return false;
|
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())
|
if(!rig.getSkeleton())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BoneMapVisitor mapVisitor;
|
BoneMapVisitor mapVisitor;
|
||||||
rig.getSkeleton()->accept(mapVisitor);
|
rig.getSkeleton()->accept(mapVisitor);
|
||||||
BoneMap boneMap = mapVisitor.getBoneMap();
|
BoneMap boneMap = mapVisitor.getBoneMap();
|
||||||
@ -179,178 +286,82 @@ bool RigTransformHardware::prepareData(RigGeometry& rig)
|
|||||||
// copy shallow from source geometry to rig
|
// copy shallow from source geometry to rig
|
||||||
rig.copyFrom(source);
|
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();
|
||||||
|
|
||||||
|
//grab geom source program and vertex shader if _shader is not setted
|
||||||
bool RigTransformHardware::buildPalette(const BoneMap&boneMap,const RigGeometry&rig)
|
if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM)))
|
||||||
{
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
const IndexWeightList& boneinflist = boneinflistit->second;
|
for(unsigned int i=0; i<program->getNumShaders(); ++i)
|
||||||
const std::string& bonename = boneinflistit->first;
|
if(program->getShader(i)->getType()==osg::Shader::VERTEX)
|
||||||
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
|
|
||||||
{
|
{
|
||||||
iwlist.push_back(VertexIndexWeight(paletteindex,weight));
|
vertexshader=program->getShader(i);
|
||||||
|
program->removeShader(vertexshader);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
OSG_WARN << "RigTransformHardware::buildPalette Bone " << bonename << " has a weight " << weight << " for vertex " << index << " this bone will not be in the palette" << std::endl;
|
{
|
||||||
}
|
program = new osg::Program;
|
||||||
|
program->setName("HardwareSkinning");
|
||||||
}
|
}
|
||||||
OSG_INFO << "RigTransformHardware::buildPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl;
|
//set default source if _shader is not user setted
|
||||||
|
if (!vertexshader.valid())
|
||||||
for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it)
|
{
|
||||||
{
|
if (!_shader.valid())
|
||||||
OSG_INFO << "RigTransformHardware::buildPalette Bone " << it->first << " is used " << it->second << " times" << std::endl;
|
vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert");
|
||||||
}
|
else vertexshader=_shader;
|
||||||
|
|
||||||
OSG_INFO << "RigTransformHardware::buildPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vertexshader.valid())
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Program> program ;
|
OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl;
|
||||||
osg::ref_ptr<osg::Shader> vertexshader;
|
return false;
|
||||||
osg::ref_ptr<osg::StateSet> stateset = rig.getOrCreateStateSet();
|
}
|
||||||
|
|
||||||
//grab geom source program and vertex shader if _shader is not setted
|
// replace max matrix by the value from uniform
|
||||||
if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM)))
|
{
|
||||||
{
|
std::string str = vertexshader->getShaderSource();
|
||||||
for(unsigned int i=0; i<program->getNumShaders(); ++i)
|
std::string toreplace = std::string("MAX_MATRIX");
|
||||||
if(program->getShader(i)->getType()==osg::Shader::VERTEX)
|
std::size_t start = str.find(toreplace);
|
||||||
{
|
if (std::string::npos != start)
|
||||||
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++)
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "boneWeight" << i;
|
ss << getMatrixPaletteUniform()->getNumElements();
|
||||||
program->addBindAttribLocation(ss.str(), _minAttribIndex + i);
|
str.replace(start, toreplace.size(), ss.str());
|
||||||
rig.setVertexAttribArray(_minAttribIndex + i, getVertexAttrib(i));
|
vertexshader->setShaderSource(str);
|
||||||
OSG_INFO << "set vertex attrib " << ss.str() << std::endl;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
program->addShader(vertexshader.get());
|
{
|
||||||
|
OSG_WARN<< "MAX_MATRIX not found in Shader! " << str << std::endl;
|
||||||
stateset->removeUniform("nbBonesPerVertex");
|
}
|
||||||
stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex));
|
OSG_INFO << "Shader " << str << std::endl;
|
||||||
|
|
||||||
stateset->removeUniform("matrixPalette");
|
|
||||||
stateset->addUniform(_uniformMatrixPalette);
|
|
||||||
|
|
||||||
stateset->setAttribute(program.get());
|
|
||||||
|
|
||||||
_needInit = false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
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)
|
void RigTransformHardware::operator()(RigGeometry& geom)
|
||||||
{
|
{
|
||||||
if (_needInit)
|
if (_needInit)
|
||||||
|
@ -38,39 +38,31 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const
|
|||||||
|
|
||||||
typedef std::vector<RigTransformSoftware::BonePtrWeight> BonePtrWeightList;
|
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>
|
///1 Create Index2Vec<BoneWeight>
|
||||||
const VertexInfluenceMap &vertexInfluenceMap=*rig.getInfluenceMap();
|
const VertexInfluenceMap &vertexInfluenceMap=*rig.getInfluenceMap();
|
||||||
std::vector<BonePtrWeightList> perVertexInfluences;
|
std::vector<BonePtrWeightList> perVertexInfluences;
|
||||||
perVertexInfluences.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements());
|
perVertexInfluences.resize(rig.getSourceGeometry()->getVertexArray()->getNumElements());
|
||||||
|
|
||||||
|
unsigned int vimapBoneID = 0;
|
||||||
for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin();
|
for (osgAnimation::VertexInfluenceMap::const_iterator perBoneinfit = vertexInfluenceMap.begin();
|
||||||
perBoneinfit != vertexInfluenceMap.end();
|
perBoneinfit != vertexInfluenceMap.end();
|
||||||
++perBoneinfit)
|
++perBoneinfit,++vimapBoneID)
|
||||||
{
|
{
|
||||||
const IndexWeightList& inflist = perBoneinfit->second;
|
const IndexWeightList& inflist = perBoneinfit->second;
|
||||||
const std::string& bonename = perBoneinfit->first;
|
const std::string& bonename = perBoneinfit->first;
|
||||||
|
|
||||||
if (bonename.empty()) {
|
if (bonename.empty())
|
||||||
|
{
|
||||||
OSG_WARN << "RigTransformSoftware::VertexInfluenceMap contains unamed bone IndexWeightList" << std::endl;
|
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)
|
for(IndexWeightList::const_iterator infit=inflist.begin(); infit!=inflist.end(); ++infit)
|
||||||
{
|
{
|
||||||
const VertexIndexWeight &iw = *infit;
|
const VertexIndexWeight &iw = *infit;
|
||||||
const unsigned int &index = iw.first;
|
const unsigned int &index = iw.first;
|
||||||
float weight = iw.second;
|
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;
|
BonePtrWeightList& bones = *it;
|
||||||
float sum = 0;
|
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();
|
sum += bwit->getWeight();
|
||||||
if (sum < 1e-4)
|
if (sum < 1e-4)
|
||||||
{
|
{
|
||||||
@ -89,7 +81,7 @@ void RigTransformSoftware::buildMinimumUpdateSet( const BoneMap&boneMap, const R
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
float mult = 1.0/sum;
|
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);
|
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;
|
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
|
///set geom as it source
|
||||||
if (rig.getSourceGeometry())
|
if (rig.getSourceGeometry())
|
||||||
rig.copyFrom(*rig.getSourceGeometry());
|
rig.copyFrom(*rig.getSourceGeometry());
|
||||||
|
|
||||||
|
|
||||||
osg::Vec3Array* normalSrc = dynamic_cast<osg::Vec3Array*>(rig.getSourceGeometry()->getNormalArray());
|
osg::Vec3Array* normalSrc = dynamic_cast<osg::Vec3Array*>(rig.getSourceGeometry()->getNormalArray());
|
||||||
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(rig.getSourceGeometry()->getVertexArray());
|
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(rig.getSourceGeometry()->getVertexArray());
|
||||||
|
|
||||||
@ -169,24 +137,92 @@ bool RigTransformSoftware::prepareData(RigGeometry&rig) {
|
|||||||
*positionDst=*positionSrc;
|
*positionDst=*positionSrc;
|
||||||
positionDst->setDataVariance(osg::Object::DYNAMIC);
|
positionDst->setDataVariance(osg::Object::DYNAMIC);
|
||||||
|
|
||||||
if(normalSrc) {
|
if(normalSrc)
|
||||||
|
{
|
||||||
osg::Vec3Array* normalDst =new osg::Vec3Array;
|
osg::Vec3Array* normalDst =new osg::Vec3Array;
|
||||||
*normalDst=*normalSrc;
|
*normalDst=*normalSrc;
|
||||||
rig.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX);
|
rig.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX);
|
||||||
normalDst->setDataVariance(osg::Object::DYNAMIC);
|
normalDst->setDataVariance(osg::Object::DYNAMIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
_needInit = false;
|
/// build minimal set of VertexGroup
|
||||||
|
buildMinimumUpdateSet(rig);
|
||||||
|
|
||||||
return true;
|
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)
|
void RigTransformSoftware::operator()(RigGeometry& geom)
|
||||||
{
|
{
|
||||||
if (_needInit)
|
if (_needInit)
|
||||||
if (!prepareData(geom))
|
if (!init(geom))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!geom.getSourceGeometry()) {
|
if (!geom.getSourceGeometry())
|
||||||
|
{
|
||||||
OSG_WARN << this << " RigTransformSoftware no source geometry found on RigGeometry" << std::endl;
|
OSG_WARN << this << " RigTransformSoftware no source geometry found on RigGeometry" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -209,11 +245,11 @@ void RigTransformSoftware::operator()(RigGeometry& geom)
|
|||||||
|
|
||||||
if (normalSrc )
|
if (normalSrc )
|
||||||
{
|
{
|
||||||
computeNormal<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
|
computeNormal<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
|
||||||
geom.getInvMatrixFromSkeletonToGeometry(),
|
geom.getInvMatrixFromSkeletonToGeometry(),
|
||||||
&normalSrc->front(),
|
&normalSrc->front(),
|
||||||
&normalDst->front());
|
&normalDst->front());
|
||||||
normalDst->dirty();
|
normalDst->dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user