using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using DirectX=Microsoft.DirectX;
using Direct3D=Microsoft.DirectX.Direct3D;
namespace DX9Sample
{
public class Form1 : System.Windows.Forms.Form
{
private AnimationRootFrame rootFrame;
private Vector3 objectCenter;
private float objectRadius;
private float elapsedTime;
private Device device;
static void Main()
{
Application.Run(new Form1());
}
public Form1()
{
if (!this.InitializeGraphics())
{
MessageBox.Show("Your card can not perform skeletal animation on " +
"this file in hardware. This application will run in " +
"reference mode instead.");
}
}
public void GenerateSkinnedMesh(MeshContainerDerived mesh)
{
if (mesh.SkinInformation == null)
throw new ArgumentException();
int numInfl = 0;
BoneCombination[] bones;
// Use ConvertToBlendedMesh to generate a drawable mesh
MeshData m = mesh.MeshData;
m.Mesh = mesh.SkinInformation.ConvertToBlendedMesh(m.Mesh, MeshFlags.Managed
| MeshFlags.OptimizeVertexCache, mesh.GetAdjacencyStream(), out numInfl,
out bones);
// Store this info
mesh.NumberInfluences = numInfl;
mesh.SetBones(bones);
// Get the number of attributes
mesh.NumberAttributes = bones.Length;
mesh.MeshData = m;
}
public bool InitializeGraphics()
{
// Set our presentation parameters
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
presentParams.EnableAutoDepthStencil = true;
bool canDoHardwareSkinning = true;
// Does a hardware device support shaders?
Caps hardware = Manager.GetDeviceCaps(0, DeviceType.Hardware);
// We will need at least four blend matrices
if (hardware.MaxVertexBlendMatrices >= 4)
{
// Default to software processing
CreateFlags flags = CreateFlags.SoftwareVertexProcessing;
// Use hardware if it's available
if (hardware.DeviceCaps.SupportsHardwareTransformAndLight)
flags = CreateFlags.HardwareVertexProcessing;
// Use pure if it's available
if (hardware.DeviceCaps.SupportsPureDevice)
flags |= CreateFlags.PureDevice;
// Yes, Create our device
device = new Device(0, DeviceType.Hardware, this, flags, presentParams);
}
else
{
// No shader support
canDoHardwareSkinning = false;
// Create a reference device
device = new Device(0, DeviceType.Reference, this,
CreateFlags.SoftwareVertexProcessing, presentParams);
}
// Create the animation
CreateAnimation(Application.StartupPath + "\\tiny.x", presentParams);
// Hook the device reset event
device.DeviceReset += new EventHandler(OnDeviceReset);
OnDeviceReset(device, null);
return canDoHardwareSkinning;
}
private void OnDeviceReset(object sender, EventArgs e)
{
Device dev = (Device)sender;
// Set the view matrix
Vector3 vEye = new Vector3( 0, 0, -1.8f * objectRadius );
Vector3 vUp = new Vector3( 0, 1, 0 );
dev.Transform.View = Matrix.LookAtLH(vEye, objectCenter, vUp);
// Setup the projection matrix
float aspectRatio = (float)dev.PresentationParameters.BackBufferWidth
/ (float)dev.PresentationParameters.BackBufferHeight;
dev.Transform.Projection = Matrix.PerspectiveFovLH( (float)Math.PI / 4,
aspectRatio, objectRadius/64.0f, objectRadius*200.0f );
// Initialize our light
dev.Lights[0].Type = LightType.Directional;
dev.Lights[0].Direction = new Vector3(0.0f, 0.0f, 1.0f);
dev.Lights[0].Diffuse = Color.White;
dev.Lights[0].Enabled = true;
}
private void CreateAnimation(string file, PresentParameters presentParams)
{
// Create our allocate hierarchy derived class
AllocateHierarchyDerived alloc = new AllocateHierarchyDerived(this);
// Load our file
rootFrame = Mesh.LoadHierarchyFromFile(file, 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((FrameDerived)rootFrame.FrameHierarchy);
// Start the timer
DXUtil.Timer(DirectXTimer.Start);
}
private void SetupBoneMatrices(FrameDerived frame)
{
if (frame.MeshContainer != null)
{
SetupBoneMatrices((MeshContainerDerived)frame.MeshContainer);
}
if (frame.FrameSibling != null)
{
SetupBoneMatrices((FrameDerived)frame.FrameSibling);
}
if (frame.FrameFirstChild != null)
{
SetupBoneMatrices((FrameDerived)frame.FrameFirstChild);
}
}
private void SetupBoneMatrices(MeshContainerDerived mesh)
{
// Is there skin information? If so, setup the matrices
if (mesh.SkinInformation != null)
{
int numBones = mesh.SkinInformation.NumberBones;
FrameDerived[] frameMatrices = new FrameDerived[numBones];
for(int i = 0; i< numBones; i++)
{
FrameDerived frame = (FrameDerived)Frame.Find(
rootFrame.FrameHierarchy,
mesh.SkinInformation.GetBoneName(i));
if (frame == null)
throw new ArgumentException();
frameMatrices = frame;
}
mesh.SetFrames(frameMatrices);
}
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
ProcessNextFrame();
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,
Color.CornflowerBlue, 1.0f, 0);
device.BeginScene();
// Draw our root frame
DrawFrame((FrameDerived)rootFrame.FrameHierarchy);
device.EndScene();
device.Present();
this.Invalidate();
}
private void ProcessNextFrame()
{
// Get the current elapsed time
elapsedTime = DXUtil.Timer(DirectXTimer.GetElapsedTime);
// Set the world matrix
Matrix worldMatrix = Matrix.Translation(objectCenter);
device.Transform.World = worldMatrix;
if (rootFrame.AnimationController != null)
rootFrame.AnimationController.AdvanceTime(elapsedTime, null);
UpdateFrameMatrices((FrameDerived)rootFrame.FrameHierarchy, worldMatrix);
}
private void UpdateFrameMatrices(FrameDerived frame, Matrix parentMatrix)
{
frame.CombinedTransformationMatrix = frame.TransformationMatrix *
parentMatrix;
if (frame.FrameSibling != null)
{
UpdateFrameMatrices((FrameDerived)frame.FrameSibling, parentMatrix);
}
if (frame.FrameFirstChild != null)
{
UpdateFrameMatrices((FrameDerived)frame.FrameFirstChild,
frame.CombinedTransformationMatrix);
}
}
private void DrawFrame(FrameDerived frame)
{
MeshContainerDerived mesh = (MeshContainerDerived)frame.MeshContainer;
while(mesh != null)
{
DrawMeshContainer(mesh, frame);
mesh = (MeshContainerDerived)mesh.NextContainer;
}
if (frame.FrameSibling != null)
{
DrawFrame((FrameDerived)frame.FrameSibling);
}
if (frame.FrameFirstChild != null)
{
DrawFrame((FrameDerived)frame.FrameFirstChild);
}
}
private void DrawMeshContainer(MeshContainerDerived mesh, FrameDerived frame)
{
// Is there skin information?
if (mesh.SkinInformation != null)
{
int attribIdPrev = -1;
// Draw
for (int iattrib = 0; iattrib < mesh.NumberAttributes; iattrib++)
{
int numBlend = 0;
BoneCombination[] bones = mesh.GetBones();
for (int i = 0; i < mesh.NumberInfluences; i++)
{
if (bones[iattrib].BoneId != -1)
{
numBlend = i;
}
}
if (device.DeviceCaps.MaxVertexBlendMatrices >= numBlend + 1)
{
// first calculate the world matrices for the current set of
// blend weights and get the accurate count of the number of
// blends
Matrix[] offsetMatrices = mesh.GetOffsetMatrices();
FrameDerived[] frameMatrices = mesh.GetFrames();
for (int i = 0; i < mesh.NumberInfluences; i++)
{
int matrixIndex = bones[iattrib].BoneId;
if (matrixIndex != -1)
{
Matrix tempMatrix = offsetMatrices[matrixIndex] *
frameMatrices[matrixIndex].
CombinedTransformationMatrix;
device.Transform.SetWorldMatrixByIndex(i, tempMatrix);
}
}
device.RenderState.VertexBlend = (VertexBlend)numBlend;
// lookup the material used for this subset of faces
if ((attribIdPrev != bones[iattrib].AttributeId) ||
(attribIdPrev == -1))
{
device.Material = mesh.GetMaterials()[
bones[iattrib].AttributeId].Material3D;
device.SetTexture(0, mesh.GetTextures()[
bones[iattrib].AttributeId]);
attribIdPrev = bones[iattrib].AttributeId;
}
mesh.MeshData.Mesh.DrawSubset(iattrib);
}
}
}
else // standard mesh, just draw it after setting material properties
{
device.Transform.World = frame.CombinedTransformationMatrix;
ExtendedMaterial[] mtrl = mesh.GetMaterials();
for (int iMaterial = 0; iMaterial < mtrl.Length; iMaterial++)
{
device.Material = mtrl[iMaterial].Material3D;
device.SetTexture(0, mesh.GetTextures()[iMaterial]);
mesh.MeshData.Mesh.DrawSubset(iMaterial);
}
}
}
}
public class AllocateHierarchyDerived : AllocateHierarchy
{
private Form1 app = null;
public AllocateHierarchyDerived(Form1 parent)
{
app = parent;
}
public override Frame CreateFrame(string name)
{
FrameDerived frame = new FrameDerived();
frame.Name = name;
frame.TransformationMatrix = Matrix.Identity;
frame.CombinedTransformationMatrix = Matrix.Identity;
return frame;
}
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();
MeshContainerDerived mesh = new MeshContainerDerived();
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);
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)
{
meshTextures = TextureLoader.FromFile(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);
app.GenerateSkinnedMesh(mesh);
}
return mesh;
}
}
public class FrameDerived : Frame
{
// Store the combined transformation matrix
private Matrix combined = Matrix.Identity;
public Matrix CombinedTransformationMatrix
{
get { return combined; } set { combined = value; }
}
}
public class MeshContainerDerived : MeshContainer
{
private Texture[] meshTextures = null;
private int numAttr = 0;
private int numInfl = 0;
private BoneCombination[] bones;
private FrameDerived[] frameMatrices;
private Matrix[] offsetMatrices;
// Public properties
public Texture[] GetTextures() { return meshTextures; }
public void SetTextures(Texture[] textures) { meshTextures = textures; }
public BoneCombination[] GetBones() { return bones; }
public void SetBones(BoneCombination[] b) { bones = b; }
public FrameDerived[] GetFrames() { return frameMatrices; }
public void SetFrames(FrameDerived[] frames) { frameMatrices = frames; }
public Matrix[] GetOffsetMatrices() { return offsetMatrices; }
public void SetOffsetMatrices(Matrix[] matrices){offsetMatrices = matrices; }
public int NumberAttributes {get{return numAttr;}set{numAttr = value;}}
public int NumberInfluences {get{return numInfl;}set{numInfl = value;}}
}
}
Skinned Animation
Hi everybody,
I am using an example from the book "Sams - Managed DirectX 9 Kick Start, Graphics and Game Programming" about animations & keyframes on meshes.
This example is working, but the program bug when I use textures on my mesh. I analysed the sample code and it seems it should be able to use textures. The bug occurs on this line in function CreateAnimation()
rootFrame = Mesh.LoadHierarchyFromFile(file, MeshFlags.Managed,
device, alloc, null);
Error : Microsoft.DirectX.Direct3D.Direct3DXException
If you have any idea to solve the problem, reply !
Thanx
/********** Here is the full source *************/
[Edited by - goundy on August 26, 2005 12:17:15 AM]
Please read the section "How do I put links/quotes/images/code/smileys in my posts?" of the forums faq and edit your post to make sure it use the proper code tags to facilitate the reading of someone who wants to help.
As for your original question, I don't know how to help you.
As for your original question, I don't know how to help you.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement