2
\$\begingroup\$

I've been causing myself some confusion lately with regards to vertex winding in a mesh class that i'm writing.

Currently, the mesh contains the appropriate structures for:

  • vertices (vector3)
  • indices (vector3 - actually a custom struct of 3 ints)
  • normals (vector3)
  • colors (vector4)

Starting out simple, i'm trying to model a cuboid with 24 vertices and 12 indices. What is causing me confusion at the moment is how vertex winding is determined for each face. OpenGL-ES seems to be set to counter clockwise winding by default (which can be changed) but i'm really not sure how CCW is determined in 3 dimensions?

It was my understanding that the "front" and "back" of an object would be defined by the direction of the vector for each vertices normal, rather than the ordering of each vertex that defines a "face". It would seem however that this isn't true. Either that, or (more likely) my code isn't entirely correct.

If this isn't the case, how is CCW defined in 3 dimensions? How does this translate for the 6 faces of a cuboid? If I use the same logic for the back face of the cuboid as the front face, surely one of the faces would point inwards?

I'm really struggling to get my head around this when manually defining vertices for my mesh. The confusion really kicks in when I try to work out how vertex data is stored in a model/mesh file created by MAYA or Blender etc. Are all faces oriented outwards when an object is exported?

Or perhaps my original assumption was correct whereby the normals define what is to be determined as the front of each face, but then why does OpenGL have a flag for specifying the vertex winding order?

Also, considering the three vectors A, B and C; surely the same winding (regardless of orientation) could be achieved in three different ways, i.e: A->B->C or B->C->A or C->A->B?

Is there a simple way for determining such things or have I completely missed the mark somewhere?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

OpenGL actually has two sets of normals for every face: one you supply with the GL_NORMAL vertex attribute and one it determines with the winding. This second normal is used to discard faces in backface culling and is determined through the following formula:

// http://glm.g-truc.net - OpenGL Mathematics library

glm::vec3 a, b, c;
glm::vec3 ab = b - a;
glm::vec3 ac = c - a;
glm::vec3 normal = glm::normalize(glm::cross(ab, ac));

If you are confused about the winding of your vertices, try calculating this normal yourself and rendering it on your faces. You can then easily spot where you made a logical error.

EDIT:

Suppose you have a set of vertices and you absolutely have to make sure what the winding is.

Given the face P with vertices a, b and c.

// calculate three axes

glm::vec3 axis_x = glm::normalize(b - a);
glm::vec3 axis_y = glm::normalize(c - a);
glm::vec3 axis_z = glm::cross(axis_x, axis_y);

// construct a transform matrix from our axes

glm::mat3x3 object_transform;
object_transform[0] = axis_x;
object_transform[1] = axis_y;
object_transform[2] = axis_z;

// invert the matrix

glm::mat3x3 object_to_world_transform = glm::inverse(object_transform);

// transform the outward normal using the matrix

glm::vec3 normal = object_to_world_transform * axis_z;

// check winding

if (normal.z > 0.f)
{
    // Counter-clockwise winding
}
else
{
    // Clockwise winding
}

Note: I didn't have time to check this! I might have reversed the check for winding at the end. I'll edit when I get home.

\$\endgroup\$
4
  • \$\begingroup\$ Sorry if I misunderstand, but does that mean that the winding isn't important if you specify your own normals for each vertices? \$\endgroup\$
    – Zack Brown
    Jun 13, 2012 at 13:09
  • \$\begingroup\$ No, it means that winding is always important, because it determines the normal used for face culling. \$\endgroup\$
    – knight666
    Jun 13, 2012 at 13:13
  • \$\begingroup\$ So, how do I determine the vertex winding? Given a set of arbitrary vertices, how do I know which order is CCW? \$\endgroup\$
    – Zack Brown
    Jun 13, 2012 at 13:59
  • \$\begingroup\$ I have updated my answer. \$\endgroup\$
    – knight666
    Jun 13, 2012 at 14:14
4
\$\begingroup\$

It isn't a 3 dimension problem really. The triangle lies on a plane. When visualizing winding order, you change (in your mind's eye) from a 3 dimensional world, to the 2 dimensional world of the plane that the triangle lies on.

No matter what order you set the indices, on one side of that plane the winding is CW, the other, it is CCW.

Whichever side has the winding order the graphics device is expecting, that side only will be drawn.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .