My 3D application works with user-imported 3D models.
Frequently, those models have a few vertices facing into the wrong direction. (For example, there is a 3D roof and a few triangles of that roof are facing inside the building). I want to repair those automatically.

We can make several assumptions about these 3D models: they are completely closed without holes, and the camera is always on the outside.

My idea: Shoot 500 rays from every triangle outwards into all directions. From the back side of the triangle, all rays will hit another part of the model. From the front side, at least one ray will hit nothing.

Is there a better algorithm?
Are there any papers about something like this?

What do you mean by "vertices facing into the wrong direction?" Does that mean you have occasional triangles that are wrapped in a different order than the rest of the mesh? Or normal data stored with the vertex and are pointed in the wrong direction? Or what?
–
chaosTechnicianApr 7 '12 at 17:26

Both: They are wrapped in the wrong order and the normals are wrong. That means, lighting calculations will be wrong and - even worse - triangles disappear when I enable culling.
–
LTRApr 7 '12 at 18:31

2 Answers
2

For each occurrence of each edge in the index list (an edge should never appear more than twice, and exactly twice for a closed model):

If the indices that define the edge appear in the same order more than once, then you've find a winding order disagreement.

0---1
| /|
| / |
|/ |
3---2

This quad could be defined by the index list (0,1,3,1,2,3), where the faces are (obviously) (0,1,3) and (1,2,3).

Note that the shared edge (1,3) appears in opposite order - (1,3) and (3,1) - which is required for the faces to have the same winding order. If you saw something like:

(0,1,3),(2,1,3), where the edge(1,3) appears in the same order in both faces, then they face opposite directions and one of them needs to be flipped.

Pick one of the faces that contains the edge and flip it by swapping the position of two of the indices within the list.

Repeat until you've traversed the entire list.

The only issue I can see here is if the edge you start with is backwards/part of a face that is wound in the wrong direction, in which case you'd wind up with a model that's backwards. However, you can try and detect that by counting the number of faces that you've flipped, and, if you reach a certain threshold - say, half of the total faces in the model - pick one of the faces that you've flipped - any one will do - and start over.

Follow-up

I didn't mention this before, but it might be wise to start with one face, then adjust the faces to which it is connected, and the ones to which those are connected, etc., however I have a weird feeling that that level of logic is unnecessary. As long as an edge is never flipped twice, everything should agree after a single pass. Feel free to point out or relay experience or problems with this method

You don't need a heuristic to detect the inverted model: take an arbitrary line or ray through the model, and you know the proper facing of the outermost triangle(s) it hits. (Unless your ray falls through the crack between two triangles...)
–
Kevin ReidApr 8 '12 at 3:11

If we assume that most face normals are correct, then you can query the surrounding face normals and dot them with the current face. If the dot product is negative, the normal is facing the wrong way.

You may have to add some heuristics in there where (this is just an e.g.) if 4 of the 5 surrounding face normals are facing one way (their dot product is positive) then your heuristic assumes that the surrounding face #5 is facing the wrong way.

This relies on a smooth object to work. A square pyramid, for example, would always have its base facing toward the point of the pyramid using this method. And a cube would be completely undefined, since each face's normal would have a dot product of 0 against each of its neighbors.
–
Trevor PowellApr 7 '12 at 22:52

@TrevorPowell: Good point (although the heuristic can consider the dot product >= 0 to be good but a dot product of 0 is not guaranteed for a cube's faces due to rounding error), this method will also fail with surfaces that have two faces at angles more than 90 degrees.
–
SamaursaApr 8 '12 at 0:43