2

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
4

1 回答 1

2

从对象外部查看顶点时,顶点应按逆时针顺序排列。(显然,从对象内部观察它们是按顺时针顺序排列的)。

法线应该指向外面。

我读过一些程序会忽略法线,只按顶点顺序进行,我什至读过将法线设置为 {0.0, 0.0, 0.0} 的建议,尽管规范规定法线和顶点顺序应该两者都可以使用。

虽然正常是多余的。对于许多程序,顶点顺序是必要的。我不知道这是否适用于所有程序。我建议使两者都正确。

于 2013-05-22T22:09:24.373 回答