2017-02-23 34 views
0

我需要在C#中的两个模型之间执行布尔减法。其中一个网格完全位于另一个网格内,所以我希望能够扭转一个模型的法线并将两个模型相加。尽管如此,我仍然对如何改变法线方向感到迷茫。C#翻转曲面法线

这是我如何计算的表面法线:

//creates surface normals 
    Vector3D CalculateSurfaceNormal(Point3D p1, Point3D p2, Point3D p3) 
    { 
     Vector3D v1 = new Vector3D(0, 0, 0);    // Vector 1 (x,y,z) & Vector 2 (x,y,z) 
     Vector3D v2 = new Vector3D(0, 0, 0); 
     Vector3D normal = new Vector3D(0, 0, 0); 

     // Finds The Vector Between 2 Points By Subtracting 
     // The x,y,z Coordinates From One Point To Another. 

     // Calculate The Vector From Point 2 To Point 1 
     v1.X = p1.X - p2.X;     
     v1.Y = p1.Y - p2.Y;     
     v1.Z = p1.Z - p2.Z;     
     // Calculate The Vector From Point 3 To Point 2 
     v2.X = p2.X - p3.X;     
     v2.Y = p2.Y - p3.Y;     
     v2.Z = p2.Z - p3.Z;     

     // Compute The Cross Product To Give Us A Surface Normal 
     normal.X = v1.Y * v2.Z - v1.Z * v2.Y; // Cross Product For Y - Z 
     normal.Y = v1.Z * v2.X - v1.X * v2.Z; // Cross Product For X - Z 
     normal.Z = v1.X * v2.Y - v1.Y * v2.X; // Cross Product For X - Y 

     normal.Normalize(); 

     return normal; 
    } 

我被告知通过否定它扭转了正常:

n = CalculateSurfaceNormal(p1, p2, p3); 
n = new Vector3D(-1 * n.X, -1 * n.Y, -1 * n.Z); 

我觉得值被否定,但是当我在3D程序中查看模型,模型中没有改变。

另一个建议是通过改变向量的顺序来尝试背面剔除。我试图通过交换v1和v2的顺序:

//creates invertedsurface normals 
    Vector3D CalculateInvertedSurfaceNormal(Point3D p1, Point3D p2, Point3D p3) 
    { 
     Vector3D v1 = new Vector3D(0, 0, 0);    // Vector 1 (x,y,z) & Vector 2 (x,y,z) 
     Vector3D v2 = new Vector3D(0, 0, 0); 
     Vector3D normal = new Vector3D(0, 0, 0); 

     // Finds The Vector Between 2 Points By Subtracting 
     // The x,y,z Coordinates From One Point To Another. 

     // Calculate The Vector From Point 2 To Point 1 
     v2.X = p1.X - p2.X; 
     v2.Y = p1.Y - p2.Y; 
     v2.Z = p1.Z - p2.Z; 
     // Calculate The Vector From Point 3 To Point 2 
     v1.X = p2.X - p3.X; 
     v1.Y = p2.Y - p3.Y; 
     v1.Z = p2.Z - p3.Z; 

     // Compute The Cross Product To Give Us A Surface Normal 
     normal.X = v1.Y * v2.Z - v1.Z * v2.Y; // Cross Product For Y - Z 
     normal.Y = v1.Z * v2.X - v1.X * v2.Z; // Cross Product For X - Z 
     normal.Z = v1.X * v2.Y - v1.Y * v2.X; // Cross Product For X - Y 

     normal.Normalize(); 

     return normal; 
    } 

模型没有变化。

这里是整个代码:

