// produce animation data
#if 1
for( int i = 0; i < count; ++i )
{
m_positions[ i ] = animSource->m_positions[ i ];
m_rotations[ i ] = animSource->m_rotations[ i ];
m_scales[ i ] = animSource->m_scales[ i ];
m_factors[ i ] = animSource->m_factors[ i ];
}
if( count > 0 )
{
Vec3 off = m_bonePositions[ 0 ] - posns[ 0 ];
m_positions[ 0 ] += m_invSkinOffsets[ 0 ].TransformNormal( off );
}
Mat4 skinXF[ SGRX_MAX_MESH_BONES ];
for( int i = 0; i < count; ++i )
{
skinXF[ i ] = m_mesh->m_bones[ i ].boneOffset;
if( i > 0 )
{
int pid = GetParentBoneID( i );
skinXF[ i ] = skinXF[ i ] * skinXF[ pid ];
}
// gather average global target/local original child pos.
Vec3 avgtgt = V3(0);
Vec3 avgpos = V3(0);
int cc = 0;
for( int ch = i + 1; ch < count; ++ch )
{
if( GetParentBoneID( ch ) != i )
continue;
avgtgt += m_bonePositions[ ch ];
avgpos += posns[ ch ];
cc++;
}
if( cc == 0 )
continue;
avgpos /= cc;
avgtgt /= cc;
Mat4 curxf = Mat4::CreateSRT( m_scales[ i ], m_rotations[ i ], m_positions[ i ] );
Mat4 inv = Mat4::Identity;
( curxf * skinXF[ i ] ).InvertTo( inv );
avgtgt = inv.TransformPos( avgtgt ).Normalized();
avgpos = m_invSkinOffsets[ i ].TransformPos( avgpos ).Normalized();
m_rotations[ i ] = m_rotations[ i ] * Quat::CreateAxisAxis( avgpos, avgtgt );
skinXF[ i ] = Mat4::CreateSRT(
m_scales[ i ], m_rotations[ i ], m_positions[ i ] ) * skinXF[ i ];
m_factors[ i ] = 1;
}
#else
for( int i = 0; i < count; ++i )
{
m_positions[ i ] = animSource->m_positions[ i ];
m_rotations[ i ] = animSource->m_rotations[ i ];
m_scales[ i ] = animSource->m_scales[ i ];
m_factors[ i ] = animSource->m_factors[ i ];
int pid = GetParentBoneID( i );
if( pid >= 0 )
{
// rotate bone with axis/angle in bone space
Vec3 nmdir = m_bonePositions[ i ] - m_bonePositions[ pid ];
Vec3 omdir = dirs[ i ];
Vec3 tf_nmdir = m_invSkinOffsets[ i ].TransformNormal( nmdir ).Normalized();
Vec3 tf_omdir = m_invSkinOffsets[ i ].TransformNormal( omdir ).Normalized();
m_rotations[ i ] = m_rotations[ i ] * Quat::CreateAxisAxis( tf_omdir, tf_nmdir );
// rotate child bones backwards
for( int ch = i + 1; ch < count; ++ch )
{
if( GetParentBoneID( ch ) != i )
continue;
tf_nmdir = m_invSkinOffsets[ ch ].TransformNormal( nmdir ).Normalized();
tf_omdir = m_invSkinOffsets[ ch ].TransformNormal( omdir ).Normalized();
m_rotations[ ch ] = m_rotations[ ch ] * Quat::CreateAxisAxis( tf_nmdir, tf_omdir );
}
}
else
{
// move bone set in world space
m_positions[ i ] += m_invSkinOffsets[ i ].TransformNormal( m_bonePositions[ i ] - posns[ i ] );
}
m_factors[ i ] = 1;
}
#endif
Comments