2012-10-24 33 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)(我很确定这个或者类似的东西存在),以确保你的点位于每对垂直平面之间。如果不在它们之间,那么您可以忽略该交叉点。