动画类型

来源:互联网 发布:淘宝u站营销导购平台 编辑:程序博客网 时间:2024/05/12 19:41

载入动画模型

本节你将创建一个叫做AnimatedModel的用于实时处理骨骼动画模型的类,这个类包含载入模型,播放和更新动画,绘制模型的方法,AnimatedModel类中开始时先声明变量。

动画模型以XNA Model的形式被载入,它有一个dictionary,此dictionary包含一个可以通过Tag属性访问的AnimatedModelData对象。通过这种方式,Model类包含了模型的网格和effect,而AnimatedModelData包含模型的骨骼和动画。你声明了类型为Modelmodel变量和类型为AnimatedModelDataanimatedModel变量,你将模型的变换信息存储在一个类型为Transformation的变量中。

Model model;

AnimatedModelData animatedModelData;

Transformation transformation;     

你还需要声明一些变量处理如何重建动画。你需要存储当前播放的动画、当前帧和动画的时间。你声明activeAnimation变量存储当前播放的动画,activeAnimationKeyframeIndexactiveAnimationTime存储当前动画帧和时间:

AnimationData activeAnimation;

int activeAnimationKeyframe; 

TimeSpan activeAnimationTime;      

你还需要声明两个变量用来设置动画速度和开启动画循环——enableAnimationLoop animationSpeed

bool enableAnimationLoop; 

float animationSpeed;      

当模型正在进行动画时,你使用一些临时矩阵数组用来计算骨骼bone的最后配置。因为bone的配置是作为一个动画改变的,所以你要声明bone变量存储每个bone的本地配置。你还要声明bonesAbsolute变量存储每个bone的绝对配置,这个配置由bone数组计算得出,用在实时动画中。最后你应声明bonesAnimation变量存储每个bone的最后变换,这个变换用于将顶点放置到bone的坐标系统内,并使用每个bone的绝对配置使它们动起来。我们会在骨骼动画公式一节中详细解释细节。

Matrix[] bones; 

Matrix[] bonesAbsolute; 

Matrix[] bonesAnimation;

要能把自定义变换作用到bone上,你还要声明一个矩阵数组。你可以独立于动画使用自定义变换改变骨骼的bone。例如,你可以对角色骨骼的脖子bone作用一个自定义的旋转:

Matrix[] bonesTransform;

最后,你需要声明两个变量存储动画模型的effect和材质:

AnimatedModelEffect animatedModelEffect; 

LightMaterial lightMaterial;

你创建了AnimatedModelEffect类封装了模型的effect,可以使用第8章中创建的LightMaterial类设置它。

载入动画模型

动画模型是作为一个XNA Model存储的,所以第一步是使用素材管理器载入一个XNA Model,然后你需要检查这个模型是否是动画模型-是否在模型的Tag属性中包含一个拥有AnimatedModelData对象的dictionary

model = Game.Content.Load<Model>( GameAssetsPath.MODELS_PATH + modelFileName); 

// Get the dictionary 

Dictionary<string, object> modelTag =(Dictionary<string, object>)model.Tag; 

if (modelTag == null) 

    throw new InvalidOperationException("This is not a valid animated model."); 

// Get the AnimatedModelData from the dictionary 

if (modelTag.ContainsKey("AnimatedModelData")) 

    animatedModelData = (AnimatedModelData)modelTag["AnimatedModelData"]; 

else 

    throw new InvalidOperationException("This is not a valid animated model.");        

载入模型后,你需要初始化一些用来设置和重新生成动画的变量。默认模型动画被设置为AnimatedModelData对象中的动画序列的第一个,它被存储在activeAnimation变量中:

if (animatedModelData.Animations.Length > 0) 

    activeAnimation = animatedModelData.Animations[0];     

当前动画关键帧和时间被存储在对应的activeAnimationKeyframeactiveAnimationTime变量中,最后你通过animationSpeed变量设置动画的速度。

// Default animation configuration 

animationSpeed = 1.0f; 

activeAnimationKeyframe = 0; 

activeAnimationTime = TimeSpan.Zero;       

当模型正在进行动画时,你使用一些临时矩阵数组用来计算每个bone的最后配置。这里你需要创建一个矩阵数组,数组长度应该等于bone的数量。你应该使用存储在AnimatedModelData中的bone配置初始化bone数组,用单位矩阵初始化bonesTransform数组。

// Temporary matrices used to animate the bones 

bones = new Matrix[animatedModelData.BonesBindPose.Length]; 

bonesAbsolute = new Matrix[animatedModelData.BonesBindPose.Length]; 

bonesAnimation = new Matrix[animatedModelData.BonesBindPose.Length]; 

// Used to apply custom transformation over the bones 

bonesTransform = new Matrix[animatedModelData.BonesBindPose.Length]; 

for (int i= 0; i< bones.Length; i++)

{

    bones[i] = animatedModelData.BonesBindPose[i]; 

    bonesTransform[i] = Matrix.Identity; 

}

最后,你获取模型的effect,并把它封装在AnimatedModelEffect中:

// Get the animated model effect - Shared by all meshes 

animatedModelEffect = new AnimatedModelEffect(model.Meshes[0].Effects[0]); 

// Create a default material 

lightMaterial = new LightMaterial();       

注意绘制模型的effect也被所有的模型网格共享,下面是AnimatedModel类的Load方法的代码:

public void Load(string modelFileName)

{

    if (!isInitialized) 

         Initialize(); 

    model = Game.Content.Load<Model>( GameAssetsPath.MODELS_PATH + modelFileName); 

    

    // Get the dictionary 

    Dictionary<string, object> modelTag =(Dictionary<string, object>)model.Tag;

    if (modelTag == null) 

        throw new InvalidOperationException( "This is not a valid animated model."); 

    // Get the AnimatedModelData from the dictionary 

    if (modelTag.ContainsKey("AnimatedModelData")) 

        animatedModelData = (AnimatedModelData)modelTag["AnimatedModelData"]; 

    else

        throw new InvalidOperationException("This is not a valid animated model."); 

    

    // Default animation 

    animationSpeed = 1.0f; 

    activeAnimationKeyframe = 0; 

    activeAnimationTime = TimeSpan.Zero; 

    

    if (animatedModelData.Animations.Length > 0)

        activeAnimation = animatedModelData.Animations[0]; 

    // Temporary matrices used to animate the bones 

    bones = new Matrix[animatedModelData.BonesBindPose.Length]; 

    bonesAbsolute = new Matrix[animatedModelData.BonesBindPose.Length]; 

    bonesAnimation = new Matrix[animatedModelData.BonesBindPose.Length]; 

    

    // Used to apply custom transformation over the bones 

    bonesTransform = new Matrix[animatedModelData.BonesBindPose.Length]; 

    for (int i= 0; i< bones.Length; i++)

    {

        bones[i] = animatedModelData.BonesBindPose[i]; 

        bonesTransform[i] = Matrix.Identity; 

    }

    

    // Get the animated model effect - Shared by all meshes 

    animatedModelEffect = new AnimatedModelEffect(model.Meshes[0].Effects[0]); 

    

    // Create a default material 

    lightMaterial = new LightMaterial(); 

}

原创粉丝点击