Sign in to follow this  
Coolkill

SlimDX DirectX10 Display MD5mesh

Recommended Posts

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[i].vertIndex0;
tmpIndices[counter++] = m_Mesh.Triangles[i].vertIndex1;
tmpIndices[counter++] = m_Mesh.Triangles[i].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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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[i].countWeight; ++j)
{
SMD5Weight weight = m_Mesh.Weights[m_Mesh.Vertices[i].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[i].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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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[i] = m_Mesh.Vertices[i].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);
});

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Hello,

i already displayed the jupitermesh.smd from the samples and only then moved to displaying the md5mesh. That is the reason why i am so confused.

Why is my use of the new operator scary?
That is not final code, it is just for testing. Maybe there is a small impact on performance, but functionality definitely is not affected. The new operator in C# works differently from the one used in C++ ;)

[Edited by - Coolkill on October 4, 2010 2:15:07 AM]

Share this post


Link to post
Share on other sites
Please don't bump your thread like this. If nobody has responded, that likely means nobody knows what's wrong or, more likely, you have not supplied sufficient information. For example, your most recent (content-containing) post suggests that you can display other meshes, so the problem is likely in your loading code or mesh setup and not the code you've posted. Or any of the code that you need to *change* to display the Jupiter mesh.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this