Reputation: 1112
I'm working on an STL file importer and thought I'd make use of the normal given to determine the triangle winding order. Sample data with 4 triangles is included below (original data has over 70k triangles). My code's logic computes the normal assuming the vertices are specified anticlockwise, then does a dot product of this calculated normal with the supplied normal. If the result is positive, then I assume anticlockwise, else clockwise.
tm.SetCCW(Dot(Cross(facet.getVertex2() - facet.getVertex1(),facet.getVertex3() - facet.getVertex1()),facet.getNormal()) > 0.0);
This logic fails on a set of files from a particular 3D scanner. When I load these files into Rhino3D though, and issue "Dir" to look at the normal direction, Rhino has the direction correct! Same with a couple of other STL viewers I've tried.
My code deduces that the vertices are supplied in clockwise order on the sample data, but when using that winding order, the model is inside-out, implying the supplied normals are wrong.
This leads me to the conclusion that it is convention for STL importers to ignore the supplied normal, and assume anticlockwise winding order. I'm looking for people with more experience in the STL file format to weigh in on whether my assumption is correct.
solid object_name
facet normal -0.651094 0.733745 -0.194150
outer loop
vertex 30.335684 -40.893806 -68.126500
vertex 31.155055 -39.911656 -67.162500
vertex 30.263726 -40.702583 -67.162500
endloop
endfacet
facet normal -0.654292 0.732059 -0.189714
outer loop
vertex 30.335684 -40.893806 -68.126500
vertex 31.225185 -40.098797 -68.126500
vertex 31.155055 -39.911656 -67.162500
endloop
endfacet
facet normal -0.711866 0.677947 -0.183397
outer loop
vertex 31.225185 -40.098797 -68.126500
vertex 31.980540 -39.044870 -67.162500
vertex 31.155055 -39.911656 -67.162500
endloop
endfacet
facet normal -0.714326 0.676343 -0.179716
outer loop
vertex 31.225185 -40.098797 -68.126500
vertex 32.048799 -39.228928 -68.126500
vertex 31.980540 -39.044870 -67.162500
endloop
endfacet
endsolid
EDIT: My calculations for the first facet:
p1 = {30.335684, -40.893806, -68.126500}
p2 = {31.155055, -39.911656, -67.162500}
p3 = {30.263726, -40.702583, -67.162500}
u = p2 - p1 = {0.819371, 0.98215, 0.964}
w = p3 - p1 = {-0.071958, 0.191223, 0.964}
u x w = {0.762454, -0.859241, 0.227356} (calculated normal)
given normal = {-0.651094, 0.733745, -0.194150}
calculated_normal <dot> given_normal = -1.17103
verdict: 90 < theta < 270 where theta is the angle between the calculated and given normals
Upvotes: 3
Views: 3618
Reputation: 41
The vertices should be in counter-clockwise order when the vertices are viewed from outside of the object. (Obviously, viewing from inside the object they are then in clockwise order).
The normal should point outward.
I have read that some programs ignore the normal and only go by the vertex ordering, and I've even read a recommendation to set the normal to {0.0, 0.0, 0.0}, although the specification states that the normal and the vertex order should both be used.
The normal is redundant though. For many programs, the vertex order is all that is necessary. I don't know if that is generally true for all programs. I recommend making both be correct.
Upvotes: 4