简单翻译一下源代码,指出其中几处重点

 

//-----------------------------------------------------------------------------
// File: SimpleAnimation.cs
//
// Simple skeletal animation using Managed DirectX
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------

using System;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.Samples.DirectX.UtilityToolkit;

namespace SimpleAnimationSample
{    
    
/// <summary>SimpleAnimation Sample Class</summary>
    public class SimpleAnimation : IFrameworkCallback, IDeviceCreation
    
{
        
无需关心之物0

        
/// <summary>
        
/// 这里面有载入动画数据的代码
        
/// </summary>

        private void OnCreateDevice(object sender, DeviceEventArgs e)
        
{
            
// 设置字体
            statsFont = ResourceCache.GetGlobalInstance().CreateFont(e.Device, 150, FontWeight.Bold, 1false, CharacterSet.Default,
                Precision.Default, FontQuality.Default, PitchAndFamily.FamilyDoNotCare 
| PitchAndFamily.DefaultPitch
                , 
"Arial");

            
// 创建动画分配层
            
// 传入this是为了在创建新容器的时候调用this的GenerateSkinnedMesh方法
            AnimationAllocation alloc = new AnimationAllocation(this);

            
// 寻找tiny.x
            string meshFile = Utility.FindMediaFile("tiny\\tiny.x");            
            
string currentFolder = System.IO.Directory.GetCurrentDirectory();
            System.IO.Directory.SetCurrentDirectory(
new System.IO.FileInfo(meshFile).Directory.FullName);
            
            
// 读取层次
            
// rootFrame是AnimationRootFrame
            rootFrame = Mesh.LoadHierarchyFromFile(meshFile, MeshFlags.Managed, e.Device, alloc, null);
            
            
// 设置目录
            System.IO.Directory.SetCurrentDirectory(currentFolder);

            
// 计算碰撞盒
            objectRadius = Frame.CalculateBoundingSphere(rootFrame.FrameHierarchy, 
                
out objectCenter);

            
// 设置动画的矩阵
            SetupBoneMatrices(rootFrame.FrameHierarchy as AnimationFrame);
            isDestroyed 
= false;
        }


        
无需关心之物1

        
/// <summary>
        
/// 渲染之前的场景更新阶段
        
/// 用来更新动画状态
        
/// </summary>

        public void OnFrameMove(Device device, double appTime, float elapsedTime)
        
{
            
// 更新摄像机位置
            camera.FrameMove(elapsedTime);

            
// 计算世界矩阵
            Matrix worldMatrix = Matrix.Translation(-objectCenter);
            worldMatrix 
*= camera.WorldMatrix;

            
// 设置世界矩阵
            device.Transform.World = worldMatrix;

            
// 时间流逝?
            if (elapsedTime > 0.0f)
            
{
                
if (rootFrame.AnimationController != null)
                    
//重要!!!
                    
//此处推移了动画时间
                    
//如果用Conv3ds从3ds文件转换出X文件的话
                    
//DX的动画时间与3DMAX的比例是1:10
                    
//即,某一个动作在3DMAX中位于32帧,那在DX中就应该位于3.2帧。                    
                    rootFrame.AnimationController.AdvanceTime(elapsedTime);

                UpdateFrameMatrices(rootFrame.FrameHierarchy 
as AnimationFrame,
                    worldMatrix);
            }

        }


        
/// <summary>
        
/// 场景渲染阶段
        
/// </summary>

