2014-05-21 12 views
0

我正在XNA中編寫光線三角形碰撞。爲此,我從我的模型生成一個三角形列表,然後使用我用來轉換模型來繪製它的相同矩陣進行變換。然後,我在轉換後的三角形列表上運行一個三角形交集算法,看看我是否擊中它。XNA:轉換個別三角形給出了不同於轉換模型的結果

我明白,這是不是因爲性能問題的最佳解決方案,但改造射線沒有發揮出來,所以我有這個打算。

我的問題是,單獨的三角形轉化也沒有產生變換模型是相同的形狀。

The Problem

在左邊的是該模型由XNA繪製。右側是響應鼠標點擊的區域。 (爲了得到這個圖像,我生成了一個float?-s數組,其中存儲了三角形交集算法在轉換後的三角形上測量的距離。然後,對於每個非空值,我在secreen上繪製了一個像素:像素越高,越接近intersetion方式向照相機。)

我的假設是實際轉化的三角形產生上述的形狀。這意味着單獨轉換它們的頂點不會產生與整體模型轉換相同的結果。我不明白爲什麼。

下面是附圖的代碼:

public void DrawMe(Camera camera, Matrix world, Texture2D texture) 
     { 
     foreach (ModelMesh mesh in ModelToDraw.Meshes) 
      { 
      foreach (BasicEffect effect in mesh.Effects) 
       { 
       effect.TextureEnabled = true; 
       effect.Texture = texture; 
       effect.EnableDefaultLighting(); 
       effect.PreferPerPixelLighting = true; 

       effect.World = world; 
       effect.Projection = camera.Projection; 
       effect.View = camera.View; 
       } 
      mesh.Draw(); 
      } 
     } 

下面是我使用變換三角形的代碼:包含在片信息 在類:

private void transformTriangles() 
    { 
    for (int i=0; i<myTriangles.Length; i++) 
     { 
     transformedTriangles[i] = myTriangles[i].GetCopy(); 
     } 
     foreach (Triangle t in transformedTriangles) 
     { 
     t.Transform(world); 
     } 
    } 

myTriangles包含提取的三角形來自模型。這些存儲在一個自定義的Triangle類中。我測試了這些數據是否準確。

GetCopy簡單地返回具有相同的數據作爲實例生成一個新的三角形實例。

世界就是我用來改變我的模型的矩陣。

在三角形類:

public void Transform(Matrix transformation) 
    { 
    vertices[0] = Vector3.Transform(vertices[0], transformation); 
    vertices[1] = Vector3.Transform(vertices[1], transformation); 
    vertices[2] = Vector3.Transform(vertices[2], transformation); 
    } 

我的目標是對匹配左邊的形狀合適的形狀。任何建議表示讚賞。

謝謝!

編輯:

根據要求,在此是整體三角類:

