2017-02-23 63 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); 

這解決了我的問題。