SlimDX DirectX10 Display MD5mesh

Started by
14 comments, last by jpetrie 13 years, 6 months ago
Hello guys,

i have a problem displaying an md5mesh. I believe, that the loading code is functional. My clue is, that my shadercode is wrong or the vertexinputlayout.

Here is the code, in which i am creating the buffers, the inputlayout and vertexbinding.

public void PreRender(Device device)        {            // ====== Need to be optimized =======            /* * * * * * * * * * * * * * * * * * * */            /* create index buffer */            /* * * * * * * * * * * * * * * * * * * */            int counter = 0;            int[] tmpIndices = new int[m_Mesh.Triangles.Length * 3];            for (int i = 0; i < m_Mesh.Triangles.Length; ++i)            {                tmpIndices[counter++] = m_Mesh.Triangles.vertIndex0;                tmpIndices[counter++] = m_Mesh.Triangles.vertIndex1;                tmpIndices[counter++] = m_Mesh.Triangles.vertIndex2;            }            using (var data = new DataStream(tmpIndices, true, false))            {                indices = new Buffer(device, data,                    new BufferDescription()                    {                        BindFlags = BindFlags.IndexBuffer,                        CpuAccessFlags = CpuAccessFlags.None,                        OptionFlags = ResourceOptionFlags.None,                        SizeInBytes = tmpIndices.Length * 4,                        Usage = ResourceUsage.Default                    });            }            /* * * * * * * * * * * * * * * * * * * */            /* create vertex buffer */            /* * * * * * * * * * * * * * * * * * * */            using (var data = new DataStream(m_Mesh.Vertices, true, false))            {                vertices = new Buffer(device, data,                    new BufferDescription()                    {                        BindFlags = BindFlags.VertexBuffer,                        CpuAccessFlags = CpuAccessFlags.None,                        OptionFlags = ResourceOptionFlags.None,                        SizeInBytes = m_Mesh.Vertices.Length * Marshal.SizeOf(typeof(SMD5Vertex)),                        Usage = ResourceUsage.Default                    });            }            elements = new InputElement[]            {                new InputElement("INDEX", 0, Format.R32_SInt, 0, 0),                new InputElement("UVCOORD", 0, Format.R32G32_Float, 0, 1),                new InputElement("STARTWEIGHT", 0, Format.R32_SInt, 0, 2),                new InputElement("COUNTWEIGHT", 0, Format.R32_SInt, 0, 3),                new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 4),                new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 0, 5),            };            effect = Effect.FromFile(device,                "MD5Model.fx", "fx_4_0", ShaderFlags.None, EffectFlags.None, null, null);            layout = new InputLayout(device,                effect.GetTechniqueByIndex(0).GetPassByIndex(0).Description.Signature,                elements);            binding = new[]            {                new VertexBufferBinding(vertices, Marshal.SizeOf(typeof(SMD5Vertex)), 0),            };        }


The Vertex struct:

[StructLayout(LayoutKind.Sequential)]struct SMD5Vertex{    public int index;    public SUVCoord UVCoord;    public int startWeight;    public int countWeight;    /// <summary>    /// Is calculated later    /// </summary>    public Vector3 FinalPosition;    public int Color;}


And here is the shader-code:

float4x4 view;float4x4 proj;float4x4 world;float4 defaultColor;struct VS_IN{	int index : INDEX;    float2 UVCoord : UVCOORD;    int startWeight : STARTWEIGHT;    int countWeight : COUNTWEIGHT;	float3 pos : POSITION;	float4 col : COLOR;};struct PS_IN{	float4 pos : SV_POSITION;	float4 col : COLOR;};PS_IN VS( VS_IN input ){	PS_IN output = (PS_IN)0;		float4x4 worldViewProj = mul(mul(world, view), proj);	output.pos = mul(input.pos, worldViewProj);		return output;}float4 PS( PS_IN input ) : SV_Target{	return defaultColor;}technique10 RenderSolid{	pass P0	{		SetGeometryShader( 0 );		SetVertexShader( CompileShader( vs_4_0, VS() ) );		SetPixelShader( CompileShader( ps_4_0, PS() ) );	}}


Thanks in advance
Advertisement
You haven't mentioned in what way it goes wrong. A description or screenshot would be helpful.

Have you tried using PIX to debug it?
ah yes sry,

well the problem is, that nothing is displayed, the screen is black. I thought, maybe my world, view or proj matrices were wrong or maybe the initialization of the device and swapchain, so i copied the smdloader from the samples and successfully displayed the jupitermesh.

And yes, i tried pix, but when i start the experiment, pix crashes. Enabling debug runtime did not help.

By the way, i am using win7 x64 and using the x64 version of SlimDX.dll.
If other meshes are rendering using the same code that rules out a lot of things that might be wrong. Here's a few possibilities to check:

- Is it rendering the mesh in black or transparent? Try clearing the screen to another colour, or adjusting the pixel shader to do a "return float4(1, 1, 1, 1);".

- Are the vertices ending up off screen? Try moving the camera round or increasing the far clip plane.

- Are all the vertices ending up in the same position? Check the data as you write it into the vertex buffer. Also make sure the size of the model looks sensible. Looking at the vertex data may also help you point the camera in the right direction.

- Are the indices all identical? Again check them as you put them into the buffer.

- Are any draw calls returning error codes?
Thanks for the tips Adam,

Quote:Is it rendering the mesh in black or transparent? Try clearing the screen to another colour, or adjusting the pixel shader to do a "return float4(1, 1, 1, 1);".

Tried it, before posting here, did not help

Quote:
- Are the vertices ending up off screen? Try moving the camera round or increasing the far clip plane.

- Are all the vertices ending up in the same position? Check the data as you write it into the vertex buffer. Also make sure the size of the model looks sensible. Looking at the vertex data may also help you point the camera in the right direction.


Checked that, everything seems to be alright, though i am not 100% sure. The final positions, which are calculated by:

private void CalculateFinalVertexPositions()        {            int numVerts = m_Mesh.Vertices.Length;            for (int i = 0; i < numVerts; ++i)            {                /* Calculate final vertex to draw with weights */                for (int j = 0; j < m_Mesh.Vertices.countWeight; ++j)                {                    SMD5Weight weight = m_Mesh.Weights[m_Mesh.Vertices.startWeight + j];                    SJoint joint = m_Mesh.Joints[weight.JointIndex];                    //Vector3 wv;                    //RotatePointbyQuaternion(ref weight.PositionInSpace, ref joint.Orientation, out wv);                    Matrix mat;                    Matrix.RotationQuaternion(ref joint.Orientation, out mat);                    Vector3 orig = weight.PositionInSpace;                    Vector4 vec;                    Vector3.Transform(ref orig, ref mat, out vec);                    Vector3 vec3 = new Vector3()                    {                        X = vec.X,                        Y = vec.Y,                        Z = vec.Z                    };                    m_Mesh.Vertices.FinalPosition += (vec3 + joint.Position) * weight.bias;                }            }        }


are very close together, but maybe i am just unfamiliar with typical 3d coordinates(for example finalPos of vertex0 = X:-7,03..., Y:-8,43..., Z:165,26... and finalPos of vertex1 = X:-6,96..., Y:-8,18..., Z:164,35...)

Quote:- Are the indices all identical? Again check them as you put them into the buffer.


Checked that, everything is exactly, like in the md5mesh-file. Checked every struct, the parser works 100% correct.

Quote:- Are any draw calls returning error codes?

Well Visual Studio do not report any errors and the only method, which returns actually something, is the Present-method from the swapchain.

Here is a snippet from my matrix setup and the mainloop:

Matrix view = Matrix.LookAtLH(new Vector3(0, 0, 0), new Vector3(-7, -8, 160), Vector3.UnitY);Mesh.Effect.GetVariableByName("view").AsMatrix().SetMatrix(view);Matrix proj = Matrix.PerspectiveFovLH(45.0f, (float)WindowWidth / (float)WindowHeight, 1.0f, 1000.0f);Mesh.Effect.GetVariableByName("proj").AsMatrix().SetMatrix(proj);MessagePump.Run(RenderForm, () =>{direct3d.DX10Device.ClearRenderTargetView(renderView, Color.Black);                Mesh.Effect.GetVariableByName("world").AsMatrix().SetMatrix(Matrix.Identity);                Mesh.Effect.GetVariableByName("defaultColor").AsVector().Set(new Vector3(255, 255, 255));Mesh.Render(direct3d.DX10Device);Result res = direct3d.SwapChain.Present(0, SlimDX.DXGI.PresentFlags.None);System.Threading.Thread.Sleep(1);});


The result is ok.

The Render-method from Mesh:
public void Render(Device device)        {        device.InputAssembler.SetInputLayout(layout);               device.InputAssembler.SetPrimitiveTopology(PrimitiveTopology.TriangleList);            device.InputAssembler.SetIndexBuffer(indices, Format.R32_UInt, 0);            device.InputAssembler.SetVertexBuffers(0, binding);            effect.GetTechniqueByIndex(0).GetPassByIndex(0).Apply();            device.DrawIndexed(m_Mesh.Triangles.Length * 3, 0, 0);            device.InputAssembler.SetIndexBuffer(null, Format.Unknown, 0);        }


What about my shader setup. You may have noticed, that i am using float2 in the shadercode for the UVCOORDs, but the following struct in C#-code.
using System.Runtime.InteropServices;[StructLayout(LayoutKind.Sequential)]struct SUVCoord{    public float u;    public float v;}


Or maybe my inputlayout is wrong.
I think the zero offsets are in your input elements aren't correct. Try something like this:

            elements = new InputElement[]            {                new InputElement("INDEX", 0, Format.R32_SInt, 0, 0),                new InputElement("UVCOORD", 0, Format.R32G32_Float, 4, 0),                new InputElement("STARTWEIGHT", 0, Format.R32_SInt, 12, 0),                new InputElement("COUNTWEIGHT", 0, Format.R32_SInt, 16, 0),                new InputElement("POSITION", 0, Format.R32G32B32_Float, 20, 0),                new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 32, 0),            };


See the documentation at: http://msdn.microsoft.com/en-us/library/bb205316%28v=VS.85%29.aspx and http://msdn.microsoft.com/en-us/library/bb205117%28v=VS.85%29.aspx

You could also try setting up an input layout and vertex format that just stores position for testing.
Hello,

thanks again Adam

zero offset were definitely wrong, though it didn't helped.
I changed vertex and input layout, to have just one float3/Vector3 in Shader/C# Code, but still nothing is displayed.

My new vertex buffer and input layout:

counter = 0;Vector3[] FinalPositions = new Vector3[m_Mesh.Vertices.Length];for (int i = 0; i < FinalPositions.Length; ++i){   FinalPositions = m_Mesh.Vertices.FinalPosition;}using (var data = new DataStream(FinalPositions, true, false)){   vertices = new Buffer(device, data,                    new BufferDescription()                    {                        BindFlags = BindFlags.VertexBuffer,                        CpuAccessFlags = CpuAccessFlags.None,                        OptionFlags = ResourceOptionFlags.None,                        SizeInBytes = FinalPositions.Length * Marshal.SizeOf(typeof(Vector3)),                        Usage = ResourceUsage.Default                    });}elements = new[]{    new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0),};layout = new InputLayout(device,                effect.GetTechniqueByIndex(0).GetPassByIndex(0).Description.Signature,                elements);binding = new[]{new VertexBufferBinding(vertices, Marshal.SizeOf(typeof(Vector3)), 0),};


I also noted, that a few methods, like setting effectvariables or applying effectpass, returns a Result. I checked the result multiple times, no errors.

I am starting to think, that my matrices are the problem, so correct me if i am wrong. I am setting the world matrix as Identity-matrix, so my mesh should be at Location(X:0,Y:0,Z:0). My view matrix would then be:

Matrix view = Matrix.LookAtLH(new Vector3(0, 0, 160), new Vector3(0, 0, 0), Vector3.UnitY);Mesh.Effect.GetVariableByName("view").AsMatrix().SetMatrix(view);


As you see in my Mainloop i use the same matrices for my md5mesh and the jupitermesh and jupitermesh works absolutely correct.

MessagePump.Run(RenderForm, () =>{direct3d.DX10Device.ClearRenderTargetView(renderView, Color.Black);Result res = Mesh.Effect.GetVariableByName("world").AsMatrix().SetMatrix(Matrix.Identity);res = Mesh.Effect.GetVariableByName("defaultColor").AsVector().Set(new Vector3(255, 255, 255));jupiterMesh.Effect.GetVariableByName("world").AsMatrix().SetMatrix(Matrix.Identity);                jupiterMesh.Effect.GetVariableByName("defaultColor").AsVector().Set(new Vector3(255, 255, 255));Mesh.Render(direct3d.DX10Device);//jupiterMesh.Draw();res = direct3d.SwapChain.Present(0, SlimDX.DXGI.PresentFlags.None);System.Threading.Thread.Sleep(1);});
*bump*
*bump*
Try to render something simple that you know. Try to render a simple triangle on the screen, once that works, then move to your mesh.

Also, your use of the new operator to set variables is scary.
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.

This topic is closed to new replies.

Advertisement