        public void OnFrameRender(Device device, double appTime, float elapsedTime)
        
{
            
bool beginSceneCalled = false;

            
// 清屏
            device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0x002D32AA1.0f0);
            
try
            
{
                device.BeginScene();
                beginSceneCalled 
= true;

                
// 渲染动画
                DrawFrame(rootFrame.FrameHierarchy as AnimationFrame);

                
// 渲染FPS
                RenderText();

                
// 渲染UI
                hud.OnRender(elapsedTime);
            }

            
finally
            
{
                
if (beginSceneCalled)
                    device.EndScene();
            }

        }

        
/// <summary>更新框架矩阵</summary>
        private void UpdateFrameMatrices(AnimationFrame frame, Matrix parentMatrix)
        
{
            frame.CombinedTransformationMatrix 
= frame.TransformationMatrix * 
                parentMatrix;

            
if (frame.FrameSibling != null)
            
{
                UpdateFrameMatrices(frame.FrameSibling 
as AnimationFrame, parentMatrix);
            }


            
if (frame.FrameFirstChild != null)
            
{
                UpdateFrameMatrices(frame.FrameFirstChild 
as AnimationFrame, 
                    frame.CombinedTransformationMatrix);
            }

        }


        
/// <summary>绘制框架</summary>
        private void DrawFrame(AnimationFrame frame)
        
{
            AnimationMeshContainer mesh 
= frame.MeshContainer as AnimationMeshContainer;
            
while(mesh != null)
            
{
                DrawMeshContainer(mesh, frame);

                mesh 
= mesh.NextContainer as AnimationMeshContainer;
            }


            
if (frame.FrameSibling != null)
            
{
                DrawFrame(frame.FrameSibling 
as AnimationFrame);
            }


            
if (frame.FrameFirstChild != null)
            
{
                DrawFrame(frame.FrameFirstChild 
as AnimationFrame);
            }

        }


        
/// <summary>渲染网格容器</summary>
        private void DrawMeshContainer(AnimationMeshContainer mesh, AnimationFrame parent)
        
{
            Device device 
= sampleFramework.Device;
            
// 检查是否有蒙皮网格
            if (mesh.SkinInformation != null)
            
{
                
if (mesh.NumberInfluences == 1)
                    device.RenderState.VertexBlend 
= VertexBlend.ZeroWeights;
                
else
                    device.RenderState.VertexBlend 
= (VertexBlend)(mesh.NumberInfluences - 1);

                
if (mesh.NumberInfluences > 0)
                    device.RenderState.IndexedVertexBlendEnable 
= true;

                BoneCombination[] bones 
= mesh.GetBones();

                
//重要!!此处绘制网格
                for(int iAttrib = 0; iAttrib < mesh.NumberAttributes; iAttrib++)
                
{
                    
// 首先,获取世界矩阵
                    for (int iPaletteEntry = 0; iPaletteEntry < mesh.NumberPaletteEntries; 
                        
++iPaletteEntry)
                    
{
                        
int iMatrixIndex = bones[iAttrib].BoneId[iPaletteEntry];
                        
if (iMatrixIndex != -1)
                        
{
                            device.Transform.SetWorldMatrixByIndex(iPaletteEntry, 
                                mesh.GetOffsetMatrices()[iMatrixIndex] 
* 
                                mesh.GetFrames()[iMatrixIndex].
                                CombinedTransformationMatrix);

                        }

                    }


                    
// 设置材质
                    device.Material = mesh.GetMaterials()[bones[iAttrib].AttributeId].Material3D;
                    device.SetTexture(
0, mesh.GetTextures()[bones[iAttrib].AttributeId]);

                    
// 最后,绘子集
                    mesh.MeshData.Mesh.DrawSubset(iAttrib);
                }

            }

            
else
            
{
                
// 如果是普通的网格,简单渲染之
                device.RenderState.VertexBlend = VertexBlend.Disable;

                
// 设置变换矩阵
                device.Transform.World = parent.CombinedTransformationMatrix;

                ExtendedMaterial[] materials 
= mesh.GetMaterials();

                
//重要!!此处绘制网格
                for (int i = 0; i < materials.Length; ++i)
                
{
                    device.Material 
= materials[i].Material3D;
                    device.SetTexture(
0, mesh.GetTextures()[i]);
                    mesh.MeshData.Mesh.DrawSubset(i);
                }

            }

        }


        
无需关心之物2

        
/// <summary>
        
/// 产生蒙皮网格数据
        
/// </summary>

