refactoring and fixes
only change in design: decouplage between MorphGeometry and MorphTransform technique no real change in behavior (i hope)
This commit is contained in:
parent
c89b08ea1f
commit
32aaeccee1
@ -42,6 +42,16 @@ namespace osgAnimation
|
|||||||
const AnimationList& getAnimationList() const { return _animations;}
|
const AnimationList& getAnimationList() const { return _animations;}
|
||||||
AnimationList& getAnimationList() { return _animations;}
|
AnimationList& getAnimationList() { return _animations;}
|
||||||
|
|
||||||
|
//uniformisation of the API
|
||||||
|
inline Animation * getRegisteredAnimation(unsigned int i){return _animations[i].get();}
|
||||||
|
inline unsigned int getNumRegisteredAnimations()const{return _animations.size();}
|
||||||
|
inline void addRegisteredAnimation(Animation* animation){
|
||||||
|
_needToLink = true;
|
||||||
|
_animations.push_back(animation);
|
||||||
|
buildTargetReference();
|
||||||
|
}
|
||||||
|
void removeRegisteredAnimation(Animation* animation);
|
||||||
|
|
||||||
/** Callback method called by the NodeVisitor when visiting a node.*/
|
/** Callback method called by the NodeVisitor when visiting a node.*/
|
||||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <osgAnimation/Export>
|
#include <osgAnimation/Export>
|
||||||
#include <osgAnimation/AnimationUpdateCallback>
|
#include <osgAnimation/AnimationUpdateCallback>
|
||||||
|
#include <osgAnimation/MorphTransformSoftware>
|
||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -59,7 +60,10 @@ namespace osgAnimation
|
|||||||
virtual const char* libraryName() const { return "osgAnimation"; }
|
virtual const char* libraryName() const { return "osgAnimation"; }
|
||||||
virtual const char* className() const { return "MorphGeometry"; }
|
virtual const char* className() const { return "MorphGeometry"; }
|
||||||
|
|
||||||
virtual void transformSoftwareMethod();
|
// set implementation of rig method
|
||||||
|
void setMorphTransformImplementation(MorphTransform*);
|
||||||
|
MorphTransform* getMorphTransformImplementation();
|
||||||
|
const MorphTransform* getMorphTransformImplementation() const { return _rigTransformImplementation.get(); }
|
||||||
|
|
||||||
/** Set the morphing method. */
|
/** Set the morphing method. */
|
||||||
void setMethod(Method method) { _method = method; }
|
void setMethod(Method method) { _method = method; }
|
||||||
@ -71,6 +75,30 @@ namespace osgAnimation
|
|||||||
/** Get the flag for morphing normals. */
|
/** Get the flag for morphing normals. */
|
||||||
inline bool getMorphNormals() const { return _morphNormals; }
|
inline bool getMorphNormals() const { return _morphNormals; }
|
||||||
|
|
||||||
|
/** Get the list of MorphTargets.*/
|
||||||
|
const MorphTargetList& getMorphTargetList() const { return _morphTargets; }
|
||||||
|
|
||||||
|
/** Get the list of MorphTargets. Warning if you modify this array you will have to call dirty() */
|
||||||
|
MorphTargetList& getMorphTargetList() { return _morphTargets; }
|
||||||
|
|
||||||
|
/** Return the \c MorphTarget at position \c i.*/
|
||||||
|
inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; }
|
||||||
|
|
||||||
|
/** Return the \c MorphTarget at position \c i.*/
|
||||||
|
inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; }
|
||||||
|
|
||||||
|
/** Set source of vertices for this morph geometry */
|
||||||
|
inline void setVertexSource(osg::Vec3Array *v){ _positionSource=v;}
|
||||||
|
|
||||||
|
/** Get source of vertices for this morph geometry */
|
||||||
|
inline osg::Vec3Array * getVertexSource()const{return _positionSource;}
|
||||||
|
|
||||||
|
/** Set source of normals for this morph geometry */
|
||||||
|
inline void setNormalSource(osg::Vec3Array *n){ _normalSource=n;}
|
||||||
|
|
||||||
|
/** Get source of normals for this morph geometry */
|
||||||
|
inline osg::Vec3Array * getNormalSource()const{return _normalSource;}
|
||||||
|
|
||||||
/** Add a \c MorphTarget to the \c MorphGeometry.
|
/** Add a \c MorphTarget to the \c MorphGeometry.
|
||||||
* If \c MorphTarget is not \c NULL and is not contained in the \c MorphGeometry
|
* If \c MorphTarget is not \c NULL and is not contained in the \c MorphGeometry
|
||||||
* then increment its reference count, add it to the MorphTargets list and
|
* then increment its reference count, add it to the MorphTargets list and
|
||||||
@ -101,6 +129,7 @@ namespace osgAnimation
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** update a morph target at index setting its current weight to morphWeight */
|
||||||
void setWeight(unsigned int index, float morphWeight)
|
void setWeight(unsigned int index, float morphWeight)
|
||||||
{
|
{
|
||||||
if (index < _morphTargets.size())
|
if (index < _morphTargets.size())
|
||||||
@ -111,29 +140,20 @@ namespace osgAnimation
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Set the MorphGeometry dirty.*/
|
/** Set the MorphGeometry dirty.*/
|
||||||
void dirty() { _dirty = true; }
|
inline void dirty(bool b=true) { _dirty = b; }
|
||||||
|
inline bool isDirty()const { return _dirty; }
|
||||||
|
|
||||||
/** Get the list of MorphTargets.*/
|
|
||||||
const MorphTargetList& getMorphTargetList() const { return _morphTargets; }
|
|
||||||
|
|
||||||
/** Get the list of MorphTargets. Warning if you modify this array you will have to call dirty() */
|
|
||||||
MorphTargetList& getMorphTargetList() { return _morphTargets; }
|
|
||||||
|
|
||||||
/** Return the \c MorphTarget at position \c i.*/
|
|
||||||
inline const MorphTarget& getMorphTarget( unsigned int i ) const { return _morphTargets[i]; }
|
|
||||||
|
|
||||||
/** Return the \c MorphTarget at position \c i.*/
|
|
||||||
inline MorphTarget& getMorphTarget( unsigned int i ) { return _morphTargets[i]; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
osg::ref_ptr<MorphTransform> _rigTransformImplementation;
|
||||||
/// Do we need to recalculate the morphed geometry?
|
/// Do we need to recalculate the morphed geometry?
|
||||||
bool _dirty;
|
bool _dirty;
|
||||||
|
|
||||||
Method _method;
|
Method _method;
|
||||||
MorphTargetList _morphTargets;
|
MorphTargetList _morphTargets;
|
||||||
|
|
||||||
std::vector<osg::Vec3> _positionSource;
|
osg::ref_ptr<osg::Vec3Array> _positionSource;
|
||||||
std::vector<osg::Vec3> _normalSource;
|
osg::ref_ptr<osg::Vec3Array> _normalSource;
|
||||||
|
|
||||||
/// Do we also morph between normals?
|
/// Do we also morph between normals?
|
||||||
bool _morphNormals;
|
bool _morphNormals;
|
||||||
@ -195,7 +215,13 @@ namespace osgAnimation
|
|||||||
if (!geom)
|
if (!geom)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
geom->transformSoftwareMethod();
|
if (!geom->getMorphTransformImplementation())
|
||||||
|
{
|
||||||
|
geom->setMorphTransformImplementation( new MorphTransformSoftware);
|
||||||
|
}
|
||||||
|
|
||||||
|
MorphTransform& implementation = *geom->getMorphTransformImplementation();
|
||||||
|
(implementation)(*geom);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
45
include/osgAnimation/MorphTransformSoftware
Normal file
45
include/osgAnimation/MorphTransformSoftware
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* -*-c++-*-
|
||||||
|
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OSGANIMATION_MORPHTRANSFORM_SOFTWARE
|
||||||
|
#define OSGANIMATION_MORPHTRANSFORM_SOFTWARE 1
|
||||||
|
|
||||||
|
#include <osgAnimation/Export>
|
||||||
|
#include <osgAnimation/RigTransform>
|
||||||
|
#include <osgAnimation/Bone>
|
||||||
|
#include <osg/observer_ptr>
|
||||||
|
|
||||||
|
namespace osgAnimation
|
||||||
|
{
|
||||||
|
|
||||||
|
class MorphGeometry;
|
||||||
|
|
||||||
|
/// This class manage format for software morphing
|
||||||
|
class OSGANIMATION_EXPORT MorphTransformSoftware : public MorphTransform
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MorphTransformSoftware():_needInit(true){}
|
||||||
|
MorphTransformSoftware(const MorphTransformSoftware& rts,const osg::CopyOp& copyop): MorphTransform(rts, copyop), _needInit(true){}
|
||||||
|
|
||||||
|
META_Object(osgAnimation,MorphTransformSoftware)
|
||||||
|
|
||||||
|
bool init(MorphGeometry&);
|
||||||
|
virtual void operator()(MorphGeometry&);
|
||||||
|
protected:
|
||||||
|
bool _needInit;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -57,14 +57,14 @@ namespace osgAnimation
|
|||||||
|
|
||||||
META_Object(osgAnimation, RigGeometry);
|
META_Object(osgAnimation, RigGeometry);
|
||||||
|
|
||||||
void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; }
|
inline void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; }
|
||||||
const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();}
|
inline const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();}
|
||||||
VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();}
|
inline VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();}
|
||||||
|
|
||||||
const Skeleton* getSkeleton() const;
|
inline const Skeleton* getSkeleton() const { return _root.get(); }
|
||||||
Skeleton* getSkeleton();
|
inline Skeleton* getSkeleton() { return _root.get(); }
|
||||||
// will be used by the update callback to init correctly the rig mesh
|
// will be used by the update callback to init correctly the rig mesh
|
||||||
void setSkeleton(Skeleton*);
|
inline void setSkeleton(Skeleton* root){ _root = root;}
|
||||||
|
|
||||||
void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;}
|
void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;}
|
||||||
bool getNeedToComputeMatrix() const { return _needToComputeMatrix;}
|
bool getNeedToComputeMatrix() const { return _needToComputeMatrix;}
|
||||||
@ -72,25 +72,25 @@ namespace osgAnimation
|
|||||||
|
|
||||||
// this build the internal database about vertex influence and bones
|
// this build the internal database about vertex influence and bones
|
||||||
void buildVertexInfluenceSet();
|
void buildVertexInfluenceSet();
|
||||||
const VertexInfluenceSet& getVertexInfluenceSet() const;
|
inline const VertexInfluenceSet& getVertexInfluenceSet() const { return _vertexInfluenceSet;}
|
||||||
|
|
||||||
void computeMatrixFromRootSkeleton();
|
void computeMatrixFromRootSkeleton();
|
||||||
|
|
||||||
|
|
||||||
// set implementation of rig method
|
// set implementation of rig method
|
||||||
void setRigTransformImplementation(RigTransform*);
|
inline RigTransform* getRigTransformImplementation() { return _rigTransformImplementation.get(); }
|
||||||
RigTransform* getRigTransformImplementation();
|
inline void setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; }
|
||||||
const RigTransform* getRigTransformImplementation() const { return _rigTransformImplementation.get(); }
|
inline const RigTransform* getRigTransformImplementation() const { return _rigTransformImplementation.get(); }
|
||||||
|
|
||||||
virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
const osg::Matrix& getMatrixFromSkeletonToGeometry() const;
|
const osg::Matrix& getMatrixFromSkeletonToGeometry() const;
|
||||||
const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const;
|
const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const;
|
||||||
|
|
||||||
osg::Geometry* getSourceGeometry();
|
|
||||||
const osg::Geometry* getSourceGeometry() const;
|
inline osg::Geometry* getSourceGeometry() { return _geometry.get(); }
|
||||||
void setSourceGeometry(osg::Geometry* geometry);
|
inline const osg::Geometry* getSourceGeometry() const { return _geometry.get(); }
|
||||||
|
inline void setSourceGeometry(osg::Geometry* geometry) { _geometry = geometry; }
|
||||||
|
|
||||||
void copyFrom(osg::Geometry& from);
|
void copyFrom(osg::Geometry& from);
|
||||||
|
|
||||||
|
@ -37,6 +37,23 @@ namespace osgAnimation
|
|||||||
virtual ~RigTransform() {}
|
virtual ~RigTransform() {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
class MorphGeometry;
|
||||||
|
|
||||||
|
class MorphTransform : public osg::Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MorphTransform() {}
|
||||||
|
MorphTransform(const MorphTransform& org, const osg::CopyOp& copyop):
|
||||||
|
osg::Object(org, copyop) {}
|
||||||
|
|
||||||
|
META_Object(osgAnimation,MorphTransform)
|
||||||
|
|
||||||
|
virtual void operator()(MorphGeometry&) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~MorphTransform() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,37 +38,36 @@ namespace osgAnimation
|
|||||||
META_Object(osgAnimation,RigTransformHardware);
|
META_Object(osgAnimation,RigTransformHardware);
|
||||||
|
|
||||||
typedef osg::Matrix MatrixType;
|
typedef osg::Matrix MatrixType;
|
||||||
typedef osgAnimation::Bone BoneType;
|
|
||||||
typedef std::vector<osg::ref_ptr<osg::Vec4Array> > BoneWeightAttribList;
|
typedef std::vector<osg::ref_ptr<osg::Vec4Array> > BoneWeightAttribList;
|
||||||
typedef std::vector<osg::ref_ptr<BoneType> > BonePalette;
|
typedef std::vector<osg::ref_ptr<Bone> > BonePalette;
|
||||||
typedef std::map<std::string, int> BoneNamePaletteIndex;
|
typedef std::map<std::string, unsigned int> BoneNamePaletteIndex;
|
||||||
|
|
||||||
typedef std::vector<osg::Matrix> MatrixPalette;
|
typedef std::vector<osg::Matrix> MatrixPalette;
|
||||||
struct IndexWeightEntry
|
struct IndexWeightEntry
|
||||||
{
|
{
|
||||||
int _boneIndex;
|
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<o._boneIndex);}
|
||||||
|
const unsigned int &getBoneIndex() const { return _boneIndex; }
|
||||||
|
const float &getWeight() const { return _boneWeight; }
|
||||||
|
unsigned int _boneIndex;
|
||||||
float _boneWeight;
|
float _boneWeight;
|
||||||
IndexWeightEntry() { _boneIndex = 0; _boneWeight = 0;}
|
|
||||||
IndexWeightEntry(int index, float weight) { _boneIndex = index; _boneWeight = weight;}
|
|
||||||
int getIndex() const { return _boneIndex; }
|
|
||||||
float getWeight() const { return _boneWeight; }
|
|
||||||
};
|
};
|
||||||
typedef std::vector<std::vector<IndexWeightEntry> > VertexIndexWeightList;
|
|
||||||
|
|
||||||
|
|
||||||
|
osg::Vec4Array* getVertexAttrib(unsigned int index);
|
||||||
osg::Vec4Array* getVertexAttrib(int index);
|
unsigned int getNumVertexAttrib();
|
||||||
int getNumVertexAttrib();
|
|
||||||
|
|
||||||
osg::Uniform* getMatrixPaletteUniform();
|
osg::Uniform* getMatrixPaletteUniform();
|
||||||
void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry);
|
void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry);
|
||||||
|
|
||||||
int getNumBonesPerVertex() const;
|
unsigned int getNumBonesPerVertex() const;
|
||||||
int getNumVertexes() const;
|
unsigned int getNumVertexes() const;
|
||||||
|
|
||||||
bool createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap);
|
bool createPalette(unsigned int nbVertexes,const BoneMap& boneMap, const VertexInfluenceSet::VertIDToBoneWeightList& vertexIndexToBoneWeightMap);
|
||||||
|
|
||||||
virtual void operator()(RigGeometry&);
|
virtual void operator()(RigGeometry&);
|
||||||
|
|
||||||
void setShader(osg::Shader*);
|
void setShader(osg::Shader*);
|
||||||
|
|
||||||
const BoneNamePaletteIndex& getBoneNameToPalette() {
|
const BoneNamePaletteIndex& getBoneNameToPalette() {
|
||||||
@ -78,13 +77,11 @@ namespace osgAnimation
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool init(RigGeometry&);
|
bool init(RigGeometry&);
|
||||||
|
osg::Uniform* createVertexUniform();
|
||||||
|
|
||||||
BoneWeightAttribList createVertexAttribList();
|
unsigned int _bonesPerVertex;
|
||||||
osg::Uniform* createVertexUniform();
|
unsigned int _nbVertexes;
|
||||||
|
|
||||||
int _bonesPerVertex;
|
|
||||||
int _nbVertexes;
|
|
||||||
VertexIndexWeightList _vertexIndexMatrixWeightList;
|
|
||||||
BonePalette _bonePalette;
|
BonePalette _bonePalette;
|
||||||
BoneNamePaletteIndex _boneNameToPalette;
|
BoneNamePaletteIndex _boneNameToPalette;
|
||||||
BoneWeightAttribList _boneWeightAttribArrays;
|
BoneWeightAttribList _boneWeightAttribArrays;
|
||||||
|
@ -37,10 +37,10 @@ namespace osgAnimation
|
|||||||
|
|
||||||
virtual void operator()(RigGeometry&);
|
virtual void operator()(RigGeometry&);
|
||||||
|
|
||||||
class BoneWeight
|
class BonePtrWeight
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BoneWeight(Bone* bone, float weight) : _bone(bone), _weight(weight) {}
|
BonePtrWeight(Bone* bone, float weight) : _bone(bone), _weight(weight) {}
|
||||||
const Bone* getBone() const { return _bone.get(); }
|
const Bone* getBone() const { return _bone.get(); }
|
||||||
float getWeight() const { return _weight; }
|
float getWeight() const { return _weight; }
|
||||||
void setWeight(float w) { _weight = w; }
|
void setWeight(float w) { _weight = w; }
|
||||||
@ -49,13 +49,13 @@ namespace osgAnimation
|
|||||||
float _weight;
|
float _weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<BoneWeight> BoneWeightList;
|
typedef std::vector<BonePtrWeight> BonePtrWeightList;
|
||||||
typedef std::vector<int> VertexList;
|
typedef std::vector<unsigned int> VertexList;
|
||||||
|
|
||||||
class UniqBoneSetVertexSet
|
class VertexGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BoneWeightList& getBones() { return _bones; }
|
BonePtrWeightList& getBoneWeights() { return _boneweights; }
|
||||||
VertexList& getVertexes() { return _vertexes; }
|
VertexList& getVertexes() { return _vertexes; }
|
||||||
|
|
||||||
void resetMatrix()
|
void resetMatrix()
|
||||||
@ -88,18 +88,17 @@ namespace osgAnimation
|
|||||||
}
|
}
|
||||||
void computeMatrixForVertexSet()
|
void computeMatrixForVertexSet()
|
||||||
{
|
{
|
||||||
if (_bones.empty())
|
if (_boneweights.empty())
|
||||||
{
|
{
|
||||||
osg::notify(osg::WARN) << this << " RigTransformSoftware::UniqBoneSetVertexSet no bones found" << std::endl;
|
osg::notify(osg::WARN) << this << " RigTransformSoftware::VertexGroup no bones found" << std::endl;
|
||||||
_result = osg::Matrix::identity();
|
_result = osg::Matrix::identity();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resetMatrix();
|
resetMatrix();
|
||||||
|
|
||||||
int size = _bones.size();
|
for(BonePtrWeightList::iterator bwit=_boneweights.begin();bwit!=_boneweights.end();++bwit )
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
{
|
||||||
const Bone* bone = _bones[i].getBone();
|
const Bone* bone = bwit->getBone();
|
||||||
if (!bone)
|
if (!bone)
|
||||||
{
|
{
|
||||||
osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl;
|
osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl;
|
||||||
@ -107,13 +106,13 @@ namespace osgAnimation
|
|||||||
}
|
}
|
||||||
const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
|
const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
|
||||||
const osg::Matrix& matrix = bone->getMatrixInSkeletonSpace();
|
const osg::Matrix& matrix = bone->getMatrixInSkeletonSpace();
|
||||||
osg::Matrix::value_type w = _bones[i].getWeight();
|
osg::Matrix::value_type w = bwit->getWeight();
|
||||||
accummulateMatrix(invBindMatrix, matrix, w);
|
accummulateMatrix(invBindMatrix, matrix, w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const osg::Matrix& getMatrix() const { return _result;}
|
const osg::Matrix& getMatrix() const { return _result;}
|
||||||
protected:
|
protected:
|
||||||
BoneWeightList _bones;
|
BonePtrWeightList _boneweights;
|
||||||
VertexList _vertexes;
|
VertexList _vertexes;
|
||||||
osg::Matrix _result;
|
osg::Matrix _result;
|
||||||
};
|
};
|
||||||
@ -123,39 +122,34 @@ namespace osgAnimation
|
|||||||
template <class V> void compute(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
|
template <class V> 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
|
// the result of matrix mult should be cached to be used for vertexes transform and normal transform and maybe other computation
|
||||||
int size = _boneSetVertexSet.size();
|
for(std::vector<VertexGroup>::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg)
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
{
|
||||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
VertexGroup& uniq = *itvg;
|
||||||
uniq.computeMatrixForVertexSet();
|
uniq.computeMatrixForVertexSet();
|
||||||
osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
|
osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
|
||||||
|
|
||||||
const VertexList& vertexes = uniq.getVertexes();
|
const VertexList& vertexes = uniq.getVertexes();
|
||||||
int vertexSize = vertexes.size();
|
for(VertexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit)
|
||||||
for (int j = 0; j < vertexSize; j++)
|
|
||||||
{
|
{
|
||||||
int idx = vertexes[j];
|
dst[*vertIDit] = src[*vertIDit] * matrix;
|
||||||
dst[idx] = src[idx] * matrix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class V> void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
|
template <class V> void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
|
||||||
{
|
{
|
||||||
int size = _boneSetVertexSet.size();
|
for(std::vector<VertexGroup>::iterator itvg=_uniqInfluenceSet2VertIDList.begin(); itvg!=_uniqInfluenceSet2VertIDList.end(); ++itvg)
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
{
|
||||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
VertexGroup& uniq = *itvg;
|
||||||
uniq.computeMatrixForVertexSet();
|
uniq.computeMatrixForVertexSet();
|
||||||
osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
|
osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
|
||||||
|
|
||||||
const VertexList& vertexes = uniq.getVertexes();
|
const VertexList& vertexes = uniq.getVertexes();
|
||||||
int vertexSize = vertexes.size();
|
for(VertexList::const_iterator vertIDit=vertexes.begin(); vertIDit!=vertexes.end(); ++vertIDit)
|
||||||
for (int j = 0; j < vertexSize; j++)
|
|
||||||
{
|
{
|
||||||
int idx = vertexes[j];
|
dst[*vertIDit] = osg::Matrix::transform3x3(src[*vertIDit],matrix);
|
||||||
dst[idx] = osg::Matrix::transform3x3(src[idx],matrix);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,8 +157,8 @@ namespace osgAnimation
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool init(RigGeometry&);
|
bool init(RigGeometry&);
|
||||||
void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence);
|
void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexGroupList& influence);
|
||||||
std::vector<UniqBoneSetVertexSet> _boneSetVertexSet;
|
std::vector<VertexGroup> _uniqInfluenceSet2VertIDList;
|
||||||
|
|
||||||
bool _needInit;
|
bool _needInit;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace osgAnimation
|
|||||||
{
|
{
|
||||||
|
|
||||||
// first is vertex index, and second the weight, the
|
// first is vertex index, and second the weight, the
|
||||||
typedef std::pair<int, float> VertexIndexWeight;
|
typedef std::pair<unsigned int, float> VertexIndexWeight;
|
||||||
typedef std::vector<VertexIndexWeight> VertexList;
|
typedef std::vector<VertexIndexWeight> VertexList;
|
||||||
class OSGANIMATION_EXPORT VertexInfluence : public VertexList
|
class OSGANIMATION_EXPORT VertexInfluence : public VertexList
|
||||||
{
|
{
|
||||||
@ -62,43 +62,48 @@ namespace osgAnimation
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BoneWeight(const std::string& name, float weight) : _boneName(name), _weight(weight) {}
|
BoneWeight(const std::string& name, float weight) : _boneName(name), _weight(weight) {}
|
||||||
|
BoneWeight(const BoneWeight &bw2) : _boneName(bw2._boneName), _weight(bw2._weight) {}
|
||||||
const std::string& getBoneName() const { return _boneName; }
|
const std::string& getBoneName() const { return _boneName; }
|
||||||
float getWeight() const { return _weight; }
|
float getWeight() const { return _weight; }
|
||||||
void setWeight(float weight) { _weight = weight; }
|
void setWeight(float weight) { _weight = weight; }
|
||||||
bool operator==(const BoneWeight& b) const { return (_boneName == b.getBoneName() && _weight == b.getWeight()); }
|
bool operator==(const BoneWeight& b) const { return (_boneName == b.getBoneName() && _weight == b.getWeight()); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string _boneName;
|
std::string _boneName;
|
||||||
float _weight;
|
float _weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<BoneWeight> BoneWeightList;
|
typedef std::vector<BoneWeight> BoneWeightList;
|
||||||
typedef std::map<int,BoneWeightList> VertexIndexToBoneWeightMap;
|
typedef std::vector<BoneWeightList> VertIDToBoneWeightList;
|
||||||
|
|
||||||
class UniqVertexSetToBoneSet
|
class VertexGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// set Influences of the VertexGroup
|
||||||
void setBones(BoneWeightList& bones) { _bones = bones;}
|
void setBones(BoneWeightList& bones) { _bones = bones;}
|
||||||
const BoneWeightList& getBones() const { return _bones;}
|
const BoneWeightList& getBones() const { return _bones;}
|
||||||
std::vector<int>& getVertexes() { return _vertexes;}
|
// set Vertex Indices of the VertexGroup
|
||||||
const std::vector<int>& getVertexes() const { return _vertexes;}
|
std::vector<unsigned int>& getVertexes() { return _vertexes;}
|
||||||
|
const std::vector<unsigned int>& getVertexes() const { return _vertexes;}
|
||||||
protected:
|
protected:
|
||||||
std::vector<int> _vertexes;
|
std::vector<unsigned int> _vertexes;
|
||||||
BoneWeightList _bones; // here we could limit matrix operation by caching (weight * matrix)
|
BoneWeightList _bones; // here we could limit matrix operation by caching (weight * matrix)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<UniqVertexSetToBoneSet> UniqVertexSetToBoneSetList;
|
typedef std::vector<VertexGroup> UniqVertexGroupList;
|
||||||
|
/** construct a vector of unique VertexGroups and their influences**/
|
||||||
const UniqVertexSetToBoneSetList& getUniqVertexSetToBoneSetList() const { return _uniqVertexSetToBoneSet;}
|
void buildUniqVertexGroupList();
|
||||||
|
/** return a list of unique VertexGroups and their influences**/
|
||||||
|
const UniqVertexGroupList& getUniqVertexGroupList() const { return _uniqVertexSetToBoneSet;}
|
||||||
void addVertexInfluence(const VertexInfluence& v);
|
void addVertexInfluence(const VertexInfluence& v);
|
||||||
void buildVertex2BoneList();
|
void buildVertex2BoneList(unsigned int numvertices);
|
||||||
void buildUniqVertexSetToBoneSetList();
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
const VertexIndexToBoneWeightMap& getVertexToBoneList() const;
|
const VertIDToBoneWeightList& getVertexToBoneList() const;
|
||||||
protected:
|
protected:
|
||||||
BoneToVertexList _bone2Vertexes;
|
BoneToVertexList _bone2Vertexes;
|
||||||
VertexIndexToBoneWeightMap _vertex2Bones;
|
VertIDToBoneWeightList _vertex2Bones;
|
||||||
UniqVertexSetToBoneSetList _uniqVertexSetToBoneSet;
|
UniqVertexGroupList _uniqVertexSetToBoneSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,10 @@ void AnimationManagerBase::registerAnimation (Animation* animation)
|
|||||||
buildTargetReference();
|
buildTargetReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationManagerBase::unregisterAnimation (Animation* animation)
|
void AnimationManagerBase::removeRegisteredAnimation(Animation* animation){
|
||||||
|
unregisterAnimation(animation);
|
||||||
|
}
|
||||||
|
void AnimationManagerBase::unregisterAnimation(Animation* animation)
|
||||||
{
|
{
|
||||||
AnimationList::iterator it = std::find(_animations.begin(), _animations.end(), animation);
|
AnimationList::iterator it = std::find(_animations.begin(), _animations.end(), animation);
|
||||||
if (it != _animations.end())
|
if (it != _animations.end())
|
||||||
|
@ -34,6 +34,7 @@ SET(TARGET_H
|
|||||||
${HEADER_PATH}/RigTransform
|
${HEADER_PATH}/RigTransform
|
||||||
${HEADER_PATH}/RigTransformHardware
|
${HEADER_PATH}/RigTransformHardware
|
||||||
${HEADER_PATH}/RigTransformSoftware
|
${HEADER_PATH}/RigTransformSoftware
|
||||||
|
${HEADER_PATH}/MorphTransformSoftware
|
||||||
${HEADER_PATH}/Sampler
|
${HEADER_PATH}/Sampler
|
||||||
${HEADER_PATH}/Skeleton
|
${HEADER_PATH}/Skeleton
|
||||||
${HEADER_PATH}/StackedMatrixElement
|
${HEADER_PATH}/StackedMatrixElement
|
||||||
@ -75,6 +76,7 @@ SET(TARGET_SRC
|
|||||||
RigGeometry.cpp
|
RigGeometry.cpp
|
||||||
RigTransformHardware.cpp
|
RigTransformHardware.cpp
|
||||||
RigTransformSoftware.cpp
|
RigTransformSoftware.cpp
|
||||||
|
MorphTransformSoftware.cpp
|
||||||
Skeleton.cpp
|
Skeleton.cpp
|
||||||
StackedMatrixElement.cpp
|
StackedMatrixElement.cpp
|
||||||
StackedQuaternionElement.cpp
|
StackedQuaternionElement.cpp
|
||||||
|
@ -23,23 +23,23 @@ using namespace osgAnimation;
|
|||||||
MorphGeometry::MorphGeometry() :
|
MorphGeometry::MorphGeometry() :
|
||||||
_dirty(false),
|
_dirty(false),
|
||||||
_method(NORMALIZED),
|
_method(NORMALIZED),
|
||||||
|
_positionSource(0),_normalSource(0),
|
||||||
_morphNormals(true)
|
_morphNormals(true)
|
||||||
{
|
{
|
||||||
setUseDisplayList(false);
|
setUseDisplayList(false);
|
||||||
setUpdateCallback(new UpdateMorphGeometry);
|
setUpdateCallback(new UpdateMorphGeometry);
|
||||||
setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
setUseVertexBufferObjects(true);
|
setUseVertexBufferObjects(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
MorphGeometry::MorphGeometry(const osg::Geometry& b) :
|
MorphGeometry::MorphGeometry(const osg::Geometry& g) :
|
||||||
osg::Geometry(b, osg::CopyOp::DEEP_COPY_ARRAYS),
|
osg::Geometry(g, osg::CopyOp::DEEP_COPY_ARRAYS),
|
||||||
_dirty(false),
|
_dirty(false),
|
||||||
_method(NORMALIZED),
|
_method(NORMALIZED),
|
||||||
|
_positionSource(0),_normalSource(0),
|
||||||
_morphNormals(true)
|
_morphNormals(true)
|
||||||
{
|
{
|
||||||
setUseDisplayList(false);
|
setUseDisplayList(false);
|
||||||
setUpdateCallback(new UpdateMorphGeometry);
|
setUpdateCallback(new UpdateMorphGeometry);
|
||||||
setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
setUseVertexBufferObjects(true);
|
setUseVertexBufferObjects(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,151 +56,14 @@ MorphGeometry::MorphGeometry(const MorphGeometry& b, const osg::CopyOp& copyop)
|
|||||||
setUseVertexBufferObjects(true);
|
setUseVertexBufferObjects(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MorphTransform* MorphGeometry::getMorphTransformImplementation() { return _rigTransformImplementation.get(); }
|
||||||
void MorphGeometry::transformSoftwareMethod()
|
void MorphGeometry::setMorphTransformImplementation(MorphTransform* rig) { _rigTransformImplementation = rig; }
|
||||||
{
|
|
||||||
if (_dirty)
|
|
||||||
{
|
|
||||||
// See if we have an internal optimized geometry
|
|
||||||
osg::Geometry* morphGeometry = this;
|
|
||||||
|
|
||||||
osg::Vec3Array* pos = dynamic_cast<osg::Vec3Array*>(morphGeometry->getVertexArray());
|
|
||||||
|
|
||||||
if(pos)
|
|
||||||
{
|
|
||||||
if ( _positionSource.size() != pos->size())
|
|
||||||
{
|
|
||||||
_positionSource = std::vector<osg::Vec3>(pos->begin(),pos->end());
|
|
||||||
pos->setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec3Array* normal = dynamic_cast<osg::Vec3Array*>(morphGeometry->getNormalArray());
|
|
||||||
bool normalmorphable = _morphNormals && normal;
|
|
||||||
if (normal && _normalSource.size() != normal->size())
|
|
||||||
{
|
|
||||||
_normalSource = std::vector<osg::Vec3>(normal->begin(),normal->end());
|
|
||||||
normal->setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!_positionSource.empty())
|
|
||||||
{
|
|
||||||
bool initialized = false;
|
|
||||||
if (_method == NORMALIZED)
|
|
||||||
{
|
|
||||||
// base * 1 - (sum of weights) + sum of (weight * target)
|
|
||||||
float baseWeight = 0;
|
|
||||||
for (unsigned int i=0; i < _morphTargets.size(); i++)
|
|
||||||
{
|
|
||||||
baseWeight += _morphTargets[i].getWeight();
|
|
||||||
}
|
|
||||||
baseWeight = 1 - baseWeight;
|
|
||||||
|
|
||||||
if (baseWeight != 0)
|
|
||||||
{
|
|
||||||
initialized = true;
|
|
||||||
for (unsigned int i=0; i < pos->size(); i++)
|
|
||||||
{
|
|
||||||
(*pos)[i] = _positionSource[i] * baseWeight;
|
|
||||||
}
|
|
||||||
if (normalmorphable)
|
|
||||||
{
|
|
||||||
for (unsigned int i=0; i < normal->size(); i++)
|
|
||||||
{
|
|
||||||
(*normal)[i] = _normalSource[i] * baseWeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //if (_method == RELATIVE)
|
|
||||||
{
|
|
||||||
// base + sum of (weight * target)
|
|
||||||
initialized = true;
|
|
||||||
for (unsigned int i=0; i < pos->size(); i++)
|
|
||||||
{
|
|
||||||
(*pos)[i] = _positionSource[i];
|
|
||||||
}
|
|
||||||
if (normalmorphable)
|
|
||||||
{
|
|
||||||
for (unsigned int i=0; i < normal->size(); i++)
|
|
||||||
{
|
|
||||||
(*normal)[i] = _normalSource[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i=0; i < _morphTargets.size(); i++)
|
|
||||||
{
|
|
||||||
if (_morphTargets[i].getWeight() > 0)
|
|
||||||
{
|
|
||||||
// See if any the targets use the internal optimized geometry
|
|
||||||
osg::Geometry* targetGeometry = _morphTargets[i].getGeometry();
|
|
||||||
|
|
||||||
osg::Vec3Array* targetPos = dynamic_cast<osg::Vec3Array*>(targetGeometry->getVertexArray());
|
|
||||||
osg::Vec3Array* targetNormals = dynamic_cast<osg::Vec3Array*>(targetGeometry->getNormalArray());
|
|
||||||
normalmorphable = normalmorphable && targetNormals;
|
|
||||||
if(targetPos)
|
|
||||||
{
|
|
||||||
if (initialized)
|
|
||||||
{
|
|
||||||
// If vertices are initialized, add the morphtargets
|
|
||||||
for (unsigned int j=0; j < pos->size(); j++)
|
|
||||||
{
|
|
||||||
(*pos)[j] += (*targetPos)[j] * _morphTargets[i].getWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (normalmorphable)
|
|
||||||
{
|
|
||||||
for (unsigned int j=0; j < normal->size(); j++)
|
|
||||||
{
|
|
||||||
(*normal)[j] += (*targetNormals)[j] * _morphTargets[i].getWeight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If not initialized, initialize with this morph target
|
|
||||||
initialized = true;
|
|
||||||
for (unsigned int j=0; j < pos->size(); j++)
|
|
||||||
{
|
|
||||||
(*pos)[j] = (*targetPos)[j] * _morphTargets[i].getWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (normalmorphable)
|
|
||||||
{
|
|
||||||
for (unsigned int j=0; j < normal->size(); j++)
|
|
||||||
{
|
|
||||||
(*normal)[j] = (*targetNormals)[j] * _morphTargets[i].getWeight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pos->dirty();
|
|
||||||
if (normalmorphable)
|
|
||||||
{
|
|
||||||
for (unsigned int j=0; j < normal->size(); j++)
|
|
||||||
{
|
|
||||||
(*normal)[j].normalize();
|
|
||||||
}
|
|
||||||
normal->dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyBound();
|
|
||||||
|
|
||||||
}
|
|
||||||
_dirty = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) :
|
UpdateMorph::UpdateMorph(const UpdateMorph& apc,const osg::CopyOp& copyop) :
|
||||||
osg::Object(apc, copyop),
|
osg::Object(apc, copyop),
|
||||||
osg::Callback(apc, copyop),
|
osg::Callback(apc, copyop),
|
||||||
AnimationUpdateCallback<osg::NodeCallback>(apc, copyop)
|
AnimationUpdateCallback<osg::NodeCallback>(apc, copyop)
|
||||||
{
|
{_targetNames=apc._targetNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateMorph::UpdateMorph(const std::string& name) : AnimationUpdateCallback<osg::NodeCallback>(name)
|
UpdateMorph::UpdateMorph(const std::string& name) : AnimationUpdateCallback<osg::NodeCallback>(name)
|
||||||
|
182
src/osgAnimation/MorphTransformSoftware.cpp
Normal file
182
src/osgAnimation/MorphTransformSoftware.cpp
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/* -*-c++-*-
|
||||||
|
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <osgAnimation/VertexInfluence>
|
||||||
|
#include <osgAnimation/MorphTransformSoftware>
|
||||||
|
#include <osgAnimation/BoneMapVisitor>
|
||||||
|
#include <osgAnimation/MorphGeometry>
|
||||||
|
|
||||||
|
using namespace osgAnimation;
|
||||||
|
|
||||||
|
|
||||||
|
bool MorphTransformSoftware::init(MorphGeometry& morphGeometry){
|
||||||
|
|
||||||
|
|
||||||
|
morphGeometry.setDataVariance(osg::Object::DYNAMIC);
|
||||||
|
osg::Vec3Array* pos = dynamic_cast<osg::Vec3Array*>(morphGeometry.getVertexArray());
|
||||||
|
osg::Vec3Array * vertexSource = (morphGeometry.getVertexSource());
|
||||||
|
osg::Vec3Array * normalSource = (morphGeometry.getNormalSource());
|
||||||
|
|
||||||
|
// See if we have an internal optimized geometry
|
||||||
|
|
||||||
|
if(pos)
|
||||||
|
{
|
||||||
|
if (!vertexSource|| vertexSource->size() != pos->size())
|
||||||
|
{
|
||||||
|
morphGeometry.setVertexSource(new osg::Vec3Array(pos->begin(),pos->end()));
|
||||||
|
pos->setDataVariance(osg::Object::DYNAMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Vec3Array* normal = dynamic_cast<osg::Vec3Array*>(morphGeometry.getNormalArray());
|
||||||
|
bool normalmorphable = morphGeometry.getMorphNormals() && normal;
|
||||||
|
morphGeometry.setMorphNormals(normalmorphable);
|
||||||
|
if (normalmorphable && (!normalSource || normalSource->size() != normal->size()))
|
||||||
|
{
|
||||||
|
morphGeometry.setNormalSource(new osg::Vec3Array(normal->begin(),normal->end()));
|
||||||
|
normal->setDataVariance(osg::Object::DYNAMIC);
|
||||||
|
}
|
||||||
|
}else return false;
|
||||||
|
|
||||||
|
_needInit=false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MorphTransformSoftware::operator()(MorphGeometry& morphGeometry)
|
||||||
|
{
|
||||||
|
if (_needInit)
|
||||||
|
if (!init(morphGeometry))
|
||||||
|
return;
|
||||||
|
if (morphGeometry.isDirty())
|
||||||
|
{
|
||||||
|
osg::Vec3Array* pos = static_cast<osg::Vec3Array*>(morphGeometry.getVertexArray());
|
||||||
|
osg::Vec3Array & vertexSource = *(morphGeometry.getVertexSource());
|
||||||
|
osg::Vec3Array& normalSource = *(morphGeometry.getNormalSource());
|
||||||
|
osg::Vec3Array* normal = static_cast<osg::Vec3Array*>(morphGeometry.getNormalArray());
|
||||||
|
bool normalmorphable = morphGeometry.getMorphNormals() && normal;
|
||||||
|
|
||||||
|
|
||||||
|
if (!vertexSource.empty())
|
||||||
|
{
|
||||||
|
bool initialized = false;
|
||||||
|
if (morphGeometry.getMethod() == MorphGeometry::NORMALIZED)
|
||||||
|
{
|
||||||
|
// base * 1 - (sum of weights) + sum of (weight * target)
|
||||||
|
float baseWeight = 0;
|
||||||
|
for (unsigned int i=0; i < morphGeometry.getMorphTargetList().size(); i++)
|
||||||
|
{
|
||||||
|
baseWeight += morphGeometry.getMorphTarget(i).getWeight();
|
||||||
|
}
|
||||||
|
baseWeight = 1 - baseWeight;
|
||||||
|
|
||||||
|
if (baseWeight != 0)
|
||||||
|
{
|
||||||
|
initialized = true;
|
||||||
|
for (unsigned int i=0; i < pos->size(); i++)
|
||||||
|
{
|
||||||
|
(*pos)[i] = vertexSource[i] * baseWeight;
|
||||||
|
}
|
||||||
|
if (normalmorphable)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i < normal->size(); i++)
|
||||||
|
{
|
||||||
|
(*normal)[i] = normalSource[i] * baseWeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //if (_method == RELATIVE)
|
||||||
|
{
|
||||||
|
// base + sum of (weight * target)
|
||||||
|
initialized = true;
|
||||||
|
for (unsigned int i=0; i < pos->size(); i++)
|
||||||
|
{
|
||||||
|
(*pos)[i] = vertexSource[i];
|
||||||
|
}
|
||||||
|
if (normalmorphable)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i < normal->size(); i++)
|
||||||
|
{
|
||||||
|
(*normal)[i] = normalSource[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i=0; i < morphGeometry.getMorphTargetList().size(); i++)
|
||||||
|
{
|
||||||
|
if (morphGeometry.getMorphTarget(i).getWeight() > 0)
|
||||||
|
{
|
||||||
|
// See if any the targets use the internal optimized geometry
|
||||||
|
osg::Geometry* targetGeometry = morphGeometry.getMorphTarget(i).getGeometry();
|
||||||
|
|
||||||
|
osg::Vec3Array* targetPos = dynamic_cast<osg::Vec3Array*>(targetGeometry->getVertexArray());
|
||||||
|
osg::Vec3Array* targetNormals = dynamic_cast<osg::Vec3Array*>(targetGeometry->getNormalArray());
|
||||||
|
normalmorphable = normalmorphable && targetNormals;
|
||||||
|
if(targetPos)
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
{
|
||||||
|
// If vertices are initialized, add the morphtargets
|
||||||
|
for (unsigned int j=0; j < pos->size(); j++)
|
||||||
|
{
|
||||||
|
(*pos)[j] += (*targetPos)[j] * morphGeometry.getMorphTarget(i).getWeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalmorphable)
|
||||||
|
{
|
||||||
|
for (unsigned int j=0; j < normal->size(); j++)
|
||||||
|
{
|
||||||
|
(*normal)[j] += (*targetNormals)[j] * morphGeometry.getMorphTarget(i).getWeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If not initialized, initialize with this morph target
|
||||||
|
initialized = true;
|
||||||
|
for (unsigned int j=0; j < pos->size(); j++)
|
||||||
|
{
|
||||||
|
(*pos)[j] = (*targetPos)[j] * morphGeometry.getMorphTarget(i).getWeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalmorphable)
|
||||||
|
{
|
||||||
|
for (unsigned int j=0; j < normal->size(); j++)
|
||||||
|
{
|
||||||
|
(*normal)[j] = (*targetNormals)[j] * morphGeometry.getMorphTarget(i).getWeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos->dirty();
|
||||||
|
if (normalmorphable)
|
||||||
|
{
|
||||||
|
for (unsigned int j=0; j < normal->size(); j++)
|
||||||
|
{
|
||||||
|
(*normal)[j].normalize();
|
||||||
|
}
|
||||||
|
normal->dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
morphGeometry.dirtyBound();
|
||||||
|
|
||||||
|
|
||||||
|
morphGeometry.dirty(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -58,7 +58,7 @@ RigGeometry::RigGeometry()
|
|||||||
_needToComputeMatrix = true;
|
_needToComputeMatrix = true;
|
||||||
_matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity();
|
_matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity();
|
||||||
// disable the computation of boundingbox for the rig mesh
|
// disable the computation of boundingbox for the rig mesh
|
||||||
setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback);
|
setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +70,11 @@ RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) :
|
|||||||
_vertexInfluenceMap(b._vertexInfluenceMap),
|
_vertexInfluenceMap(b._vertexInfluenceMap),
|
||||||
_needToComputeMatrix(b._needToComputeMatrix)
|
_needToComputeMatrix(b._needToComputeMatrix)
|
||||||
{
|
{
|
||||||
|
_needToComputeMatrix = true;
|
||||||
|
_matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity();
|
||||||
// disable the computation of boundingbox for the rig mesh
|
// disable the computation of boundingbox for the rig mesh
|
||||||
setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback);
|
|
||||||
|
setComputeBoundingBoxCallback(new RigComputeBoundingBoxCallback());
|
||||||
// we don't copy the RigImplementation yet. because the RigImplementation need to be initialized in a valid graph, with a skeleton ...
|
// we don't copy the RigImplementation yet. because the RigImplementation need to be initialized in a valid graph, with a skeleton ...
|
||||||
// don't know yet what to do with a clone of a RigGeometry
|
// don't know yet what to do with a clone of a RigGeometry
|
||||||
|
|
||||||
@ -81,12 +84,6 @@ RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) :
|
|||||||
const osg::Matrix& RigGeometry::getMatrixFromSkeletonToGeometry() const { return _matrixFromSkeletonToGeometry; }
|
const osg::Matrix& RigGeometry::getMatrixFromSkeletonToGeometry() const { return _matrixFromSkeletonToGeometry; }
|
||||||
const osg::Matrix& RigGeometry::getInvMatrixFromSkeletonToGeometry() const { return _invMatrixFromSkeletonToGeometry;}
|
const osg::Matrix& RigGeometry::getInvMatrixFromSkeletonToGeometry() const { return _invMatrixFromSkeletonToGeometry;}
|
||||||
|
|
||||||
|
|
||||||
void RigGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
|
|
||||||
{
|
|
||||||
osg::Geometry::drawImplementation(renderInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RigGeometry::buildVertexInfluenceSet()
|
void RigGeometry::buildVertexInfluenceSet()
|
||||||
{
|
{
|
||||||
if (!_vertexInfluenceMap.valid())
|
if (!_vertexInfluenceMap.valid())
|
||||||
@ -97,12 +94,12 @@ void RigGeometry::buildVertexInfluenceSet()
|
|||||||
_vertexInfluenceSet.clear();
|
_vertexInfluenceSet.clear();
|
||||||
for (osgAnimation::VertexInfluenceMap::iterator it = _vertexInfluenceMap->begin();
|
for (osgAnimation::VertexInfluenceMap::iterator it = _vertexInfluenceMap->begin();
|
||||||
it != _vertexInfluenceMap->end();
|
it != _vertexInfluenceMap->end();
|
||||||
++it)
|
++it){
|
||||||
_vertexInfluenceSet.addVertexInfluence(it->second);
|
_vertexInfluenceSet.addVertexInfluence(it->second);
|
||||||
|
}
|
||||||
_vertexInfluenceSet.buildVertex2BoneList();
|
_vertexInfluenceSet.buildVertex2BoneList(getSourceGeometry()->getVertexArray()->getNumElements());
|
||||||
_vertexInfluenceSet.buildUniqVertexSetToBoneSetList();
|
_vertexInfluenceSet.buildUniqVertexGroupList();
|
||||||
OSG_DEBUG << "uniq groups " << _vertexInfluenceSet.getUniqVertexSetToBoneSetList().size() << " for " << getName() << std::endl;
|
OSG_DEBUG << "uniq groups " << _vertexInfluenceSet.getUniqVertexGroupList().size() << " for " << getName() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RigGeometry::computeMatrixFromRootSkeleton()
|
void RigGeometry::computeMatrixFromRootSkeleton()
|
||||||
@ -132,45 +129,45 @@ void RigGeometry::update()
|
|||||||
|
|
||||||
void RigGeometry::copyFrom(osg::Geometry& from)
|
void RigGeometry::copyFrom(osg::Geometry& from)
|
||||||
{
|
{
|
||||||
bool copyToSelf = (this==&from);
|
if (this==&from) return;
|
||||||
|
|
||||||
osg::Geometry& target = *this;
|
osg::Geometry& target = *this;
|
||||||
|
|
||||||
if (!copyToSelf) target.setStateSet(from.getStateSet());
|
target.setStateSet(from.getStateSet());
|
||||||
|
|
||||||
// copy over primitive sets.
|
// copy over primitive sets.
|
||||||
if (!copyToSelf) target.getPrimitiveSetList() = from.getPrimitiveSetList();
|
target.getPrimitiveSetList() = from.getPrimitiveSetList();
|
||||||
|
|
||||||
if (from.getVertexArray())
|
if (from.getVertexArray())
|
||||||
{
|
{
|
||||||
if (!copyToSelf) target.setVertexArray(from.getVertexArray());
|
target.setVertexArray(from.getVertexArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from.getNormalArray())
|
if (from.getNormalArray())
|
||||||
{
|
{
|
||||||
if (!copyToSelf) target.setNormalArray(from.getNormalArray());
|
target.setNormalArray(from.getNormalArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from.getColorArray())
|
if (from.getColorArray())
|
||||||
{
|
{
|
||||||
if (!copyToSelf) target.setColorArray(from.getColorArray());
|
target.setColorArray(from.getColorArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from.getSecondaryColorArray())
|
if (from.getSecondaryColorArray())
|
||||||
{
|
{
|
||||||
if (!copyToSelf) target.setSecondaryColorArray(from.getSecondaryColorArray());
|
target.setSecondaryColorArray(from.getSecondaryColorArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from.getFogCoordArray())
|
if (from.getFogCoordArray())
|
||||||
{
|
{
|
||||||
if (!copyToSelf) target.setFogCoordArray(from.getFogCoordArray());
|
target.setFogCoordArray(from.getFogCoordArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int ti=0;ti<from.getNumTexCoordArrays();++ti)
|
for(unsigned int ti=0;ti<from.getNumTexCoordArrays();++ti)
|
||||||
{
|
{
|
||||||
if (from.getTexCoordArray(ti))
|
if (from.getTexCoordArray(ti))
|
||||||
{
|
{
|
||||||
if (!copyToSelf) target.setTexCoordArray(ti,from.getTexCoordArray(ti));
|
target.setTexCoordArray(ti,from.getTexCoordArray(ti));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,19 +177,11 @@ void RigGeometry::copyFrom(osg::Geometry& from)
|
|||||||
osg::Array* array = arrayList[vi].get();
|
osg::Array* array = arrayList[vi].get();
|
||||||
if (array)
|
if (array)
|
||||||
{
|
{
|
||||||
if (!copyToSelf) target.setVertexAttribArray(vi,array);
|
target.setVertexAttribArray(vi,array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VertexInfluenceSet& RigGeometry::getVertexInfluenceSet() const { return _vertexInfluenceSet;}
|
|
||||||
|
|
||||||
const Skeleton* RigGeometry::getSkeleton() const { return _root.get(); }
|
|
||||||
Skeleton* RigGeometry::getSkeleton() { return _root.get(); }
|
|
||||||
void RigGeometry::setSkeleton(Skeleton* root) { _root = root;}
|
|
||||||
RigTransform* RigGeometry::getRigTransformImplementation() { return _rigTransformImplementation.get(); }
|
|
||||||
void RigGeometry::setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; }
|
|
||||||
|
|
||||||
osg::Geometry* RigGeometry::getSourceGeometry() { return _geometry.get(); }
|
|
||||||
const osg::Geometry* RigGeometry::getSourceGeometry() const { return _geometry.get(); }
|
|
||||||
void RigGeometry::setSourceGeometry(osg::Geometry* geometry) { _geometry = geometry; }
|
|
||||||
|
@ -31,7 +31,6 @@ RigTransformHardware::RigTransformHardware(const RigTransformHardware& rth, cons
|
|||||||
RigTransform(rth, copyop),
|
RigTransform(rth, copyop),
|
||||||
_bonesPerVertex(rth._bonesPerVertex),
|
_bonesPerVertex(rth._bonesPerVertex),
|
||||||
_nbVertexes(rth._nbVertexes),
|
_nbVertexes(rth._nbVertexes),
|
||||||
_vertexIndexMatrixWeightList(rth._vertexIndexMatrixWeightList),
|
|
||||||
_bonePalette(rth._bonePalette),
|
_bonePalette(rth._bonePalette),
|
||||||
_boneNameToPalette(rth._boneNameToPalette),
|
_boneNameToPalette(rth._boneNameToPalette),
|
||||||
_boneWeightAttribArrays(rth._boneWeightAttribArrays),
|
_boneWeightAttribArrays(rth._boneWeightAttribArrays),
|
||||||
@ -41,14 +40,14 @@ RigTransformHardware::RigTransformHardware(const RigTransformHardware& rth, cons
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec4Array* RigTransformHardware::getVertexAttrib(int index)
|
osg::Vec4Array* RigTransformHardware::getVertexAttrib(unsigned int index)
|
||||||
{
|
{
|
||||||
if (index >= (int)_boneWeightAttribArrays.size())
|
if (index >= _boneWeightAttribArrays.size())
|
||||||
return 0;
|
return 0;
|
||||||
return _boneWeightAttribArrays[index].get();
|
return _boneWeightAttribArrays[index].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int RigTransformHardware::getNumVertexAttrib()
|
unsigned int RigTransformHardware::getNumVertexAttrib()
|
||||||
{
|
{
|
||||||
return _boneWeightAttribArrays.size();
|
return _boneWeightAttribArrays.size();
|
||||||
}
|
}
|
||||||
@ -61,68 +60,83 @@ osg::Uniform* RigTransformHardware::getMatrixPaletteUniform()
|
|||||||
|
|
||||||
void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry)
|
void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)_bonePalette.size(); i++)
|
for (unsigned int i = 0; i < _bonePalette.size(); i++)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<Bone> bone = _bonePalette[i].get();
|
osg::ref_ptr<Bone> bone = _bonePalette[i].get();
|
||||||
const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
|
const osg::Matrixf& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
|
||||||
const osg::Matrix& boneMatrix = bone->getMatrixInSkeletonSpace();
|
const osg::Matrixf& boneMatrix = bone->getMatrixInSkeletonSpace();
|
||||||
osg::Matrix resultBoneMatrix = invBindMatrix * boneMatrix;
|
osg::Matrixf resultBoneMatrix = invBindMatrix * boneMatrix;
|
||||||
osg::Matrix result = transformFromSkeletonToGeometry * resultBoneMatrix * invTransformFromSkeletonToGeometry;
|
osg::Matrixf result = transformFromSkeletonToGeometry * resultBoneMatrix * invTransformFromSkeletonToGeometry;
|
||||||
if (!_uniformMatrixPalette->setElement(i, result))
|
if (!_uniformMatrixPalette->setElement(i, result))
|
||||||
OSG_WARN << "RigTransformHardware::computeUniformMatrixPalette can't set uniform at " << i << " elements" << std::endl;
|
OSG_WARN << "RigTransformHardware::computeUniformMatrixPalette can't set uniform at " << i << " elements" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;}
|
unsigned int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;}
|
||||||
int RigTransformHardware::getNumVertexes() const { return _nbVertexes;}
|
unsigned int RigTransformHardware::getNumVertexes() const { return _nbVertexes;}
|
||||||
|
|
||||||
bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap)
|
typedef std::vector<std::vector<RigTransformHardware::IndexWeightEntry> > 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<std::string, int> BoneNameCountMap;
|
typedef std::map<std::string, int> BoneNameCountMap;
|
||||||
BonePalette palette;
|
_bonePalette.clear();
|
||||||
|
_boneNameToPalette.clear();
|
||||||
BoneNameCountMap boneNameCountMap;
|
BoneNameCountMap boneNameCountMap;
|
||||||
|
|
||||||
// init vertex attribute data
|
// init vertex attribute data
|
||||||
VertexIndexWeightList vertexIndexWeight;
|
VertexIndexWeightList vertexIndexWeight;
|
||||||
vertexIndexWeight.resize(nbVertexes);
|
vertexIndexWeight.resize(nbVertexes);
|
||||||
|
|
||||||
int maxBonePerVertex = 0;
|
unsigned int maxBonePerVertex = 0;
|
||||||
for (VertexInfluenceSet::VertexIndexToBoneWeightMap::const_iterator vit = vertexIndexToBoneWeightMap.begin(); vit != vertexIndexToBoneWeightMap.end(); ++vit)
|
if(vertexIndexToBoneWeightMap.size()!=nbVertexes) {
|
||||||
|
OSG_WARN << "RigTransformHardware::some vertex has no transform " <<vertexIndexToBoneWeightMap.size()<<"!="<< nbVertexes << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned int vertexID=0;
|
||||||
|
BoneNamePaletteIndex::iterator boneName2PaletteIndex;
|
||||||
|
for (VertexInfluenceSet::VertIDToBoneWeightList::const_iterator vit = vertexIndexToBoneWeightMap.begin();
|
||||||
|
vit != vertexIndexToBoneWeightMap.end(); ++vit,++vertexID)
|
||||||
{
|
{
|
||||||
int vertexIndex = vit->first;
|
const VertexInfluenceSet::BoneWeightList& boneWeightList = *vit;
|
||||||
const VertexInfluenceSet::BoneWeightList& boneWeightList = vit->second;
|
unsigned int bonesForThisVertex = 0;
|
||||||
int bonesForThisVertex = 0;
|
|
||||||
for (VertexInfluenceSet::BoneWeightList::const_iterator it = boneWeightList.begin(); it != boneWeightList.end(); ++it)
|
for (VertexInfluenceSet::BoneWeightList::const_iterator it = boneWeightList.begin(); it != boneWeightList.end(); ++it)
|
||||||
{
|
{
|
||||||
const VertexInfluenceSet::BoneWeight& bw = *it;
|
const VertexInfluenceSet::BoneWeight& bw = *it;
|
||||||
if(fabs(bw.getWeight()) > 1e-2) // don't use bone with weight too small
|
if(fabs(bw.getWeight()) > 1e-4) // don't use bone with weight too small
|
||||||
{
|
{
|
||||||
if (boneNameCountMap.find(bw.getBoneName()) != boneNameCountMap.end())
|
if ((boneName2PaletteIndex= _boneNameToPalette.find(bw.getBoneName())) != _boneNameToPalette.end())
|
||||||
{
|
{
|
||||||
boneNameCountMap[bw.getBoneName()]++;
|
boneNameCountMap[bw.getBoneName()]++;
|
||||||
bonesForThisVertex++; // count max number of bones per vertexes
|
bonesForThisVertex++; // count max number of bones per vertexes
|
||||||
vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(_boneNameToPalette[bw.getBoneName()],bw.getWeight()));
|
vertexIndexWeight[vertexID].push_back(IndexWeightEntry(boneName2PaletteIndex->second,bw.getWeight()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (boneMap.find(bw.getBoneName()) == boneMap.end())
|
BoneMap::const_iterator bonebyname;
|
||||||
|
if ((bonebyname=boneMap.find(bw.getBoneName())) == boneMap.end())
|
||||||
{
|
{
|
||||||
OSG_INFO << "RigTransformHardware::createPalette can't find bone " << bw.getBoneName() << " skip this influence" << std::endl;
|
OSG_WARN << "RigTransformHardware::createPalette can't find bone " << bw.getBoneName() << "in skeleton bonemap: skip this influence" << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
boneNameCountMap[bw.getBoneName()] = 1; // for stats
|
boneNameCountMap[bw.getBoneName()] = 1; // for stats
|
||||||
bonesForThisVertex++;
|
bonesForThisVertex++;
|
||||||
palette.push_back(boneMap[bw.getBoneName()]);
|
|
||||||
_boneNameToPalette[bw.getBoneName()] = palette.size()-1;
|
_boneNameToPalette[bw.getBoneName()] = _bonePalette.size() ;
|
||||||
vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(_boneNameToPalette[bw.getBoneName()],bw.getWeight()));
|
vertexIndexWeight[vertexID].push_back(IndexWeightEntry(_bonePalette.size(),bw.getWeight()));
|
||||||
}
|
_bonePalette.push_back(bonebyname->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OSG_WARN << "RigTransformHardware::createPalette Bone " << bw.getBoneName() << " has a weight " << bw.getWeight() << " for vertex " << vertexIndex << " this bone will not be in the palette" << std::endl;
|
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);
|
maxBonePerVertex = osg::maximum(maxBonePerVertex, bonesForThisVertex);
|
||||||
}
|
}
|
||||||
OSG_INFO << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl;
|
OSG_INFO << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl;
|
||||||
@ -136,15 +150,12 @@ bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const
|
|||||||
OSG_INFO << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl;
|
OSG_INFO << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl;
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0 ; i < (int)vertexIndexWeight.size(); i++)
|
|
||||||
vertexIndexWeight[i].resize(maxBonePerVertex);
|
|
||||||
|
|
||||||
_nbVertexes = nbVertexes;
|
|
||||||
_bonesPerVertex = maxBonePerVertex;
|
_bonesPerVertex = maxBonePerVertex;
|
||||||
_bonePalette = palette;
|
for (int i = 0 ; i < (int)vertexIndexWeight.size(); i++)
|
||||||
_vertexIndexMatrixWeightList = vertexIndexWeight;
|
vertexIndexWeight[i].resize(maxBonePerVertex);
|
||||||
|
|
||||||
_uniformMatrixPalette = createVertexUniform();
|
_uniformMatrixPalette = createVertexUniform();
|
||||||
_boneWeightAttribArrays = createVertexAttribList();
|
createVertexAttribList(*this,vertexIndexWeight,this->_boneWeightAttribArrays);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,33 +168,34 @@ bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const
|
|||||||
// the idea is to use this format to have a granularity smaller
|
// the idea is to use this format to have a granularity smaller
|
||||||
// than the 4 bones using two vertex attributes
|
// than the 4 bones using two vertex attributes
|
||||||
//
|
//
|
||||||
RigTransformHardware::BoneWeightAttribList RigTransformHardware::createVertexAttribList()
|
void createVertexAttribList(RigTransformHardware& rig,const VertexIndexWeightList& _vertexIndexMatrixWeightList, RigTransformHardware::BoneWeightAttribList& boneWeightAttribArrays)
|
||||||
{
|
{
|
||||||
BoneWeightAttribList arrayList;
|
unsigned int nbVertices= rig.getNumVertexes();
|
||||||
int nbArray = static_cast<int>(ceilf(getNumBonesPerVertex() * 0.5));
|
unsigned int maxbonepervertex=rig.getNumBonesPerVertex();
|
||||||
|
unsigned int nbArray = static_cast<unsigned int>(ceilf( ((float)maxbonepervertex) * 0.5f));
|
||||||
if (!nbArray)
|
if (!nbArray)
|
||||||
return arrayList;
|
return ;
|
||||||
|
|
||||||
arrayList.resize(nbArray);
|
boneWeightAttribArrays.resize(nbArray);
|
||||||
for (int i = 0; i < nbArray; i++)
|
for (unsigned int i = 0; i < nbArray; i++)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Vec4Array> array = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX);
|
osg::ref_ptr<osg::Vec4Array> array = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX);
|
||||||
arrayList[i] = array;
|
boneWeightAttribArrays[i] = array;
|
||||||
int nbVertexes = getNumVertexes();
|
array->resize( nbVertices);
|
||||||
array->resize(nbVertexes);
|
for (unsigned int j = 0; j < nbVertices; j++)
|
||||||
for (int j = 0; j < nbVertexes; j++)
|
|
||||||
{
|
{
|
||||||
for (int b = 0; b < 2; b++)
|
|
||||||
|
for (unsigned int b = 0; b < 2; b++)
|
||||||
{
|
{
|
||||||
// the granularity is 2 so if we have only one bone
|
// the granularity is 2 so if we have only one bone
|
||||||
// it's convenient to init the second with a weight 0
|
// it's convenient to init the second with a weight 0
|
||||||
int boneIndexInList = i*2 + b;
|
unsigned int boneIndexInList = i*2 + b;
|
||||||
int boneIndexInVec4 = b*2;
|
unsigned int boneIndexInVec4 = b*2;
|
||||||
(*array)[j][0 + boneIndexInVec4] = 0;
|
(*array)[j][0 + boneIndexInVec4] = 0;
|
||||||
(*array)[j][1 + boneIndexInVec4] = 0;
|
(*array)[j][1 + boneIndexInVec4] = 0;
|
||||||
if (boneIndexInList < getNumBonesPerVertex())
|
if (boneIndexInList < maxbonepervertex)
|
||||||
{
|
{
|
||||||
float boneIndex = static_cast<float>(_vertexIndexMatrixWeightList[j][boneIndexInList].getIndex());
|
float boneIndex = static_cast<float>(_vertexIndexMatrixWeightList[j][boneIndexInList].getBoneIndex());
|
||||||
float boneWeight = _vertexIndexMatrixWeightList[j][boneIndexInList].getWeight();
|
float boneWeight = _vertexIndexMatrixWeightList[j][boneIndexInList].getWeight();
|
||||||
// fill the vec4
|
// fill the vec4
|
||||||
(*array)[j][0 + boneIndexInVec4] = boneIndex;
|
(*array)[j][0 + boneIndexInVec4] = boneIndex;
|
||||||
@ -192,10 +204,9 @@ RigTransformHardware::BoneWeightAttribList RigTransformHardware::createVertexAtt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return arrayList;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
osg::Uniform* RigTransformHardware::createVertexUniform()
|
osg::Uniform* RigTransformHardware::createVertexUniform()
|
||||||
{
|
{
|
||||||
osg::Uniform* uniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size());
|
osg::Uniform* uniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size());
|
||||||
@ -210,6 +221,15 @@ void RigTransformHardware::setShader(osg::Shader* shader)
|
|||||||
|
|
||||||
bool RigTransformHardware::init(RigGeometry& geom)
|
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::Geometry& source = *geom.getSourceGeometry();
|
||||||
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());
|
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());
|
||||||
if (!positionSrc)
|
if (!positionSrc)
|
||||||
@ -218,72 +238,93 @@ bool RigTransformHardware::init(RigGeometry& geom)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!geom.getSkeleton())
|
|
||||||
{
|
|
||||||
OSG_WARN << "RigTransformHardware no skeleton set in geometry " << geom.getName() << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// copy shallow from source geometry to rig
|
// copy shallow from source geometry to rig
|
||||||
geom.copyFrom(source);
|
geom.copyFrom(source);
|
||||||
|
|
||||||
|
if (!createPalette(positionSrc->size(),bm,geom.getVertexInfluenceSet().getVertexToBoneList()))
|
||||||
BoneMapVisitor mapVisitor;
|
|
||||||
geom.getSkeleton()->accept(mapVisitor);
|
|
||||||
BoneMap bm = mapVisitor.getBoneMap();
|
|
||||||
|
|
||||||
if (!createPalette(positionSrc->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList()))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Program> program = new osg::Program;
|
osg::ref_ptr<osg::Program> program ;
|
||||||
program->setName("HardwareSkinning");
|
osg::ref_ptr<osg::Shader> vertexshader;
|
||||||
if (!_shader.valid())
|
osg::ref_ptr<osg::StateSet> stateset = geom.getOrCreateStateSet();
|
||||||
_shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert");
|
|
||||||
|
|
||||||
if (!_shader.valid()) {
|
//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;
|
OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace max matrix by the value from uniform
|
// replace max matrix by the value from uniform
|
||||||
{
|
{
|
||||||
std::string str = _shader->getShaderSource();
|
std::string str = vertexshader->getShaderSource();
|
||||||
std::string toreplace = std::string("MAX_MATRIX");
|
std::string toreplace = std::string("MAX_MATRIX");
|
||||||
std::size_t start = str.find(toreplace);
|
std::size_t start = str.find(toreplace);
|
||||||
|
|
||||||
if (std::string::npos != start) {
|
if (std::string::npos != start) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << getMatrixPaletteUniform()->getNumElements();
|
ss << getMatrixPaletteUniform()->getNumElements();
|
||||||
str.replace(start, toreplace.size(), ss.str());
|
str.replace(start, toreplace.size(), ss.str());
|
||||||
_shader->setShaderSource(str);
|
vertexshader->setShaderSource(str);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OSG_WARN << "MAX_MATRIX not found in Shader! " << str << std::endl;
|
OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl;
|
||||||
}
|
}
|
||||||
OSG_INFO << "Shader " << str << std::endl;
|
OSG_INFO << "Shader " << str << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int attribIndex = 11;
|
unsigned int attribIndex = 11;
|
||||||
int nbAttribs = getNumVertexAttrib();
|
unsigned int nbAttribs = getNumVertexAttrib();
|
||||||
for (int i = 0; i < nbAttribs; i++)
|
if(nbAttribs==0)
|
||||||
|
OSG_WARN << "nbAttribs== " << nbAttribs << std::endl;
|
||||||
|
for (unsigned int i = 0; i < nbAttribs; i++)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "boneWeight" << i;
|
ss << "boneWeight" << i;
|
||||||
program->addBindAttribLocation(ss.str(), attribIndex + 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));
|
geom.setVertexAttribArray(attribIndex + i, getVertexAttrib(i));
|
||||||
OSG_INFO << "set vertex attrib " << ss.str() << std::endl;
|
OSG_INFO << "set vertex attrib " << ss.str() << std::endl;
|
||||||
}
|
}
|
||||||
program->addShader(_shader.get());
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> ss = geom.getOrCreateStateSet();
|
program->addShader(vertexshader.get());
|
||||||
ss->addUniform(getMatrixPaletteUniform());
|
|
||||||
ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex()));
|
stateset->removeUniform("matrixPalette");
|
||||||
ss->setAttributeAndModes(program.get());
|
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;
|
_needInit = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RigTransformHardware::operator()(RigGeometry& geom)
|
void RigTransformHardware::operator()(RigGeometry& geom)
|
||||||
{
|
{
|
||||||
if (_needInit)
|
if (_needInit)
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <osgAnimation/BoneMapVisitor>
|
#include <osgAnimation/BoneMapVisitor>
|
||||||
#include <osgAnimation/RigGeometry>
|
#include <osgAnimation/RigGeometry>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
using namespace osgAnimation;
|
using namespace osgAnimation;
|
||||||
|
|
||||||
RigTransformSoftware::RigTransformSoftware()
|
RigTransformSoftware::RigTransformSoftware()
|
||||||
@ -33,6 +34,45 @@ RigTransformSoftware::RigTransformSoftware(const RigTransformSoftware& rts,const
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort by name and weight
|
||||||
|
struct SortByNameAndWeight : public std::less<VertexInfluenceSet::BoneWeight>
|
||||||
|
{
|
||||||
|
bool operator()(const VertexInfluenceSet::BoneWeight& b0,
|
||||||
|
const VertexInfluenceSet::BoneWeight& 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<VertexInfluenceSet::BoneWeightList>
|
||||||
|
{
|
||||||
|
bool operator()(const VertexInfluenceSet::BoneWeightList& b0,
|
||||||
|
const VertexInfluenceSet::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)
|
bool RigTransformSoftware::init(RigGeometry& geom)
|
||||||
{
|
{
|
||||||
if (!geom.getSkeleton())
|
if (!geom.getSkeleton())
|
||||||
@ -41,12 +81,34 @@ bool RigTransformSoftware::init(RigGeometry& geom)
|
|||||||
BoneMapVisitor mapVisitor;
|
BoneMapVisitor mapVisitor;
|
||||||
geom.getSkeleton()->accept(mapVisitor);
|
geom.getSkeleton()->accept(mapVisitor);
|
||||||
BoneMap bm = mapVisitor.getBoneMap();
|
BoneMap bm = mapVisitor.getBoneMap();
|
||||||
initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexSetToBoneSetList());
|
initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexGroupList());
|
||||||
|
|
||||||
if (geom.getSourceGeometry())
|
if (geom.getSourceGeometry())
|
||||||
geom.copyFrom(*geom.getSourceGeometry());
|
geom.copyFrom(*geom.getSourceGeometry());
|
||||||
geom.setVertexArray(0);
|
|
||||||
geom.setNormalArray(0);
|
|
||||||
|
osg::Vec3Array* normalSrc = dynamic_cast<osg::Vec3Array*>(geom.getSourceGeometry()->getNormalArray());
|
||||||
|
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(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;
|
_needInit = false;
|
||||||
return true;
|
return true;
|
||||||
@ -65,74 +127,50 @@ void RigTransformSoftware::operator()(RigGeometry& geom)
|
|||||||
osg::Geometry& source = *geom.getSourceGeometry();
|
osg::Geometry& source = *geom.getSourceGeometry();
|
||||||
osg::Geometry& destination = geom;
|
osg::Geometry& destination = geom;
|
||||||
|
|
||||||
osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());
|
osg::Vec3Array* positionSrc = static_cast<osg::Vec3Array*>(source.getVertexArray());
|
||||||
osg::Vec3Array* positionDst = dynamic_cast<osg::Vec3Array*>(destination.getVertexArray());
|
osg::Vec3Array* positionDst = static_cast<osg::Vec3Array*>(destination.getVertexArray());
|
||||||
if (positionSrc )
|
|
||||||
{
|
|
||||||
if (!positionDst || (positionDst->size() != positionSrc->size()) )
|
|
||||||
{
|
|
||||||
if (!positionDst)
|
|
||||||
{
|
|
||||||
positionDst = new osg::Vec3Array;
|
|
||||||
positionDst->setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
destination.setVertexArray(positionDst);
|
|
||||||
}
|
|
||||||
*positionDst = *positionSrc;
|
|
||||||
}
|
|
||||||
if (!positionDst->empty())
|
|
||||||
{
|
|
||||||
compute<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
|
|
||||||
geom.getInvMatrixFromSkeletonToGeometry(),
|
|
||||||
&positionSrc->front(),
|
|
||||||
&positionDst->front());
|
|
||||||
positionDst->dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec3Array* normalSrc = dynamic_cast<osg::Vec3Array*>(source.getNormalArray());
|
osg::Vec3Array* normalSrc = dynamic_cast<osg::Vec3Array*>(source.getNormalArray());
|
||||||
osg::Vec3Array* normalDst = dynamic_cast<osg::Vec3Array*>(destination.getNormalArray());
|
osg::Vec3Array* normalDst = static_cast<osg::Vec3Array*>(destination.getNormalArray());
|
||||||
|
|
||||||
|
|
||||||
|
compute<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
|
||||||
|
geom.getInvMatrixFromSkeletonToGeometry(),
|
||||||
|
&positionSrc->front(),
|
||||||
|
&positionDst->front());
|
||||||
|
positionDst->dirty();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (normalSrc )
|
if (normalSrc )
|
||||||
{
|
{
|
||||||
if (!normalDst || (normalDst->size() != normalSrc->size()) )
|
|
||||||
{
|
|
||||||
if (!normalDst)
|
|
||||||
{
|
|
||||||
normalDst = new osg::Vec3Array;
|
|
||||||
normalDst->setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
destination.setNormalArray(normalDst, osg::Array::BIND_PER_VERTEX);
|
|
||||||
}
|
|
||||||
*normalDst = *normalSrc;
|
|
||||||
}
|
|
||||||
if (!normalDst->empty())
|
|
||||||
{
|
|
||||||
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();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence)
|
///convert BoneWeight to BonePtrWeight using bonemap
|
||||||
|
void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexGroupList& vertexgroups)
|
||||||
{
|
{
|
||||||
_boneSetVertexSet.clear();
|
_uniqInfluenceSet2VertIDList.clear();
|
||||||
|
|
||||||
int size = influence.size();
|
int size = vertexgroups.size();
|
||||||
_boneSetVertexSet.resize(size);
|
_uniqInfluenceSet2VertIDList.resize(size);
|
||||||
for (int i = 0; i < size; i++)
|
//for (VertexInfluenceSet::UniqVertexGroupList::const_iterator vgit=vertexgroups.begin(); vgit!=vertexgroups.end();vgit++)
|
||||||
|
for(int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
const VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i];
|
const VertexInfluenceSet::VertexGroup& vg = vertexgroups[i];
|
||||||
int nbBones = inf.getBones().size();
|
int nbBones = vg.getBones().size();
|
||||||
BoneWeightList& boneList = _boneSetVertexSet[i].getBones();
|
BonePtrWeightList& boneList = _uniqInfluenceSet2VertIDList[i].getBoneWeights();
|
||||||
|
|
||||||
double sumOfWeight = 0;
|
double sumOfWeight = 0;
|
||||||
for (int b = 0; b < nbBones; b++)
|
for (int b = 0; b < nbBones; b++)
|
||||||
{
|
{
|
||||||
const std::string& bname = inf.getBones()[b].getBoneName();
|
const std::string& bname = vg.getBones()[b].getBoneName();
|
||||||
float weight = inf.getBones()[b].getWeight();
|
float weight = vg.getBones()[b].getWeight();
|
||||||
BoneMap::const_iterator it = map.find(bname);
|
BoneMap::const_iterator it = map.find(bname);
|
||||||
if (it == map.end() )
|
if (it == map.end() )
|
||||||
{
|
{
|
||||||
@ -143,18 +181,18 @@ void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const Vert
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Bone* bone = it->second.get();
|
Bone* bone = it->second.get();
|
||||||
boneList.push_back(BoneWeight(bone, weight));
|
boneList.push_back(BonePtrWeight(bone, weight));
|
||||||
sumOfWeight += weight;
|
sumOfWeight += weight;
|
||||||
}
|
}
|
||||||
// if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0
|
// 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
|
// so we check it and renormalize the all weight bone
|
||||||
const double threshold = 1e-4;
|
/*const double threshold = 1e-4;
|
||||||
if (!_boneSetVertexSet[i].getBones().empty() &&
|
if (!_boneSetVertexSet[i].getBones().empty() &&
|
||||||
(sumOfWeight < 1.0 - threshold || sumOfWeight > 1.0 + threshold))
|
(sumOfWeight < 1.0 - threshold || sumOfWeight > 1.0 + threshold))
|
||||||
{
|
{
|
||||||
for (int b = 0; b < (int)boneList.size(); b++)
|
for (int b = 0; b < (int)boneList.size(); b++)
|
||||||
boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight);
|
boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight);
|
||||||
}
|
}*/
|
||||||
_boneSetVertexSet[i].getVertexes() = inf.getVertexes();
|
_uniqInfluenceSet2VertIDList[i].getVertexes() = vg.getVertexes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,16 +16,21 @@
|
|||||||
#include <osg/Notify>
|
#include <osg/Notify>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
using namespace osgAnimation;
|
using namespace osgAnimation;
|
||||||
|
|
||||||
void VertexInfluenceSet::addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); }
|
void VertexInfluenceSet::addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); }
|
||||||
const VertexInfluenceSet::VertexIndexToBoneWeightMap& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;}
|
const VertexInfluenceSet::VertIDToBoneWeightList& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;}
|
||||||
// this class manage VertexInfluence database by mesh
|
// this class manage VertexInfluence database by mesh
|
||||||
// reference bones per vertex ...
|
// reference bones per vertex ...
|
||||||
void VertexInfluenceSet::buildVertex2BoneList()
|
|
||||||
|
void VertexInfluenceSet::buildVertex2BoneList(unsigned int numvertices)
|
||||||
{
|
{
|
||||||
_vertex2Bones.clear();
|
_vertex2Bones.clear();
|
||||||
|
_vertex2Bones.reserve(numvertices);
|
||||||
|
_vertex2Bones.resize(numvertices);
|
||||||
|
|
||||||
for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); ++it)
|
for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); ++it)
|
||||||
{
|
{
|
||||||
const VertexInfluence& vi = (*it);
|
const VertexInfluence& vi = (*it);
|
||||||
@ -35,23 +40,25 @@ void VertexInfluenceSet::buildVertex2BoneList()
|
|||||||
VertexIndexWeight viw = vi[i];
|
VertexIndexWeight viw = vi[i];
|
||||||
int index = viw.first;
|
int index = viw.first;
|
||||||
float weight = viw.second;
|
float weight = viw.second;
|
||||||
if (vi.getName().empty())
|
if (vi.getName().empty()){
|
||||||
OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl;
|
OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl;
|
||||||
|
}
|
||||||
_vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight));
|
_vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalize weight per vertex
|
// normalize weight per vertex
|
||||||
for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it)
|
unsigned int vertid=0;
|
||||||
|
for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertid)
|
||||||
{
|
{
|
||||||
BoneWeightList& bones = it->second;
|
BoneWeightList& bones =*it;
|
||||||
int size = bones.size();
|
int size = bones.size();
|
||||||
float sum = 0;
|
float sum = 0;
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
sum += bones[i].getWeight();
|
sum += bones[i].getWeight();
|
||||||
if (sum < 1e-4)
|
if (sum < 1e-4)
|
||||||
{
|
{
|
||||||
OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " << it->first << " seems to have 0 weight, skip normalize for this vertex" << std::endl;
|
OSG_WARN << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " <<vertid << " seems to have 0 weight, skip normalize for this vertex" << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -109,17 +116,17 @@ void VertexInfluenceSet::clear()
|
|||||||
_uniqVertexSetToBoneSet.clear();
|
_uniqVertexSetToBoneSet.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexInfluenceSet::buildUniqVertexSetToBoneSetList()
|
void VertexInfluenceSet::buildUniqVertexGroupList()
|
||||||
{
|
{
|
||||||
_uniqVertexSetToBoneSet.clear();
|
_uniqVertexSetToBoneSet.clear();
|
||||||
|
|
||||||
typedef std::map<BoneWeightList,UniqVertexSetToBoneSet, SortByBoneWeightList> UnifyBoneGroup;
|
typedef std::map<BoneWeightList,VertexGroup, SortByBoneWeightList> UnifyBoneGroup;
|
||||||
UnifyBoneGroup unifyBuffer;
|
UnifyBoneGroup unifyBuffer;
|
||||||
|
|
||||||
for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it)
|
unsigned int vertexID=0;
|
||||||
|
for (VertIDToBoneWeightList::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); ++it,++vertexID)
|
||||||
{
|
{
|
||||||
BoneWeightList bones = it->second;
|
BoneWeightList bones = *it;
|
||||||
int vertexIndex = it->first;
|
|
||||||
|
|
||||||
// sort the vector to have a consistent key
|
// sort the vector to have a consistent key
|
||||||
std::sort(bones.begin(), bones.end(), SortByNameAndWeight());
|
std::sort(bones.begin(), bones.end(), SortByNameAndWeight());
|
||||||
@ -128,10 +135,12 @@ void VertexInfluenceSet::buildUniqVertexSetToBoneSetList()
|
|||||||
UnifyBoneGroup::iterator result = unifyBuffer.find(bones);
|
UnifyBoneGroup::iterator result = unifyBuffer.find(bones);
|
||||||
if (result == unifyBuffer.end())
|
if (result == unifyBuffer.end())
|
||||||
unifyBuffer[bones].setBones(bones);
|
unifyBuffer[bones].setBones(bones);
|
||||||
unifyBuffer[bones].getVertexes().push_back(vertexIndex);
|
unifyBuffer[bones].getVertexes().push_back(vertexID);
|
||||||
}
|
}
|
||||||
|
|
||||||
_uniqVertexSetToBoneSet.reserve(unifyBuffer.size());
|
_uniqVertexSetToBoneSet.reserve(unifyBuffer.size());
|
||||||
|
|
||||||
|
|
||||||
for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it)
|
for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); ++it)
|
||||||
{
|
{
|
||||||
_uniqVertexSetToBoneSet.push_back(it->second);
|
_uniqVertexSetToBoneSet.push_back(it->second);
|
||||||
|
Loading…
Reference in New Issue
Block a user