Sign in to follow this  
sjf

Front facing triangles help

Recommended Posts

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???

Share this post


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

Share this post


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

Share this post


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

Share this post


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

Share this post


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

Share this post


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

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