Morph Targets |
This topic contains the following sections:
Meshes support morph target animation (a.k.a. per-vertex animation, blend shape interpolation, or just morphing). Morph targets (a.k.a. blend shapes) can be used for a variety of things:
But the most prominent application is facial animation. In the past, there have been games that relied solely on skeletal animation for facial animation, but modern games typically use a combination of skeletal animation and morph targets.
Morph targets are stored per submesh in the MorphTargets collection. Morph targets are identified by their name (e.g. "smile", "frown", "blink", etc.). The morph target stores the vertices relative to the submesh, i.e. only the difference between the morph target and the base mesh is stored (a.k.a. delta shapes").
The MorphWeights stored by the MeshNode control the morph targets. Morph target weights can be set directly or animated using DigitalRune Animation.
// Show the morph target named "smile". meshNode.MorphWeights["smile"] = 1.0f;
The following video demonstrates the use of morph targets for facial animation:
The topic Asset Creation: Morph Targets explains how to load morph targets using the XNA content pipeline.
Mesh deformations are calculated on the GPU. Therefore the model requires a special effects. See Predefined Effects. Here is an example material:
<?xml version="1.0" encoding="utf-8"?> <Material> <Pass Name="ShadowMap" Effect="DigitalRune/Materials/ShadowMapMorphSkinned" Profile="HiDef" /> <Pass Name="GBuffer" Effect="DigitalRune/Materials/GBufferMorphSkinned" Profile="HiDef"> <Parameter Name="SpecularPower" Value="75" /> </Pass> <Pass Name="Material" Effect="DigitalRune/Materials/MaterialMorphSkinned" Profile="HiDef"> <Parameter Name="DiffuseColor" Value="1,0.9,0.8,1" /> <Parameter Name="SpecularColor" Value="1,0.81,0.64,1" /> <Texture Name="DiffuseTexture" File="sintel_face_diff.png" /> </Pass> </Material>
The property MorphWeights implements the interface IAnimatableObject, which means it can be animated using DigitalRune Animation. For example:
var smile = new SingleKeyFrameAnimation { TargetProperty = "MOUTH-smile" }; smile.KeyFrames.Add(new KeyFrame<float>(TimeSpan.FromSeconds(0), 0)); smile.KeyFrames.Add(new KeyFrame<float>(TimeSpan.FromSeconds(1), 1)); smile.KeyFrames.Add(new KeyFrame<float>(TimeSpan.FromSeconds(4), 1)); smile.KeyFrames.Add(new KeyFrame<float>(TimeSpan.FromSeconds(5), 0)); var blink = new SingleKeyFrameAnimation { TargetProperty = "EYES-closed" }; blink.KeyFrames.Add(new KeyFrame<float>(TimeSpan.FromSeconds(3.75), 0)); blink.KeyFrames.Add(new KeyFrame<float>(TimeSpan.FromSeconds(4), 1)); blink.KeyFrames.Add(new KeyFrame<float>(TimeSpan.FromSeconds(4.25), 0)); var timelineGroup = new TimelineGroup(); timelineGroup.Add(smile); timelineGroup.Add(blink); var controller = AnimationService.StartAnimation(timelineGroup, meshNode.MorphWeights);
All features of DigitalRune Animation (composition, blending, transitions, …) can be directly applied to morph targets.
Meshes with morph targets are rendered by the MeshRenderer as usual. The predefined material shaders support up to 5 active morph targets simultaneously. When more morph targets are activated only the 5 morph targets with the largest morph weights are rendered.