need help with directX animation

Started by
4 comments, last by allenm84 17 years, 9 months ago
Hello. I have been at this for awhile now and I've learned a lot, but I can't seem to get animation working. I've looked the SimpleAnimation sample, I've also read a series of books and online tutorials, and while I can get their samples working, I can't write up my own code. My goal is to have a generic abstract class that does the basic loading of a .X file, and then derived classes for the different characters in my game. I've started out small with trying to animate the tiny.x file, and while I can render it, I can't get it animate. I wrote this in C# using the April DirectX SDK. Any help, resources, or suggestions would be greatly appreciated:
 
public class Tiny : AnimatedCharacter
	{
		protected string filename = "tiny.x";
		protected Device device;
		protected AnimationRootFrame rootFrame;
		protected MeshContainerEx meshCont;
		protected float radius = 0.0f;
		protected Vector3 center = Vector3.Empty;
		protected float angle = 0.005F;

		#region Accessor Functions
		public float Radius
		{
			get{ return this.radius; }
		}

		public Vector3 objectCenter
		{
			get{ return this.center; }
		}
		#endregion

		public Tiny(Device device)
		{
			// Set the device
			this.device = device;

			// load in everything
			rootFrame = Mesh.LoadHierarchyFromFile(filename, MeshFlags.SystemMemory, device, new FrameAllocate(filename), null );

			// calculate the radius
			radius = Frame.CalculateBoundingSphere( rootFrame.FrameHierarchy, out center );

			// map
			MapFramesToBone();

			for( int i=0; i<animControl.NumberAnimationSets; ++i )
			{
				AnimationSet animSet = animControl.GetAnimationSet(i);

				rootFrame.AnimationController.SetTrackEnable(i,true);
				rootFrame.AnimationController.SetTrackAnimationSet(i,animSet);
				rootFrame.AnimationController.ResetTime();
				rootFrame.AnimationController.SetTrackPosition(0, 0.0F);
				rootFrame.AnimationController.SetTrackSpeed(0, 1f);
				rootFrame.AnimationController.SetTrackWeight(0, 1f);

				for( int j=0; j<animSet.NumberAnimations; ++j )
				{
					string animName = animSet.GetAnimationName(j);
					int index = animSet.GetAnimationIndex(animName);
				}
			}
		}

		public override void Update()
		{
			((FrameEx)rootFrame.FrameHierarchy).UpdateHierarchy(Matrix.Identity);

			FindMeshContainerFrame( this.rootFrame.FrameHierarchy as FrameEx );
			int NumBones = meshCont.SkinInformation.NumberBones;

			for(int Counter = 0; Counter < NumBones; Counter++)
			{
				meshCont.BoneMatrices[Counter] = meshCont.SkinInformation.GetBoneOffsetMatrix(Counter);
				meshCont.BoneMatrices[Counter] *= meshCont.FrameMatrices[Counter];
			}

			GraphicsStream Src = meshCont.MeshData.Mesh.LockVertexBuffer(LockFlags.ReadOnly);
			GraphicsStream Des = meshCont.originalMesh.LockVertexBuffer(0);
			meshCont.SkinInformation.UpdateSkinnedMesh(meshCont.BoneMatrices, null, Src, Des);

			meshCont.MeshData.Mesh.UnlockVertexBuffer();
			meshCont.originalMesh.UnlockVertexBuffer();
		}

		public override void RenderFrame(float ElapsedTime)
		{
			Update();
			rootFrame.AnimationController.AdvanceTime( ElapsedTime );
			DrawFrame( rootFrame.FrameHierarchy as FrameEx );
		}

		private void DrawFrame(FrameEx frame)
		{
			MeshContainerEx mesh = frame.MeshContainer as MeshContainerEx;
			while(mesh != null)
			{
				DrawMeshContainer(mesh, frame);
				mesh = mesh.NextContainer as MeshContainerEx;
			}

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

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

		private void DrawMeshContainer(MeshContainerEx mesh, FrameEx parent)
		{
			// position tiny upright
			device.Transform.World = Matrix.RotationY((float)Math.PI/(float)Math.Cos(angle));

			// Standard mesh, just draw it using FF
			device.RenderState.VertexBlend = VertexBlend.Disable;

			// Set up transforms
			//device.Transform.World = parent.matCombined * Matrix.RotationY(angle);
			angle+=0.005F;

			ExtendedMaterial[] materials = mesh.GetMaterials();
			for (int i = 0; i < materials.Length; ++i)
			{
				device.Material = materials.Material3D;
				device.SetTexture(0, mesh.textures);
				mesh.MeshData.Mesh.DrawSubset(i);
			}
		}

		protected void MapFramesToBone()
		{
			FindMeshContainerFrame( this.rootFrame.FrameHierarchy as FrameEx );
			int NumBones = meshCont.SkinInformation.NumberBones;

			meshCont.FrameMatrices = new Matrix[NumBones];
			meshCont.BoneMatrices = new Matrix[NumBones];

			for(int Counter = 0; Counter < NumBones; ++Counter)
			{
				string BoneName = meshCont.SkinInformation.GetBoneName(Counter);
				FrameEx FramePtr = Frame.Find(rootFrame.FrameHierarchy, BoneName) as FrameEx;

				if(FramePtr != null)
					meshCont.FrameMatrices[Counter] = FramePtr.matCombined;
				else
					meshCont.FrameMatrices[Counter] = Matrix.Identity;
			}
		}

		protected void FindMeshContainerFrame( FrameEx frame )
		{
			if( frame.MeshContainer == null )
			{
				if( frame.FrameSibling != null )
				{
					FindMeshContainerFrame( frame.FrameSibling as FrameEx );
				}
				if( frame.FrameFirstChild != null )
				{
					FindMeshContainerFrame( frame.FrameFirstChild as FrameEx );
				}
			}
			else
			{
				this.meshCont = frame.MeshContainer as MeshContainerEx;
			}
		}
	}

	public class MeshContainerEx : MeshContainer
	{
		public Matrix[] BoneMatrices;
		public Matrix[] FrameMatrices;
		public Texture[] textures;
		public string xFilePath;
		public Mesh originalMesh;

		public MeshContainerEx(string xFilePath, string name, MeshData meshData, ExtendedMaterial[] materials, EffectInstance[] effectInstances, GraphicsStream adjacency, SkinInformation skinInfo)
		{
			this.Name = name;
			this.MeshData = meshData;
			this.SetMaterials(materials);
			this.SetEffectInstances(effectInstances);
			this.SetAdjacency(adjacency);
			this.SkinInformation = skinInfo;
			this.xFilePath = xFilePath;

			// Load the textures for the mesh.
			ExtendedMaterial[] m = this.GetMaterials();
			this.textures = new Texture[m.Length];

			for(int i=0; i<m.Length; i++)
			{
				if(m.TextureFilename != null)
				{
					string path = Path.Combine(Path.GetDirectoryName(this.xFilePath), m.TextureFilename);
					this.textures = TextureLoader.FromFile(this.MeshData.Mesh.Device, path);
				}
			}

			originalMesh = this.MeshData.Mesh.Clone( MeshFlags.SystemMemory, MeshData.Mesh.VertexFormat, MeshData.Mesh.Device );
		}
	}

	public class FrameAllocate : AllocateHierarchy
	{
		private string xFilePath;

		public FrameAllocate(string xFilePath) : base()
		{
			this.xFilePath = xFilePath;
		}

		public override Frame CreateFrame(string name)
		{
			return new FrameEx(name);
		}

		public override MeshContainer CreateMeshContainer(string name, MeshData meshData, ExtendedMaterial[] materials, EffectInstance[] effectInstances, GraphicsStream adjacency, SkinInformation skinInfo)
		{
			return new MeshContainerEx(this.xFilePath, name, meshData, materials, effectInstances, adjacency, skinInfo);
		}
	}

	public class FrameEx : Frame
	{
		public Matrix matCombined = Matrix.Identity;
		public Matrix matOriginal = Matrix.Identity;

		public FrameEx(string Name)
		{
			this.Name = Name;
			this.TransformationMatrix = Matrix.Identity;
			this.MeshContainer = null;
		}

		public void Reset()
		{
			TransformationMatrix = matOriginal;

			if( ((FrameEx)this.FrameSibling) != null )
				((FrameEx)this.FrameSibling).Reset();

			if( ((FrameEx)this.FrameFirstChild) != null )
				((FrameEx)this.FrameFirstChild).Reset();
		}

		public void UpdateHierarchy(Matrix matTransformation)
		{
			matCombined = TransformationMatrix * matTransformation;

			if( ((FrameEx)this.FrameSibling) != null )
				((FrameEx)this.FrameSibling).UpdateHierarchy(matTransformation);

			if( ((FrameEx)this.FrameFirstChild) != null )
				((FrameEx)this.FrameFirstChild).UpdateHierarchy(matCombined);
		}
	}

Thanks a lot!
Advertisement
can anyone help at all? If not, I'll look elsewhere.
I can't really help you with any code, as I'm not very friendly with C#. But I can give you some advice.

First, what you're getting into is complicated. You probably already know this, but you might not know that most users on this forum don't want to get into a large amount of work. And just looking through so much code (not saying bad code) to find a possible bug is a pretty big job.

What you need to do is to try really hard to isolate problems. Test small parts of code, check the values, see if everything looks right, then continue. Keep doing this until you find something whacky or out of place. Then post that code, along with the whacky values or results, and you'll most likely get a lot more help.

For some steps to test, here is the order I would debug the program:

1. Make sure the animation key matrices are being loaded in, and make sure the values look right. The first three rows of the matrices should be normalized (sum should be around 0.8 to 1.3).

2. Make sure your animation time-progress value is being increased correctly. If not, that would stop everything.

3. Make sure your animation update routines are interpolating correctly between the matrices. That probably means lerping or s-lerping between two key matrices at a time for each bone, depending on the time-progress variable.

4. Make sure you're sending your bone matrices to the shader or whatever rendering setup you use before you render. That usually means packing them into a solid array, then shipping them off to the graphics card. If you don't send these, your model will just stay in a bind pose.

I think that's about it. The only way I've ever animated skinned mesh models was with a vertex shader. I've never even attempted software skinning, because I knew my game would kill whatever system I tried to run it on. But I think you just manually lock the vertex buffer of the model and multiply the vertex positions with the bone transformation matrices. You would also need to back up the vertex positions in some type of system memory, so you can do this again and again. That's about all I can detail about that.

If I almost covered your problem, let me know and I'll try to explain more. But like I said, I can't really help directly with code.
Thanks for the help!! I followed your instructions. I debugged the example "SimpleAnimation" (after morphing my code to match it) in the directX SDK and it failed on the line when I drew the subset. I fixed it by adding a variable of type Mesh to the derived AllocationHierarchy class and just rendered that. However, I can't render additional meshes to the screen (skyboxes, terrain, other characters, etc) without them being messed up. I tried to create a simple mesh (the cylinder mesh provided as a static function of the Mesh class) and it became skewed and moved with the tiny.x animation. I'm not sure why this is. Any suggestions? If not, I'll look over the "Multi-animation" sample in C++ in the SDK to see if I can find something. Thanks again for the help!!
I been through the same problem before, And I have an abstract class for loading .x files animation with multible animation set, and it is working just fine.
here is the whole source code for the file XFileAnim.c
using System;using System.IO;using Microsoft.DirectX;using Microsoft.DirectX.Direct3D;namespace Fadi.XFileAnimation{    public class XFileAnim    {		//Public mumbers		public float objectRadius = 0.0f;		public Vector3 objectCenter;		public AnimationController Controller=null;		public Matrix World=Matrix.Identity;		private Device device=null;		private AnimationRootFrame rootFrame; 		private bool isDestroyed = false;		/// <summary>Create a new instance of the class</summary>        public XFileAnim(Device dev)         { 			device=dev;        }        public void LoadFromFile(string meshFile)        {            // Create our allocate hierarchy derived class            AnimationAllocation alloc = new AnimationAllocation(this);            rootFrame = Mesh.LoadHierarchyFromFile(meshFile, MeshFlags.Managed, device, alloc, null);            // Calculate the center and radius of a bounding sphere            objectRadius = Frame.CalculateBoundingSphere(rootFrame.FrameHierarchy,                 out objectCenter);            // Setup the matrices for animation            SetupBoneMatrices(rootFrame.FrameHierarchy as AnimationFrame);			//Clone the Animation controler to add more animation tracks			if (rootFrame.AnimationController!=null)				Controller=rootFrame.AnimationController.Clone(50,30,10,30);            isDestroyed = false;        }                public void Destroy()        {            if (isDestroyed)                return; // Only clean up once            Frame.Destroy(rootFrame.FrameHierarchy, new AnimationAllocation(this));            if (rootFrame.AnimationController != null)            {                rootFrame.AnimationController.Dispose();            }            isDestroyed = true;        }        public void FrameMove(Matrix ViewWorldMatrix,float elapsedTime)        {            // Build the world matrix            Matrix worldMatrix = Matrix.Translation(-objectCenter);            worldMatrix *= ViewWorldMatrix;            // Set world matrix            device.Transform.World = worldMatrix;            // Has any time elapsed?            if (elapsedTime > 0.0f)            {                if (Controller != null)                    Controller.AdvanceTime(elapsedTime);                UpdateFrameMatrices(rootFrame.FrameHierarchy as AnimationFrame,worldMatrix);            }        }        public void Render()        {			DrawFrame(rootFrame.FrameHierarchy as AnimationFrame);        }        /// <summary>Update the frames matrices and combine it with it's parents</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>Draw a frame and all child and sibling frames</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>Render a mesh container</summary>        private void DrawMeshContainer(AnimationMeshContainer mesh, AnimationFrame parent)        {            // first check for skinning            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(Int32 iAttrib = 0; iAttrib < mesh.NumberAttributes; iAttrib++)                {                    // first, get world matrices                    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*World);                        }                    }                    // Setup the material                    device.Material = mesh.GetMaterials()[bones[iAttrib].AttributeId].Material3D;                    device.SetTexture(0, mesh.GetTextures()[bones[iAttrib].AttributeId]);                    // Finally draw the subset                    mesh.MeshData.Mesh.DrawSubset(iAttrib);                }            }            else            {                // Standard mesh, just draw it using FF                device.RenderState.VertexBlend = VertexBlend.Disable;                // Set up transforms                device.Transform.World = parent.CombinedTransformationMatrix*World;                ExtendedMaterial[] materials = mesh.GetMaterials();                for (int i = 0; i < materials.Length; ++i)                {                    device.Material = materials.Material3D;                    device.SetTexture(0, mesh.GetTextures());                    mesh.MeshData.Mesh.DrawSubset(i);                }            }        }        /// <summary>        /// Generate the skinned mesh information        /// </summary>        public void GenerateSkinnedMesh(AnimationMeshContainer mesh)        {            if (mesh.SkinInformation == null)                throw new ArgumentException();  // There is nothing to generate            MeshFlags flags = MeshFlags.OptimizeVertexCache;            Caps caps = device.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 entry palette guarantees that any triangle (4 independent             // influences per vertex of a tri) can be handled            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;            // Use ConvertToBlendedMesh to generate a drawable mesh            MeshData data = mesh.MeshData;            data.Mesh = mesh.SkinInformation.ConvertToIndexedBlendedMesh(data.Mesh, flags,                 mesh.GetAdjacencyStream(), mesh.NumberPaletteEntries, out influences,                 out bones);            // Store this info            mesh.NumberInfluences = influences;            mesh.SetBones(bones);            // Get the number of attributes            mesh.NumberAttributes = bones.Length;            mesh.MeshData = data;        }        /// <summary>This method will set the bone matrices for a frame</summary>        private void SetupBoneMatrices(AnimationFrame frame)        {            // First do the mesh container this frame contains (if it does)            if (frame.MeshContainer != null)            {                SetupBoneMatrices(frame.MeshContainer as AnimationMeshContainer);            }            // Next do any siblings this frame may contain            if (frame.FrameSibling != null)            {                SetupBoneMatrices(frame.FrameSibling as AnimationFrame);            }            // Finally do the children of this frame            if (frame.FrameFirstChild != null)            {                SetupBoneMatrices(frame.FrameFirstChild as AnimationFrame);            }        }        /// <summary>Sets the bone matrices for a mesh container</summary>        private void SetupBoneMatrices(AnimationMeshContainer mesh)        {            // Is there skin information?  If so, setup the matrices            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 = frame;                }                mesh.SetFrames(frameMatrices);            }        }		public AnimationFrame GetFrameByName(string FrameName)		{			AnimationFrame Result=Frame.Find(rootFrame.FrameHierarchy,FrameName) as AnimationFrame;			return Result;		}		public void GetMeshBoundingBox(AnimationFrame Frame,out Vector3 MinVec,out Vector3 MaxVec)		{			AnimationMeshContainer Cont=(AnimationMeshContainer)Frame.MeshContainer;			Mesh mesh=Cont.MeshData.Mesh;			using (VertexBuffer vb = mesh.VertexBuffer)			{				GraphicsStream vertexData = vb.Lock(0, 0, LockFlags.None);				Geometry.ComputeBoundingBox(vertexData,mesh.NumberVertices,					mesh.VertexFormat,out MinVec,out MaxVec);				vb.Unlock();			}		}	}    #region Derived Frame Class    /// <summary>    /// The frame that will hold mesh animation     /// </summary>    public class AnimationFrame : Frame    {        // Store the combined transformation matrix		private Matrix combined = Matrix.Identity;        /// <summary>The combined transformation matrix</summary>        public Matrix CombinedTransformationMatrix		{            get { return combined; } set { combined = value; }        }    }    #endregion    #region Derived Mesh Container    /// <summary>    /// The mesh container class that will hold the animation data    /// </summary>    public class AnimationMeshContainer : MeshContainer    {        // Array data		private Texture[] meshTextures = null;		private BoneCombination[] bones;		private Matrix[] offsetMatrices;		private AnimationFrame[] frameMatrices;		//private IndexBuffer ib;        // Instance data		private int numAttributes = 0;		private int numInfluences = 0;		private int numPalette = 0;        // Public properties        /// <summary>Retrieve the textures used for this container</summary>        public Texture[] GetTextures() { return meshTextures; }        /// <summary>Set the textures used for this container</summary>        public void SetTextures(Texture[] textures) { meshTextures = textures; }                /// <summary>Retrieve the bone combinations used for this container</summary>        public BoneCombination[] GetBones() { return bones; }        /// <summary>Set the bone combinations used for this container</summary>        public void SetBones(BoneCombination[] b) { bones = b; }                /// <summary>Retrieve the animation frames used for this container</summary>        public AnimationFrame[] GetFrames() { return frameMatrices; }        /// <summary>Set the animation frames used for this container</summary>        public void SetFrames(AnimationFrame[] frames) { frameMatrices = frames; }                /// <summary>Retrieve the offset matrices used for this container</summary>        public Matrix[] GetOffsetMatrices() { return offsetMatrices; }        /// <summary>Set the offset matrices used for this container</summary>        public void SetOffsetMatrices(Matrix[] matrices) { offsetMatrices = matrices; }                /// <summary>Total number of attributes this mesh container contains</summary>        public int NumberAttributes { get { return numAttributes; } set { numAttributes = value; } }        /// <summary>Total number of influences this mesh container contains</summary>        public int NumberInfluences { get { return numInfluences; } set { numInfluences = value; } }        /// <summary>Total number of palette entries this mesh container contains</summary>        public int NumberPaletteEntries { get { return numPalette; } set { numPalette = value; } }    }    #endregion    #region Animation Allocation Hierarchy    /// <summary>    /// AllocateHierarchy derived class    /// </summary>    public class AnimationAllocation : AllocateHierarchy    {        XFileAnim parent = null;        /// <summary>Create new instance of this class</summary>        public AnimationAllocation(XFileAnim p) { parent = p; }        /// <summary>Create a new frame</summary>        public override Frame CreateFrame(string name)        {            AnimationFrame frame = new AnimationFrame();            frame.Name = name;            frame.TransformationMatrix = Matrix.Identity;            frame.CombinedTransformationMatrix = Matrix.Identity;            return frame;        }        /// <summary>Create a new mesh container</summary>        public override MeshContainer CreateMeshContainer(string name,             MeshData meshData, ExtendedMaterial[] materials,             EffectInstance[] effectInstances, GraphicsStream adjacency,             SkinInformation skinInfo)        {            // We only handle meshes here            if (meshData.Mesh == null)                throw new ArgumentException();            // We must have a vertex format mesh            if (meshData.Mesh.VertexFormat == VertexFormats.None)                throw new ArgumentException();            AnimationMeshContainer mesh = new AnimationMeshContainer();            mesh.Name = name;            int numFaces = meshData.Mesh.NumberFaces;            Device dev = meshData.Mesh.Device;                        // Make sure there are normals            if ((meshData.Mesh.VertexFormat & VertexFormats.Normal) == 0)            {                // Clone the mesh                Mesh tempMesh = meshData.Mesh.Clone(meshData.Mesh.Options.Value,                     meshData.Mesh.VertexFormat | VertexFormats.Normal, dev);                // Destroy current mesh, use the new one                meshData.Mesh.Dispose();                meshData.Mesh = tempMesh;                meshData.Mesh.ComputeNormals();            }            // Store the materials            mesh.SetMaterials(materials);            mesh.SetAdjacency(adjacency);            Texture[] meshTextures = new Texture[materials.Length];                        // Create any textures            for (int i = 0; i < materials.Length; i++)            {                if ((materials.TextureFilename != null)&&(File.Exists(materials.TextureFilename)))                {					meshTextures = TextureLoader.FromFile(dev, materials.TextureFilename);//                  meshTextures = ResourceCache.GetGlobalInstance().CreateTextureFromFile(//                        dev, materials.TextureFilename);                }            }            mesh.SetTextures(meshTextures);            mesh.MeshData = meshData;            // If there is skinning info, save any required data            if (skinInfo != null)            {                mesh.SkinInformation = skinInfo;                int numBones = skinInfo.NumberBones;                Matrix[] offsetMatrices = new Matrix[numBones];                for (int i = 0; i < numBones; i++)                    offsetMatrices = skinInfo.GetBoneOffsetMatrix(i);                mesh.SetOffsetMatrices(offsetMatrices);                parent.GenerateSkinnedMesh(mesh);            }            return mesh;        }    }    #endregion}


and here is a sample on how to implement this class:
//declaringXFileAnim KBody;//for loadingKBody=new XFileAnim(device);KBody.LoadFromFile("KhBody.X");//synchronize with the application timefloat ElapsedTime=(float)FrameworkTimer.GetElapsedTime();KBody.FrameMove(Matrix.Identity, ElapsedTime);//Rendering and moving according to the matrix MeshMoveMatrixKBody.World=MeshMoveMatrix;KBody.Render();
Thanks a lot for the source code! I did need to animate different or multiple animation tracks and I think this will help. Maybe using a cloned controller would solve this problem: What I was trying to say in the last post was that I couldn't render additional meshes to the screen (without them being skewed), but I will try this code and see what happens.

This topic is closed to new replies.

Advertisement