5

I am trying to render a 3D model (from volvis.org) with Gouraud shading using the marching cubes algorithm. So far I have the normals for each vertex with:

GetNormalForVertex(vertex &b, vertex &a, vertex &c) {
    u.X = a.X - b.X;
    u.Y = a.Y - b.Y;
    u.Z = a.Z - b.Z;
    v.X = c.X - b.X;
    v.Y = c.Y - b.Y;
    v.Z = c.Z - b.Z;

    return  Cross(u,v);
}

I can see a nice flat shading when its rendered. Now, far as I know I need to interpolate those vertex normals to find normal at the intersection point to get Gouraud shading. How could I interpolate the vertex normals?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Floyd Barber
  • 107
  • 1
  • 3
  • 10

2 Answers2

11

First of all, you are not computing vertex normals. You are computing face normals. This is step 1 in the process of computing vertex normals.

The next step is not interpolating anything. What you do is compute the (unnormalized) face normal for each face attached to a vertex. Then add them all together and normalize the result. That is the vertex normal.

How you determine which faces are attached to a vertex is another matter. In your case, because you're building this data via marching cubes, it shouldn't be too difficult to generate or retrieve the triangles from adjacent cubes. But if you're pass the generation step and just have a bag of triangles, then you're going to need an appropriate mesh topology data structure. Winged-edge or Quad-edge are both good choices.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
10

What are a, b and c?

If they're the vertices of a triangle, then you are computing the normal for the triangle, not for any particular vertex. The assumption in that case, is that the entire triangle is flat. This is called flat shading.

If, on the other hand, you wish to interpolate the surface normal across the interior of a triangle (used in Gouraud shading), then you need to have three different normals at the three vertices to begin with. This is a bit less trivial, but still easy. One way is to average the normals of all triangles that share a vertex in order to obtain the normal at that vertex. This obviously requires connectivity information (or you need to extract it somehow).

Once you have three different normals (say na, nb, nc), then the normal at any interior point can be computed via barycentric coordinates. Let the vertices be va, vb, vc and the interior point's barycentric coords be α and β. Then, the interior point v and its normal n are given by:

v = α*va + β*vb + (1 - α - β)*vc
n = α*na + β*nb + (1 - α - β)*nc

This interpolated normal (n) should be used for Gouraud shading.

Rahul Banerjee
  • 2,343
  • 15
  • 16
  • Yes a, b and c are the vertices of a triangle and I compute the normals for each vertex with the function GetNormalForVertex. How can I get the shared vertices if I have an array of triangle structs? – Floyd Barber Mar 26 '13 at 02:19
  • 1
    That's what I meant when I wrote "this is a bit less trivial". I refer you to @Nicol's answer above. – Rahul Banerjee Mar 26 '13 at 05:13