Sign in to follow this  
MrSparkle27

DX Mesh creation with Normals

Recommended Posts

Hi! I create a DirectX9 mesh from a VertexBuffer and an IndexBuffer. To define the normals of each vertex, I have to create the mesh's VertexBuffer with the CustomVertex.PositionNormal declaration. This means that the Normal declaration is per vertex, but in the DirectX model file (*.x), the Normals are declared for each index. How can I declare different Normals for each triangle so they'll have hard edges? Thank you! Christian

Share this post


Link to post
Share on other sites
I don't really understand your question, but if all you want is to compute normals for the mesh, this code worked for me (assuming MDX):


if ((mesh.VertexFormat & VertexFormats.Normal) == 0)
{
Mesh temp = mesh.Clone(mesh.Options.Value, mesh.VertexFormat | VertexFormats.Normal, device);
temp.ComputeNormals();
mesh.Dispose();
mesh = temp;
}





I think I got it from the MDX documentation.

Share this post


Link to post
Share on other sites
There is no built in functionality to set up a mesh for per-face/flat lighting, you'll have to implement this yourself.

A simple enough set of loops can traverse through indexed geometry and duplicate the appropriate vertices and setting each of the three vertices to have the same (face) normal.

Remember that as soon as one attribute of the vertex changes you have to split it - you can't have shared positions but different normals for example.

hth
Jack

Share this post


Link to post
Share on other sites
After reading jollyjeffers's post and re-reading your post, I see that I misunderstood your question.

It sounds like what you want is flat shading, in which case you just need to do this:

device.RenderState.ShadeMode = ShadeMode.Flat;

Share this post


Link to post
Share on other sites
yup, forcing flat shading will work but bare in mind that you may not get identical results to face-normals stored by a modelling application. They'll likely be very close so depends what sort of code complexity trade-off you want!

hth
Jack

Share this post


Link to post
Share on other sites
Thank you for your quick answers! I want to have both, smooth edges and hard edges in the same model. I developed a polygon class that uses SmoothingGroups like in 3ds max. Two adjoining polygons that share the same SmoothingGroup should have interpolated normals applied to each shared vertex.

Otherwise, the shared vertices should have an independent normal for each polygon (e.g. triangle). This is what causes the trouble because I don't know how to apply the normals when creating the Mesh from the VertexBuffer and the IndexBuffer.

This is my code so far (the CustomVertex.PositionOnly should be replaced by CustomVertex.PositionNormal, but this won't solve the problem...):


public static Mesh ConvertToMesh(PolyObj obj)
{
List<Vector3D> vertexBuffer = obj.CreateVertexBuffer();
List<int> indexBuffer = obj.CreateIndexBuffer();


// Create a new Mesh from the VertexBuffer
Mesh mesh = new Mesh(indexBuffer.Count / 3, vertexBuffer.Count,
MeshFlags.Managed, CustomVertex.PositionOnly.Format, Renderer.Direct3DDevice);

// Write into the VertexBuffer
using (VertexBuffer vb = mesh.VertexBuffer)
{
GraphicsStream data = vb.Lock(0, 0, LockFlags.None);

foreach (Vector3D v in vertexBuffer)
{
Vector3 dxv = new Vector3((float)v.X, (float)v.Y, (float)v.Z);
data.Write(new CustomVertex.PositionOnly(dxv));
}

vb.Unlock();
}


// Set the IndexBuffer
using (IndexBuffer meshIndexBuffer = mesh.IndexBuffer)
{
meshIndexBuffer.SetData(indexBuffer.ToArray(), 0, LockFlags.None);
} // using

return mesh;

}


Share this post


Link to post
Share on other sites
I'm not positive if I understand you right. But it sounds like you want to adjust the normals that are provided in the x-file according to which faces are adjacent to which, and you have a list or array of face indices vs. smoothing group. I'm not sure how your smoothing group info is organized, but I presume it's some sort of list that tells you the smoothing group (if any) to which a face (triangle) belongs.

First: are you generating a mesh that has 3 vertices per face? Not just 3 indices per face! That is, there are no shared vertices between faces. You'll have to do that if you want different vertex normals for vertices which are at the same position for adjacent triangles but the triangles are not in the same smoothing group.

As a result, my suggestion is rather generalized. I've only worked in C++ but, hopefully, you can translate my comments.

1. load the vertices and indices from the x-file.
2. generate an adjacency table for the mesh. The adjacency table tells you which faces are adjacent to which. That is, for each face, there are three face indices for each of the three possible edges. If an index is 0xffff (or 0xffffffff), then that's a hard edge; otherwise, it's the face index for the triangle adjacent to that edge.
3. go through your smoothing group list. For each face, calculate the appropriate normal for each of the 3 vertices in the face by checking which (if any) adjacent faces on the two edges to which each vertex belongs are in the same group. Store the calculated normals in a separate array (e.g., vertex index with it's normal) so you don't use an already smoothed normal in your calc.
4. go back through your list of calculated normals, stuffing the normals into the vertex buffer at the appropriate vertex position.

I hope that has something to do with what you're asking about. [smile]

Share this post


Link to post
Share on other sites
Quote:
so the trick is to create 3 different vertices at the same position but with different normals to achieve hard edges

Yes. The number of vertices = 3 * number of faces. You'll probably start out with an index buffer that looks like ( 0, 1, 2, 3, 4, ... ) until you optimize it.

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