private void SaveMoldMeshtoStlFile(MeshGeometry3D mesh, string filename) 
    { 
     if (mesh == null) 
      return; 

     if (File.Exists(filename)) 
     { 
      File.SetAttributes(filename, FileAttributes.Normal); 
      File.Delete(filename); 
     } 

     Point3DCollection vertexes = mesh.Positions; 
     Int32Collection indexes = mesh.TriangleIndices; 

     Point3D p1, p2, p3; 
     Vector3D n; 

     string text; 

     using (TextWriter writer = new StreamWriter(filename)) 
     { 
      writer.WriteLine("solid Bolus"); 

      for (int v = 0; v < mesh.TriangleIndices.Count(); v += 3) 
      { 
       //gather the 3 points for the face and the normal 
       p1 = vertexes[indexes[v]]; 
       p2 = vertexes[indexes[v + 1]]; 
       p3 = vertexes[indexes[v + 2]]; 
       n = CalculateInvertedSurfaceNormal(p1, p2, p3); 

       text = string.Format("facet normal {0} {1} {2}", n.X,n.Y, n.Z); 
       writer.WriteLine(text); 
       writer.WriteLine("outer loop"); 
       text = String.Format("vertex {0} {1} {2}", p1.X, p1.Y, p1.Z); 
       writer.WriteLine(text); 
       text = String.Format("vertex {0} {1} {2}", p2.X, p2.Y, p2.Z); 
       writer.WriteLine(text); 
       text = String.Format("vertex {0} {1} {2}", p3.X, p3.Y, p3.Z); 
       writer.WriteLine(text); 
       writer.WriteLine("endloop"); 
       writer.WriteLine("endfacet"); 

      } 


     } 
    } 

    //creates inverted surface normals 
    Vector3D CalculateInvertedSurfaceNormal(Point3D p1, Point3D p2, Point3D p3) 
    { 
     Vector3D v1 = new Vector3D(0, 0, 0);    // Vector 1 (x,y,z) & Vector 2 (x,y,z) 
     Vector3D v2 = new Vector3D(0, 0, 0); 
     Vector3D normal = new Vector3D(0, 0, 0); 

     // Finds The Vector Between 2 Points By Subtracting 
     // The x,y,z Coordinates From One Point To Another. 

     // Calculate The Vector From Point 2 To Point 1 
     v2.X = p1.X - p2.X; 
     v2.Y = p1.Y - p2.Y; 
     v2.Z = p1.Z - p2.Z; 
     // Calculate The Vector From Point 3 To Point 2 
     v1.X = p2.X - p3.X; 
     v1.Y = p2.Y - p3.Y; 
     v1.Z = p2.Z - p3.Z; 

     // Compute The Cross Product To Give Us A Surface Normal 
     normal.X = v1.Y * v2.Z - v1.Z * v2.Y; // Cross Product For Y - Z 
     normal.Y = v1.Z * v2.X - v1.X * v2.Z; // Cross Product For X - Z 
     normal.Z = v1.X * v2.Y - v1.Y * v2.X; // Cross Product For X - Y 

     normal.Normalize(); 

     return normal; 
    } 

是否有我的代码错误?我错过了什么吗?我已经在几个不同的程序中试用了导出的模型,并且都显示导出的模型仍然具有向外的法线。我尝试翻转Blender中的法线,发现其他程序也显示法线翻转,所以我相当确定这是我的程序的问题。

回答

0

找出解决方案。

每个三角形的点的顺序是至关重要的。如果点的顺序不支持正常的方向,我发现其他程序会自动纠正正常。

在那里我有这样的:

//gather the 3 points for the face and the normal 
      p1 = vertexes[indexes[v]]; 
      p2 = vertexes[indexes[v + 1]]; 
      p3 = vertexes[indexes[v + 2]]; 
      n = CalculateInvertedSurfaceNormal(p1, p2, p3); 

我,而不是逆转改变这个点的方向:

//gather the 3 points for the face and the normal 
      p3 = vertexes[indexes[v]]; 
      p2 = vertexes[indexes[v + 1]]; 
      p1 = vertexes[indexes[v + 2]]; 
      n = CalculateInvertedSurfaceNormal(p1, p2, p3); 

这解决了我的问题。