Some triangles are culled if their normals are pointing outward

Started by
5 comments, last by EngineCoder 14 years, 8 months ago
I'm making my engine's objects in Blender and exporting them as COLLADA .dae. In my engine I use backface culling and expect every face to be counter-clockwise. That's what Blender's COLLADA exporter does, right? Some meshes have all their triangles rendered only when I point their normals inside in Blender, and that messes up my lighting. I made some code that tests if the winding is counter-clockwise, and if not, it changes it, but it causes almost half of my triangles to disappear, so I don't use it ATM:

Vector v1crossv2 = mesh.back().vertex[mesh.back().face[f].vInd[1]].cross(mesh.back().vertex[mesh.back().face[f].vInd[2]]);

            if (v1crossv2.x < .0f && v1crossv2.y < .0f && v1crossv2.z < .0f) {
                unsigned int tmpVertInd = mesh.back().face[f].vInd[1];
                mesh.back().face[f].vInd[1] = mesh.back().face[f].vInd[2];
                mesh.back().face[f].vInd[2] = tmpVertInd;
            }

            Vector v0crossv2 = mesh.back().vertex[mesh.back().face[f].vInd[0]].cross(mesh.back().vertex[mesh.back().face[f].vInd[2]]);

            if (v0crossv2.x < .0f && v0crossv2.y < .0f && v0crossv2.z < .0f) {
                unsigned int tmpVertInd = mesh.back().face[f].vInd[0];
                mesh.back().face[f].vInd[0] = mesh.back().face[f].vInd[2];
                mesh.back().face[f].vInd[2] = tmpVertInd;
            }

            Vector v0crossv1 = mesh.back().vertex[mesh.back().face[f].vInd[0]].cross(mesh.back().vertex[mesh.back().face[f].vInd[1]]);

            if (v0crossv1.x < .0f && v0crossv1.y < .0f && v0crossv1.z < .0f) {
                unsigned int tmpVertInd = mesh.back().face[f].vInd[0];
                mesh.back().face[f].vInd[0] = mesh.back().face[f].vInd[1];
                mesh.back().face[f].vInd[1] = tmpVertInd;
                }

My iOS 3D action/hacking game: http://itunes.apple....73873?ls=1&mt=8
Blog
Advertisement
Not sure if this helps you or not, but my experience with 3D content has been that the culling mode is per material, in the sense that the content designer (you) marks a group of triangles in their modeling program and says "I want these triangles to be rendered with no back-face culling because they are not double-sided triangles". You might do that for flags or tents or windows or ships sails or similar thin meshes that don't really have volume in one plane.

So if you can identify and group the triangles that you know are not double-sided and either (1) make them double-sided via Blender or (2) mark them as not using back-face culling during the export, that would be the way to go.
I don't understand your detection code, would you explain? How is it that "v.x < 0 and v.y < 0 and v.z < 0" is equivalent to "the triangle is facing back?
I don't think it's that simple to detect if a triangle is facing the right direction, because you have to define what "the right direction is". It's easy for convex meshes if you know a point inside the mesh as a reference (usually the origin), but if the mesh is concave...

Also, (might be unrelated) what topology are you using? Be careful, when you draw a triangle strip, the back-face culling bit is flipped after every triangle...
Quote:Original post by jantaHow is it that "v.x < 0 and v.y < 0 and v.z < 0" is equivalent to "the triangle is facing back?

From the following link: "A positive cross product means we have a counterclockwise polygon."
http://local.wasp.uwa.edu.au/~pbourke/geometry/clockwise/index.html.
Quote:Also, (might be unrelated) what topology are you using?

I'm not sure about the topology. I just use those vertex lists and triangle indices exported by Blender.

update: There's also a weirdness: If I change glFrontFace(GL_CCW); to glFrontFace(GL_CW); it makes no difference. Of course I also have glEnable(GL_CULL_FACE); and glCullFace(GL_BACK);
My iOS 3D action/hacking game: http://itunes.apple....73873?ls=1&mt=8
Blog
Quote:Original post by EngineCoder
Quote:Original post by jantaHow is it that "v.x < 0 and v.y < 0 and v.z < 0" is equivalent to "the triangle is facing back?

From the following link: "A positive cross product means we have a counterclockwise polygon."
http://local.wasp.uwa.edu.au/~pbourke/geometry/clockwise/index.html.

You should pay more attention to details, and put things into context.
Quote:
If the crossproduct is positive then it rises above the plane (z axis up out of the plane)[...]

See how he's finding the winding order of a two-dimensional polygon? His method is correct within his context, but it doesn't extend as easily to three-dimensional winding order detection.

What he's basically doing is calculating the normal of the polygon, and determines whether it's pointing up or down, where up is defined as one winding order and down as another. The equivalent of his method in three dimensions would be to calculate the normal and determine its direction relative the reference plane that determines correct winding order (the XY-plane with normal pointing along the Z-axis in his article), by taking the dot product of the normal of the polygon and the reference plane. But the reference plane is what you need to know for each polygon, and you cannot do that on an arbitrary geometry without more information on what exactly determines a front and back face.
Does this problem happen with all your meshes? If possible, try to reproduce the problem with a simple convex mesh (look up what that means if you don't know) like a sphere or a cube that contains the origin.

Then for each triangle of the mesh defined by p1, p2, p3 (in that order)
- Figure out the normal with N = p1p2 x p1p3
- Make sure the normal is pointing outward: N.x*p1.x + N.y*p1.y + N.z*p1.z > 0

That being said, if changing the culling state makes no difference, your problem might be something else.

Disable culling completely and see if that helps.

If it does not, then make sure you're drawing your mesh with the proper topology The fact that you don't know is a bad sign. It's important to know; drawing a vertex array as a triangle list or as a triangle strip (there are others, but they are less likely) will give totally different results. That could be your issue too.


Thanks for the help, but I solved the problem in Blender by mirroring the wrongly-lit meshes. Seems that many of the meshes that I had done by duplicating other meshes had their normals wrong.
My iOS 3D action/hacking game: http://itunes.apple....73873?ls=1&mt=8
Blog

This topic is closed to new replies.

Advertisement