Front facing triangles help

Started by
7 comments, last by JohnBolton 18 years, 10 months ago
I am using the *.RAW file format for loading 3D models into my game. The RAW file format is simple, each line of the file lists 3 triangle vertices (x, y and z) that make up a triangle. However I model my objects using CAD and hence use the *.DXF file format – and then convert *.DXF to *.RAW files. This works great, but some of the triangles are GL_BACK facing (I forget if that is CCW or CW, whatever). In my GL setup: glEnable(GL_CULL_FACE); glCullFace(GL_BACK); Thus, I need ‘em all to be GL_FRONT facing –to speed things up, lighting etc. Here are my functions to load *.RAW files where I would like to also make each triangle GL_FRONT facing:

struct marker
{
   float x, y, z;
};

void CalculateNormal(marker* normal, marker o, marker b, marker c)
{
   b.x = b.x - o.x;
   b.y = b.y - o.y;
   b.z = b.z - o.z;

   c.x = c.x - o.x;
   c.y = c.y - o.y;
   c.z = c.z - o.z;

/* Cross Product. */
   normal->x = (b.y * c.z) - (b.z * c.y);
   normal->y = (b.z * c.x) - (b.x * c.z);
   normal->z = (b.x * c.y) - (b.y * c.x);

/* Normalise. */
   float length = sqrt(normal->x * normal->x + normal->y * normal->y + normal->z * normal->z);
   normal->x = normal->x / length;
   normal->y = normal->y / length;
   normal->z = normal->z / length;

   return;
}

#define COLINEAR        0x00
#define CLOCKWISE       0x01
#define ANTICLOCKWISE   0x02

int TriangleOrientation(marker a, marker b, marker c)
{
   double determinant = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
   int result = COLINEAR;

   if (determinant < 0)
   {
      result = CLOCKWISE;
   }

   if (determinant > 0)
   {
      result = ANTICLOCKWISE;
   }

   return result;
}

/* Load a RAW file of triangle points. */
void LoadRAW(char* szFileName, float scale, marker* m, marker* normal, int& n)
{
	FILE* file = fopen(szFileName, "r");
   int ch = 0;

   n = 0;

	if (file != NULL)
   {
      ch = getc(file);

	   while (ch != EOF)
      {
         ungetc(ch, file);
         fscanf(file, "%f %f %f %f %f %f %f %f %f\n", &m[n + 0].x,
                                                      &m[n + 0].y,
                                                      &m[n + 0].z,
                                                      &m[n + 1].x,
                                                      &m[n + 1].y,
                                                      &m[n + 1].z,
                                                      &m[n + 2].x,
                                                      &m[n + 2].y,
                                                      &m[n + 2].z);

         m[n + 0].x = m[n + 0].x * scale; /* Scale the model. */
         m[n + 0].y = m[n + 0].y * scale;
         m[n + 0].z = m[n + 0].z * scale;
         m[n + 1].x = m[n + 1].x * scale;
         m[n + 1].y = m[n + 1].y * scale;
         m[n + 1].z = m[n + 1].z * scale;
         m[n + 2].x = m[n + 2].x * scale;
         m[n + 2].y = m[n + 2].y * scale;
         m[n + 2].z = m[n + 2].z * scale;

         if (TriangleOrientation(m[n + 0], m[n + 1], m[n + 2]) == CLOCKWISE)
         {
            marker t = m[n + 0]; // Help here!
            m[n + 0] = m[n + 2]; // Help here!
            m[n + 2] = t;        // Help here!
         }

         CalculateNormal(&normal[n], m[n + 0], m[n + 1], m[n + 2]);
         
         n = n + 3;

         ch = getc(file);
      }

      fclose(file);
   }
     
   return;
}

This does not work! How do I swap the vertices of my triangles so that they each is front facing???
Advertisement
I think you are swapping the vertices correctly, however I'm not so sure about your TriangleOrientation() function. It looks like you're projecting the triangle into the xy plane, and testing the resulting triangle's winding in that plane. I'm not positive, but I don't think this gives you any useful information. First of all, the triangle may be nearly perpendicular to the xy plane. More importantly, I think triangles which are facing away from the xy plane will retain their orientation, while triangles facing the xy plane will be flipped (or maybe vice versa). I doubt that's what you want.
Thanks and Ouch, I missed that (I just cut 'n' paste from my old 2D app)! How do I correct the function to make it work for 3D?
Quote:How do I correct the function to make it work for 3D?
I'm not sure. I think that to determine whether the winding of a triangle is 'correct' or not in 3d, you have to have some sort of reference.

One fact that can sometimes be exploited is that for correctly wound triangles that share an edge, the edge endpoints will appear in opposite order in each of the triangles (draw it out on paper if you're not sure what I mean). However, it sounds like you're dealing with raw vertices rather than indexed data, so you'd have to compare the vertices themselves. It's likely the components of shared vertices in the model would have exactly the same values, but floating-point equality tests are always dicey.

It seems there would be a standard method for fixing incorrectly wound triangles in 3d models, but atm it's not occuring to me. Perhaps someone else will post a solution...
Thanks, you've given starting place. Google does not seem to be much help (or I just do not know how to word my search). Anyone else?

Can I just find the determinant of a 3x3 matrix. Would that help???
It is not possible to determine if a triangle is front or back facing simply by the positions of the vertexes. However, you can tell by the exported normal which way a triangle faces.

Anyway, something is messed up if the CAD program exports some triangles with CW vertexes and others with CCW vertexes, unless it assumes that both sides are drawn.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
How does opengl determine if a triangle is front or back facing when no normal is given???
I do not program in GL, but in general the normal of a polygon is determined by the positions of the vertices and the order that the vertices are listed: clockwise or counter-clockwise. I believe counter-clockwise ordering is the most common, this is most likely what GL uses (correct me if I'm wrong). This is called the left-handed rule, which you can demonstrate by taking your left hand and rolling your fingers from vertex to vertex in the counter-clockwise order, and your thumb will be pointing in the direction of the polygon's normal. A normal is computed by calculation the cross product of two coplanar edges of the polygon.
Quote:Original post by sjf
How does opengl determine if a triangle is front or back facing when no normal is given???

Face culling is done in the hardware after the vertex shader has transformed the vertexes into clip space and before triangles are rasterized. It uses the same 2D algorithm that you wrote in your original post to determine if the triangle is facing towards the camera or away from the camera.

You can't make a triangle "front-facing" when you load the vertexes unless the camera always has the same orientation, because if a triangle is front-facing when the camera is points in one direction, it is back-facing when the camera points in the opposite direction.

But even assuming the camera always has the orientation, why do you want to turn all the triangles around to face the camera? If you want to see both sides of the triangles, you could turn off face culling (glDisable(GL_CULL_FACE)) and not worry about which way they are facing.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!

This topic is closed to new replies.

Advertisement