class Triangle 
    { 
    public Vector3[] vertices; 
    public Vector3 normal; 

    public Triangle(Vector3 A, Vector3 B, Vector3 C) 
     { 
     vertices = new Vector3[3]; 
     vertices[0] = A; 
     vertices[1] = B; 
     vertices[2] = C; 
     calculateNormal(); 
     } 

    public Triangle(Vector3[] vertices) 
     { 
     this.vertices = vertices; 
     calculateNormal(); 
     } 

    private void calculateNormal() 
     { 
     Vector3 AB = new Vector3(); 
     Vector3 AC = new Vector3(); 

     AB = Vector3.Subtract(vertices[1], vertices[0]); 
     AC = Vector3.Subtract(vertices[2], vertices[0]); 
     normal = Vector3.Cross(AB, AC); 
     normal.Normalize(); 
     } 

    private Vector3 project(Vector3 projectUnto, Vector3 toProject) 
     { 
     float multiplier = Vector3.Dot(projectUnto, toProject)/Vector3.Dot(projectUnto, projectUnto); 
     return Vector3.Multiply(projectUnto, multiplier); 
     } 

    private Vector3? calculateIntersectionPoint(Ray r) 
     { 
     if (Vector3.Dot(r.Direction, normal) == 0) 
      { 
      return null; 
      } 

     Vector3 I, w; 
     float multiplier; 

     w = Vector3.Subtract(vertices[0], r.Position); 
     multiplier = Vector3.Dot(w, normal)/Vector3.Dot(r.Direction, normal); 
     I = Vector3.Add(r.Position, Vector3.Multiply(r.Direction, multiplier)); 

     return I; 
     } 

    private bool inside(Vector3? i) 
     { 
     if (i == null) 
      { 
      return false; 
      } 
     float a, b, c; 
     Vector3 AB, AC, BC, v, w, u, AI, BI, CI; 
     Vector3 I = (Vector3) i; 
     AB = Vector3.Subtract(vertices[1], vertices[0]); 
     AC = Vector3.Subtract(vertices[2], vertices[0]); 
     BC = Vector3.Subtract(vertices[2], vertices[1]); 
     AI = Vector3.Subtract(I, vertices[0]); 
     BI = Vector3.Subtract(I, vertices[1]); 
     CI = Vector3.Subtract(I, vertices[2]); 

     v = Vector3.Subtract(AB, project(Vector3.Multiply(BC, -1), AB)); 
     u = Vector3.Subtract(BC, project(Vector3.Multiply(AC, -1), BC)); 
     w = Vector3.Subtract(Vector3.Multiply(AC, -1), project(AB, Vector3.Multiply(AC, -1))); 

     a = 1 - Vector3.Dot(v, AI)/Vector3.Dot(v, AB); 
     b = 1 - Vector3.Dot(u, BI)/Vector3.Dot(u, BC); 
     c = 1 - Vector3.Dot(w, CI)/Vector3.Dot(w, Vector3.Multiply(AC, -1)); 

     return a >= 0 && a <= 1 && b >= 0 && b <= 1 && c >= 0 && c <= 1; 
     } 

    public float? Intersects(Ray ray) 
     { 
     Vector3? I = calculateIntersectionPoint(ray); 
     if (I == null) 
      { 
      return null; 
      } 

     if (inside(I)) 
      { 
      Vector3 i = (Vector3) I; 
      return Vector3.Distance(ray.Position, i); 
      } 

     return null; 
     } 

    public Triangle GetCopy() 
     { 
     return new Triangle(vertices); 
     } 

    public void Transform(Matrix transformation) 
     { 
     vertices[0] = Vector3.Transform(vertices[0], transformation); 
     vertices[1] = Vector3.Transform(vertices[1], transformation); 
     vertices[2] = Vector3.Transform(vertices[2], transformation); 
     } 
    } 

編輯2:

根據要求,代碼產生射線。不能更標準,如果你問我:

private Ray getRay() 
     { 
     Vector3 nearPoint = BoardViewPort.Unproject(new Vector3(ms.X, ms.Y, 0), cam.Projection, cam.View, Matrix.Identity); 
     Vector3 farPoint = BoardViewPort.Unproject(new Vector3(ms.X, ms.Y, 1), cam.Projection, cam.View, Matrix.Identity); 
     Vector3 direction = farPoint - nearPoint; 
     direction.Normalize(); 
     return new Ray(nearPoint, direction); 
     } 
+0

是'Triangle'類還是結構?請顯示你的碰撞碼。 –

+0

老實說,我不知道你在那裏做什麼樣的花哨的東西。以前沒見過有人這樣做過。特別是「內部」方法似乎太過分了。看看[這裏](http://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates)看看如何計算重心座標。我強烈建議您清理數學(或至少編寫單元測試以充分測試它)。這可能就是你的光線轉換不起作用的原因。並使用合理的變量名稱! –

+0

順便說一句,你知道象'*',''和'+'這樣的常用運算符對於向量來說是過載的,對吧?使用那些而不是'Vector3.Subtract'等。這會使你的代碼更具可讀性。 –

回答

0

我只是沒有重新計算轉換後的正常情況。添加calculateNormal(); Transform函數結束語句解決了這個問題。