        public void GenerateSkinnedMesh(AnimationMeshContainer mesh)
        
{
            
if (mesh.SkinInformation == null)
                
throw new ArgumentException();  

            MeshFlags flags 
= MeshFlags.OptimizeVertexCache;

            Caps caps 
= sampleFramework.DeviceCaps;
            
if (caps.VertexShaderVersion >= new Version(1,1))
            
{
                flags 
|= MeshFlags.Managed;
            }

            
else
            
{
                flags 
|= MeshFlags.SystemMemory;
            }


            
int numMaxFaceInfl;
            
using(IndexBuffer ib = mesh.MeshData.Mesh.IndexBuffer)
            
{
                numMaxFaceInfl 
= mesh.SkinInformation.GetMaxFaceInfluences(ib, 
                    mesh.MeshData.Mesh.NumberFaces);
            }

            
// 12个调色板入口能保证所有三角形都被处理
            numMaxFaceInfl = (int)Math.Min(numMaxFaceInfl, 12);

            
if (caps.MaxVertexBlendMatrixIndex + 1 >= numMaxFaceInfl)
            
{
                mesh.NumberPaletteEntries 
= (int)Math.Min((caps.
                    MaxVertexBlendMatrixIndex
+ 1/ 2
                    mesh.SkinInformation.NumberBones);

                flags 
|= MeshFlags.Managed;
            }


            
int influences = 0;
            BoneCombination[] bones 
= null;

            
// 用ConvertToBlendedMesh来创建一个可以绘制的网格
            MeshData data = mesh.MeshData;
            data.Mesh 
= mesh.SkinInformation.ConvertToIndexedBlendedMesh(data.Mesh, flags, 
                mesh.GetAdjacencyStream(), mesh.NumberPaletteEntries, 
out influences, 
                
out bones);

            
// 把数据保存下来
            mesh.NumberInfluences = influences;
            mesh.SetBones(bones);

            
// 获取属性数
            mesh.NumberAttributes = bones.Length;

            mesh.MeshData 
= data;
        }


        
/// <summary>这个方法为框架设置骨骼</summary>
        private void SetupBoneMatrices(AnimationFrame frame)
        
{
            
// 如果有父级
            if (frame.MeshContainer != null)
            
{
                SetupBoneMatrices(frame.MeshContainer 
as AnimationMeshContainer);
            }

            
// 如果有同级
            if (frame.FrameSibling != null)
            
{
                SetupBoneMatrices(frame.FrameSibling 
as AnimationFrame);
            }

            
// 如果还有子集
            if (frame.FrameFirstChild != null)
            
{
                SetupBoneMatrices(frame.FrameFirstChild 
as AnimationFrame);
            }

        }


        
/// <summary>为容器设置骨骼</summary>
        private void SetupBoneMatrices(AnimationMeshContainer mesh)
        
{
            
// 如果有蒙皮信息
            if (mesh.SkinInformation != null)
            
{
                
int numberBones = mesh.SkinInformation.NumberBones;

                AnimationFrame[] frameMatrices 
= new AnimationFrame[numberBones];
                
for(int i = 0; i< numberBones; i++)
                
{
                    AnimationFrame frame 
= Frame.Find(rootFrame.FrameHierarchy, 
                        mesh.SkinInformation.GetBoneName(i)) 
as AnimationFrame;

                    
if (frame == null)
                        
throw new InvalidOperationException("Could not find valid bone.");

                    frameMatrices[i] 
= frame;
                }

                mesh.SetFrames(frameMatrices);
            }

        }


        
无需关心之物3
    }
    

    
从 Frame 派生
    
从 MeshContainer 派生

    
动画分配层
}

posted @ 2007-03-07 15:14  Cloudage  阅读(928)  评论(0编辑  收藏  举报