在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); } 

同样,这是我的四元结构,我用它在3d空间中绘制一个“立方体世界”。 public struct Quad {public Vector3 Origin; public Vector3 UpperLeft; public Vector3 LowerLeft; 公共Vector3 UpperRight; 公共Vector3 LowerRight; public Vector3 Normal; 公共Vector3 Up; 公共Vector3左;

  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; } } 

我发现ray类有一个方法intersects(),它以一个平面结构作为参数,并且平面结构在构造函数中取一个法线和原点的距离,但是我的平面有一个位置和法线而不是距原点的距离,所以我无法转换它们。 如何检测我的光线是否与我的四边形结构相交?

编辑:我意识到我不能使用平面结构,因为它不是有限的大小,并且不包括角,就像我的四边形那样。 我现在需要找到一种方法来检测这条光线是否与我创建的四边形相交…

感谢阅读,我意识到这个问题有点冗长,并提前感谢。

我不确定它们的意思是“从原点到法线的距离”,但我认为它只是指距离原点的距离。 您可以从Vector3上的length属性获取。

如果这不起作用,还有一个平面构造函数,它在飞机上占据三个点:

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

您可以将此与平面上的任意3个点(例如四边形的角点)一起使用以创建平面。

由于您使用的是立方体,因此可以使用Ray.Intersects(Plane)方法。 你只需要几架飞机。

确定第一个交叉点后,可以为立方体的每个垂直面构建更多平面。 然后你可以使用Plane.Distance(Vector3) (我很确定这个或类似的东西存在)来确保你的点在每对垂直平面之间。 如果它们不在它们之间,则可以忽略该交集。

不完全是你的问题的直接答案,但也许你发现这相关。

您是否考虑构建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文件的底部包含您已经知道的,计算Ray
  3. 转到Game.cs文件。 在那里你会发现UpdatePicking()调用RayIntersectsModel(…)调用RayIntersectsTriangle(…)

Ray的变换就是这个部分:

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

你想要去多深(你的采摘的准确程度)当然符合你的需要,但你有它。