2011-09-30 69 views
0

我試圖爲Vector3s(或者說,VertexPositionNormalTextures)編寫一個Comparer類,它將按順時針順序排列它們的列表以修復我的背面剔除問題。我試圖在Web上調整一個非常常見的方法,它在兩個向量之間得到一個有符號的角度。但是,在運行時,我的列表會抱怨排序方法不一致,也就是說兩個項目在不同階段不一致比較,或者項目與自身進行比較,並且發現不相等。爲什麼我的Vector3s順時針排序不一致?

這裏的比較器類:

public class ClockwiseSorter : IComparer<VertexPositionNormalTexture> 
    { 
     private Vector3 center; 
     public ClockwiseSorter(Vector3 c) 
     { 
      center = c; 
     } 
     public int Compare(VertexPositionNormalTexture a, VertexPositionNormalTexture b) 
     { 
      Vector3 normal = Vector3.Cross(a.Position - center, b.Position - center); 
      normal.Normalize(); 
      double theta = GetSignedAngleBetween2DVectors(a.Position - center, b.Position - center, Vector3.Cross(a.Position - center, normal)); 

      if (theta > 0) 
       return -1; 
      else if (theta < 0) 
       return 1; 
      else 
       return 0; 
     } 

     /// Find the angle between two vectors. This will not only give the angle difference, but the direction. 
     /// For example, it may give you -1 radian, or 1 radian, depending on the direction. Angle given will be the 
     /// angle from the FromVector to the DestVector, in radians. 
     /// </summary> 
     /// <param name="FromVector">Vector to start at.</param> 
     /// <param name="DestVector">Destination vector.</param> 
     /// <param name="DestVectorsRight">Right vector of the destination vector</param> 
     /// <returns>Signed angle, in radians</returns>   
     /// <remarks>All three vectors must lie along the same plane.</remarks> 
     public static double GetSignedAngleBetween2DVectors(Vector3 FromVector, Vector3 DestVector, Vector3 DestVectorsRight) 
     { 
      FromVector.Normalize(); 
      DestVector.Normalize(); 
      DestVectorsRight.Normalize(); 

      float forwardDot = Vector3.Dot(FromVector, DestVector); 
      float rightDot = Vector3.Dot(FromVector, DestVectorsRight); 

      // Keep dot in range to prevent rounding errors 
      forwardDot = MathHelper.Clamp(forwardDot, -1.0f, 1.0f); 

      double angleBetween = Math.Acos(forwardDot); 

      if (rightDot < 0.0f) 
       angleBetween *= -1.0f; 

      return angleBetween; 
     } 

    } 

我通過平均所有向量的價值得到了中心向量:

 private Vector3 AverageVectors(List<VertexPositionNormalTexture> vectors) 
    { 
     Vector3 sum = Vector3.Zero; 
     foreach (VertexPositionNormalTexture vector in vectors) 
      sum += vector.Position; 
     return (sum/vectors.Count); 
    } 

難道我搞砸了某個地方,而不是想着這是否正確?還是我錯誤地計算了正常或中心?背面剔除已經只是一個頭痛對我來說,我是那種不顧一切地繼續......

+0

我是否正確地假設你每次排序三個頂點?除此之外,對背面剔除問題沒有意義。 – TreDubZedd

+0

我實際上正在排序4.這有點奇怪,是的。我正在排列四邊形而不是三角形水平,但如果這更容易,我可以輕鬆地過渡到三角形水平。 –

回答

1

如果你有一個頂點A,B和C的三角形,

正常的三角形calcultated與跨產品操作

N = (B-A) x (C-A) 

現在您必須確定面向正常的方向。當你在代碼中使用,但如果網不是凸它可以提供錯誤的結果

enter image description here

這可能是有用的網格的中心。

您必須確定法線和從三角形中心到網格中心的矢量構建之間的角度。

TriangleCenter= (A+B+C)/3; 

P = MeshCenter - TriangleCenter; 

P.Normalize(); 
N.Normalize(); 

the dot product d = P.N = |P||N|.cos(alfa) 

if (d>0) P and N are in the same direction (AntiClockWise order) 
if (d<0) P and N are in opposite direction (Clockwise order) 
+0

老實說,我有點困惑,爲什麼我自己現在已經睡了一覺..我想我很困惑兩種方法。我的想法是以中心周圍的角度爲中心。恐怕我不明白你的繪圖的相關性。儘管如此,我還是要走出最後一點:所以我有一個三角形的所有3個點,並且我希望它們按照臉部的法線順時針排列。什麼是「正確的方式」來計算? –

+0

中心c1或c2的位置是任意的,對於相同的三角形,如果中心位於AB的右側或左側,則順序不同。你的計算。要看看如何確定它,你可以看到這[回答](http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order/1165943#1165943)。 – Blau

+0

這似乎是一個很好的2D矢量解決方案,但我不知道如何用3D矢量來完成。 –

相關問題