@ -1,5 +1,7 @@
# include "riggeometry.hpp"
# include <unordered_map>
# include <osg/MatrixTransform>
# include <osgUtil/CullVisitor>
@ -10,39 +12,10 @@
# include "skeleton.hpp"
# include "util.hpp"
namespace
{
inline void accumulateMatrix (
const osg : : Matrixf & invBindMatrix , const osg : : Matrixf & matrix , const float weight , osg : : Matrixf & result )
{
osg : : Matrixf m = invBindMatrix * matrix ;
float * ptr = m . ptr ( ) ;
float * ptrresult = result . ptr ( ) ;
ptrresult [ 0 ] + = ptr [ 0 ] * weight ;
ptrresult [ 1 ] + = ptr [ 1 ] * weight ;
ptrresult [ 2 ] + = ptr [ 2 ] * weight ;
ptrresult [ 4 ] + = ptr [ 4 ] * weight ;
ptrresult [ 5 ] + = ptr [ 5 ] * weight ;
ptrresult [ 6 ] + = ptr [ 6 ] * weight ;
ptrresult [ 8 ] + = ptr [ 8 ] * weight ;
ptrresult [ 9 ] + = ptr [ 9 ] * weight ;
ptrresult [ 10 ] + = ptr [ 10 ] * weight ;
ptrresult [ 12 ] + = ptr [ 12 ] * weight ;
ptrresult [ 13 ] + = ptr [ 13 ] * weight ;
ptrresult [ 14 ] + = ptr [ 14 ] * weight ;
}
}
namespace SceneUtil
{
RigGeometry : : RigGeometry ( )
: mSkeleton ( nullptr )
, mLastFrameNumber ( 0 )
, mBoundsFirstFrame ( true )
{
setNumChildrenRequiringUpdateTraversal ( 1 ) ;
// update done in accept(NodeVisitor&)
@ -50,12 +23,7 @@ namespace SceneUtil
RigGeometry : : RigGeometry ( const RigGeometry & copy , const osg : : CopyOp & copyop )
: Drawable ( copy , copyop )
, mSkeleton ( nullptr )
, mInfluenceMap ( copy . mInfluenceMap )
, mBone2VertexVector ( copy . mBone2VertexVector )
, mBoneSphereVector ( copy . mBoneSphereVector )
, mLastFrameNumber ( 0 )
, mBoundsFirstFrame ( true )
, mData ( copy . mData )
{
setSourceGeometry ( copy . mSourceGeometry ) ;
setNumChildrenRequiringUpdateTraversal ( 1 ) ;
@ -151,42 +119,18 @@ namespace SceneUtil
return false ;
}
if ( ! m InfluenceMap )
if ( ! m Data )
{
Log ( Debug : : Error ) < < " Error: No InfluenceMap set on RigGeometry" ;
Log ( Debug : : Error ) < < " Error: No influence data set on RigGeometry" ;
return false ;
}
mBoneNodesVector . clear ( ) ;
for ( auto & bonePair : mBoneSphereVector - > mData )
{
const std : : string & boneName = bonePair . first ;
Bone * bone = mSkeleton - > getBone ( boneName ) ;
if ( ! bone )
{
mBoneNodesVector . push_back ( nullptr ) ;
Log ( Debug : : Error ) < < " Error: RigGeometry did not find bone " < < boneName ;
continue ;
}
mBoneNodesVector . push_back ( bone ) ;
}
for ( auto & pair : mBone2VertexVector - > mData )
{
for ( auto & weight : pair . first )
mNodes . clear ( ) ;
for ( const BoneInfo & info : mData - > mBones )
{
const std : : string & boneName = weight . first . first ;
Bone * bone = mSkeleton - > getBone ( boneName ) ;
if ( ! bone )
{
mBoneNodesVector . push_back ( nullptr ) ;
Log ( Debug : : Error ) < < " Error: RigGeometry did not find bone " < < boneName ;
continue ;
}
mBoneNodesVector . push_back ( bone ) ;
}
mNodes . push_back ( mSkeleton - > getBone ( info . mName ) ) ;
if ( ! mNodes . back ( ) )
Log ( Debug : : Error ) < < " Error: RigGeometry did not find bone " < < info . mName ;
}
return true ;
@ -226,25 +170,28 @@ namespace SceneUtil
osg : : Vec3Array * normalDst = static_cast < osg : : Vec3Array * > ( geom . getNormalArray ( ) ) ;
osg : : Vec4Array * tangentDst = static_cast < osg : : Vec4Array * > ( geom . getTexCoordArray ( 7 ) ) ;
int index = mBoneSphereVector - > mData . size ( ) ;
for ( auto & pair : mBone2VertexVector - > mData )
for ( const auto & [ influences , vertices ] : mData - > mInfluences )
{
osg : : Matrixf resultMat ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ) ;
for ( auto& weight : pair . first )
for ( const auto & [ index , weight ] : influences )
{
Bone * bone = m Bone NodesVector [ index ] ;
const Bone * bone = m Nodes[ index ] ;
if ( bone = = nullptr )
continue ;
accumulateMatrix ( weight . first . second , bone - > mMatrixInSkeletonSpace , weight . second , resultMat ) ;
index + + ;
osg : : Matrixf boneMat = mData - > mBones [ index ] . mInvBindMatrix * bone - > mMatrixInSkeletonSpace ;
float * boneMatPtr = boneMat . ptr ( ) ;
float * resultMatPtr = resultMat . ptr ( ) ;
for ( int i = 0 ; i < 16 ; + + i , + + resultMatPtr , + + boneMatPtr )
if ( i % 4 ! = 3 )
* resultMatPtr + = * boneMatPtr * weight ;
}
if ( mGeomToSkelMatrix )
resultMat * = ( * mGeomToSkelMatrix ) ;
for ( auto & vertex : pair . second )
for ( unsigned short vertex : vertices )
{
( * positionDst ) [ vertex ] = resultMat . preMult ( ( * positionSrc ) [ vertex ] ) ;
if ( normalDst )
@ -291,15 +238,14 @@ namespace SceneUtil
osg : : BoundingBox box ;
in t index = 0 ;
for ( auto& boundPair : mBoneSphereVector - > mData )
size_ t index = 0 ;
for ( const BoneInfo & info : mData - > mBones )
{
Bone * bone = m Bone NodesVector [ index ] ;
const Bone * bone = m Nodes[ index + + ] ;
if ( bone = = nullptr )
continue ;
index + + ;
osg : : BoundingSpheref bs = boundPair . second ;
osg : : BoundingSpheref bs = info . mBoundSphere ;
if ( mGeomToSkelMatrix )
transformBoundingSphere ( bone - > mMatrixInSkeletonSpace * ( * mGeomToSkelMatrix ) , bs ) ;
else
@ -357,35 +303,26 @@ namespace SceneUtil
void RigGeometry : : setInfluenceMap ( osg : : ref_ptr < InfluenceMap > influenceMap )
{
mInfluenceMap = influenceMap ;
typedef std : : map < unsigned short , std : : vector < BoneWeight > > Vertex2BoneMap ;
Vertex2BoneMap vertex2BoneMap ;
mBoneSphereVector = new BoneSphereVector ;
mBoneSphereVector - > mData . reserve ( mInfluenceMap - > mData . size ( ) ) ;
mBone2VertexVector = new Bone2VertexVector ;
for ( auto & influencePair : mInfluenceMap - > mData )
{
const std : : string & boneName = influencePair . first ;
const BoneInfluence & bi = influencePair . second ;
mBoneSphereVector - > mData . emplace_back ( boneName , bi . mBoundSphere ) ;
mData = new InfluenceData ;
mData - > mBones . reserve ( influenceMap - > mData . size ( ) ) ;
for ( auto & weightPair : bi . mWeights )
std : : unordered_map < unsigned short , std : : vector < BoneWeight > > vertexToInfluences ;
size_t index = 0 ;
for ( const auto & [ boneName , bi ] : influenceMap - > mData )
{
std : : vector < BoneWeight > & vec = vertex2BoneMap [ weightPair . first ] ;
mData - > mBones . push_back ( { boneName , bi . mBoundSphere , bi . mInvBindMatrix } ) ;
vec . emplace_back ( std : : make_pair ( boneName , bi . mInvBindMatrix ) , weightPair . second ) ;
}
for ( const auto & [ vertex , weight ] : bi . mWeights )
vertexToInfluences [ vertex ] . emplace_back ( index , weight ) ;
index + + ;
}
Bone2VertexMap bone2VertexMap ;
for ( auto & vertexPair : vertex2BoneMap )
{
bone2VertexMap [ vertexPair . second ] . emplace_back ( vertexPair . first ) ;
}
std : : map < std : : vector < BoneWeight > , VertexList > influencesToVertices ;
for ( const auto & [ vertex , weights ] : vertexToInfluences )
influencesToVertices [ weights ] . emplace_back ( vertex ) ;
m Bone2VertexVector- > mData . reserve ( bone2VertexMap . size ( ) ) ;
m Bone2VertexVector- > mData . assign ( bone2VertexMap . begin ( ) , bone2VertexMap . end ( ) ) ;
mData - > mInfluences . reserve ( influencesToVertices . size ( ) ) ;
m Data- > mInfluences . assign ( influencesToVertices . begin ( ) , influencesToVertices . end ( ) ) ;
}
void RigGeometry : : accept ( osg : : NodeVisitor & nv )