2012-10-24 68 views
3

所以,我已經成功地取得了光線的代表未投影到世界的鼠標,現在我需要檢查,如果該線可以用四物相交,這裏是我使用來獲取射線代碼:Ray在XNA中與3D四邊形相交?

public Ray GetMouseRay() 
    { 
     Vector2 mousePosition = new Vector2(cursor.getX(), cursor.getY()); 

     Vector3 nearPoint = new Vector3(mousePosition, 0); 
     Vector3 farPoint = new Vector3(mousePosition, 1); 

     nearPoint = viewport.Unproject(nearPoint, projectionMatrix, viewMatrix, Matrix.Identity); 
     farPoint = viewport.Unproject(farPoint, projectionMatrix, viewMatrix, Matrix.Identity); 

     Vector3 direction = farPoint - nearPoint; 
     direction.Normalize(); 

     return new Ray(nearPoint, direction); 
    } 

同樣,這是我的四元結構,我用它在三維空間中繪製「立方體世界」。 public struct Quad { public Vector3 Origin; public Vector3 UpperLeft; public Vector3 LowerLeft; public Vector3 UpperRight; public Vector3 LowerRight; public Vector3正常; public Vector3 Up; public Vector3 Left;

public VertexPositionNormalTexture[] Vertices; 
     public int[] Indexes; 
    public short[] Indexes; 


    public Quad(Vector3 origin, Vector3 normal, Vector3 up, 
     float width, float height) 
    { 
     Vertices = new VertexPositionNormalTexture[4]; 
     Indexes = new short[6]; 
     Origin = origin; 
     Normal = normal; 
     Up = up; 

     // Calculate the quad corners 
     Left = Vector3.Cross(normal, Up); 
     Vector3 uppercenter = (Up * height/2) + origin; 
     UpperLeft = uppercenter + (Left * width/2); 
     UpperRight = uppercenter - (Left * width/2); 
     LowerLeft = UpperLeft - (Up * height); 
     LowerRight = UpperRight - (Up * height); 

     FillVertices(); 
    } 

    private void FillVertices() 
    { 
     // Fill in texture coordinates to display full texture 
     // on quad 
     Vector2 textureUpperLeft = new Vector2(0.0f, 0.0f); 
     Vector2 textureUpperRight = new Vector2(1.0f, 0.0f); 
     Vector2 textureLowerLeft = new Vector2(0.0f, 1.0f); 
     Vector2 textureLowerRight = new Vector2(1.0f, 1.0f); 

     // Provide a normal for each vertex 
     for (int i = 0; i < Vertices.Length; i++) 
     { 
      Vertices[i].Normal = Normal; 
     } 

     // Set the position and texture coordinate for each 
     // vertex 
     Vertices[0].Position = LowerLeft; 
     Vertices[0].TextureCoordinate = textureLowerLeft; 
     Vertices[1].Position = UpperLeft; 
     Vertices[1].TextureCoordinate = textureUpperLeft; 
     Vertices[2].Position = LowerRight; 
     Vertices[2].TextureCoordinate = textureLowerRight; 
     Vertices[3].Position = UpperRight; 
     Vertices[3].TextureCoordinate = textureUpperRight; 

     // Set the index buffer for each vertex, using 
     // clockwise winding 
     Indexes[0] = 0; 
     Indexes[1] = 1; 
     Indexes[2] = 2; 
     Indexes[3] = 2; 
     Indexes[4] = 1; 
     Indexes[5] = 3; 
    } 
} 

我發現射線類有一個方法相交(),這需要平面結構作爲參數,飛機結構需要一個正常的距離起源於構造,但我的飛機有位置和法線,而不是距離原點的距離,所以我不能轉換它們。我如何檢測我的射線是否與四元結構相交?

編輯: 我意識到我不能使用平面結構,因爲它不是有限的大小,也不包括角落,就像我的四邊形一樣。我需要找到一種方法來檢測這條射線是否與我創建的四邊形相交...

感謝閱讀,我意識到這個問題有點冗長,並且在此先感謝。

回答

3

我不確定他們的意思是「從原點到法線的距離」,但我認爲它只是表示距離原點的距離。你可以從Vector3的長度屬性中獲得。

如果不工作,也有對平面這飛機上有三個點,一個構造函數:

public Plane (
    Vector3 point1, 
    Vector3 point2, 
    Vector3 point3 
) 

您可以在飛機上3分,如使用創建一架飛機。

+0

沿着平面的法向矢量的距離意味着,如果平面處於相同的方向,但被翻譯爲它也包含點(0,0,0),它需要移動多遠以達到其實際位置。或者它可能是這個價值的負面影響,我總是混合最後一點:) –

+0

好吧,但不是距離原點到飛機最近的距離?對我來說,這似乎措辭不佳。 –

+0

是的,但它依賴於一個平面可以完全由該正常單位矢量和距離定義的想法。 –

0

對於你的問題並不完全是直接的答案,但也許你會發現這個問題相關。

你有沒有考慮構造一個BoundingBox對象並使用Intersects(Ray)? http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.boundingbox.intersects.aspx

編輯1:這是我通常這樣做。根據你的數據結構,它可能也更容易優化(例如,如果你構造了更大的邊界框來例如鑽孔)。

編輯2: 根據Niko的建議:我不想從樣本中發佈相關的代碼(因爲它總共有兩頁長,以使上下文有意義),但我可以指出你部分,你會感興趣的

  1. http://xbox.create.msdn.com/en-US/education/catalog/sample/picking_triangle
  2. 下載樣本Cursor.cs文件的底部包含你已經知道,在計算雷
  3. 轉到Game.cs文件。在那裏,你會發現UpdatePicking()這就要求RayIntersectsModel(...),它調用RayIntersectsTriangle(...)

光線的變換是這一部分:

Matrix inverseTransform = Matrix.Invert(modelTransform); 

ray.Position = Vector3.Transform(ray.Position, inverseTransform); 
ray.Direction = Vector3.TransformNormal(ray.Direction, inverseTransform); 

你想有多深去(選擇的準確度)是否滿足您的需求,但是您擁有它。

+0

不幸的是,'BoundingBox'是軸對齊的,這意味着它不會像他的'Quad'那樣旋轉。 – neeKo

+0

......只需通過改變射線就可以輕鬆解決這個問題。如果您有興趣,可以在以下兩個示例中演示:http://xbox.create.msdn.com/en-US/education/catalog/sample/picking_triangle和http://xbox.create.msdn.com/en - 美國/教育/目錄/樣本/採摘 – FanerYedermann

+0

嘿,那太好了 - 如果你可以編輯答案包括一個工作樣本,它很可能會被接受! – neeKo

1

由於您正在使用多維數據集,因此可以使用Ray.Intersects(Plane)方法。你只需要更多的飛機。

確定第一個交點後,您可以爲立方體的每個垂直面創建更多平面。然後你可以使用Plane.Distance(Vector3)(我很確定這個或者類似的東西存在),以確保你的點位於每對垂直平面之間。如果不在它們之間,那麼您可以忽略該交叉點。