public void ApplyToVertexData( VertexData data, float time, float weight, List<Pose> poseList )
{
// Nothing to do if no keyframes
if ( keyFrameList.Count == 0 )
return;
// Get keyframes
KeyFrame kf1, kf2;
short firstKeyIndex;
float t = GetKeyFramesAtTime( time, out kf1, out kf2, out firstKeyIndex );
if ( animationType == VertexAnimationType.Morph )
{
VertexMorphKeyFrame vkf1 = (VertexMorphKeyFrame)kf1;
VertexMorphKeyFrame vkf2 = (VertexMorphKeyFrame)kf2;
if ( targetMode == VertexAnimationTargetMode.Hardware )
{
// If target mode is hardware, need to bind our 2 keyframe buffers,
// one to main pos, one to morph target texcoord
Debug.Assert( data.HWAnimationDataList.Count == 0,
"Haven't set up hardware vertex animation elements!" );
// no use for TempBlendedBufferInfo here btw
// NB we assume that position buffer is unshared
// VertexDeclaration::getAutoOrganisedDeclaration should see to that
VertexElement posElem =
data.vertexDeclaration.FindElementBySemantic( VertexElementSemantic.Position );
// Set keyframe1 data as original position
data.vertexBufferBinding.SetBinding( posElem.Source, vkf1.VertexBuffer );
// Set keyframe2 data as derived
data.vertexBufferBinding.SetBinding( data.HWAnimationDataList[ 0 ].TargetVertexElement.Source,
vkf2.VertexBuffer );
// save T for use later
data.HWAnimationDataList[ 0 ].Parametric = t;
}
else
{
// If target mode is software, need to software interpolate each vertex
Mesh.SoftwareVertexMorph( t, vkf1.VertexBuffer, vkf2.VertexBuffer, data );
}
}
else
{
// Pose
VertexPoseKeyFrame vkf1 = (VertexPoseKeyFrame)kf1;
VertexPoseKeyFrame vkf2 = (VertexPoseKeyFrame)kf2;
// For each pose reference in key 1, we need to locate the entry in
// key 2 and interpolate the influence
List<PoseRef> poseRefList1 = vkf1.PoseRefs;
List<PoseRef> poseRefList2 = vkf2.PoseRefs;
foreach ( PoseRef p1 in poseRefList1 )
{
float startInfluence = p1.Influence;
float endInfluence = 0;
// Search for entry in keyframe 2 list (if not there, will be 0)
foreach ( PoseRef p2 in poseRefList2 )
{
if ( p1.PoseIndex == p2.PoseIndex )
{
endInfluence = p2.Influence;
break;
}
}
// Interpolate influence
float influence = startInfluence + t * ( endInfluence - startInfluence );
// Scale by animation weight
influence = weight * influence;
// Get pose
Debug.Assert( p1.PoseIndex <= poseList.Count );
Pose pose = poseList[ p1.PoseIndex ];
// apply
ApplyPoseToVertexData( pose, data, influence );
}
// Now deal with any poses in key 2 which are not in key 1
foreach ( PoseRef p2 in poseRefList2 )
{
bool found = false;
foreach ( PoseRef p1 in poseRefList1 )
{
if ( p1.PoseIndex == p2.PoseIndex )
{
found = true;
break;
}
}
if ( !found )
{
// Need to apply this pose too, scaled from 0 start
float influence = t * p2.Influence;
// Scale by animation weight
influence = weight * influence;
// Get pose
Debug.Assert( p2.PoseIndex <= poseList.Count );
Pose pose = poseList[ p2.PoseIndex ];
// apply
ApplyPoseToVertexData( pose, data, influence );
}
} // key 2 iteration
} // morph or pose animation
}