简体   繁体   English

Ray在XNA中与3D四边形相交?

[英]Ray intersection with 3D quads in XNA?

So I have successfully made a ray the represents the mouse unprojected into the world, and now I need to check if that ray can intersect with a quad object, here is the code I use to get the ray: 所以我已经成功制作了一个代表鼠标未被投射到世界的光线,现在我需要检查光线是否可以与四边形物体相交,这里是我用来获取光线的代码:

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

And similarly, this is my quad struct, which I use to draw a "cube world" in 3d space. 同样地,这是我的四元结构,我用它在3d空间中绘制一个“立方体世界”。 public struct Quad { public Vector3 Origin; public struct Quad {public Vector3 Origin; public Vector3 UpperLeft; public Vector3 UpperLeft; public Vector3 LowerLeft; public Vector3 LowerLeft; public Vector3 UpperRight; 公共Vector3 UpperRight; public Vector3 LowerRight; 公共Vector3 LowerRight; public Vector3 Normal; public Vector3 Normal; public Vector3 Up; 公共Vector3 Up; public Vector3 Left; 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;
    }
}

I found that the ray class has a method intersects() which takes a plane struct as a parameter, and the plane struct takes a normal and distance from origin in the constructor, but my planes have a position and normal instead of just distance from origin, so I can't convert them. 我发现ray类有一个方法intersects(),它以一个平面结构作为参数,并且平面结构在构造函数中从原点获取法线和距离,但是我的平面有一个位置和法线而不是距原点的距离,所以我无法转换它们。 How can I detect if my ray is intersecting my quad struct? 如何检测我的光线是否与我的四边形结构相交?

Edit: I realize that I can't use the plane struct, as it is not of finite size and does not include corners, as my quad does. 编辑:我意识到我不能使用平面结构,因为它不是有限的大小,并且不包括角,就像我的四边形那样。 I need to find a way now to detect if this ray is intersecting the quad I have created... 我现在需要找到一种方法来检测这条光线是否与我创建的四边形相交...

Thanks for reading, I realize this question is a bit lengthy, and thanks in advance. 感谢阅读,我意识到这个问题有点冗长,并提前感谢。

I'm not sure exactly what they mean by "distance along the normal from the origin", but I would assume it just mean the distance from the origin. 我不确定它们的意思是“从原点到法线的距离”,但我认为它只是指距离原点的距离。 You can get that from the length property on a Vector3 . 您可以从Vector3上的length属性获取。

If that doesn't work, there is also a constructor for plane which takes three points on the plane: 如果这不起作用,还有一个平面构造函数,它在飞机上占据三个点:

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

You can use this with any 3 points on the plane, such as the corners of your quad, to create a plane. 您可以将此与平面上的任意3个点(例如四边形的角点)一起使用以创建平面。

Since you are using cubes, you can use the Ray.Intersects(Plane) method. 由于您使用的是立方体,因此可以使用Ray.Intersects(Plane)方法。 You just need a few more planes. 你只需要几架飞机。

Once you determine the first intersection point, then you can construct more planes for each perpendicular face of your cube. 确定第一个交叉点后,可以为立方体的每个垂直面构建更多平面。 Then you can use the Plane.Distance(Vector3) (I'm pretty sure this or something like it exists) to make sure your point is between each pair of perpendicular planes. 然后你可以使用Plane.Distance(Vector3) (我很确定这个或类似的东西存在)来确保你的点在每对垂直平面之间。 If it is not between them, then you can ignore the intersection. 如果它们不在它们之间,则可以忽略该交集。

Not exactly a straight answer to your question, but perhaps you find this relevant. 不完全是你的问题的直接答案,但也许你发现这相关。

Have you considered constructing a BoundingBox object and use the Intersects(Ray)? 您是否考虑过构造BoundingBox对象并使用Intersects(Ray)? http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.boundingbox.intersects.aspx http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.boundingbox.intersects.aspx

Edit 1: It's how I usually do it. 编辑1:这就是我通常的做法。 Depending on your data structure, it might also be easier to optimize (if you construct larger bounding boxes to bore into for example). 根据您的数据结构,它可能也更容易优化(例如,如果您构建更大的边界框以进行钻孔)。

Edit 2: As per Niko's suggestion: I don't want to post the relevant code (because it's a couple of pages long in total to make the context make sense) from the samples, but I can point you to the parts that you'll be interested in. 编辑2:根据Niko的建议:我不想发布相关代码(因为它总共需要几页才能使上下文有意义),但是我可以指出你的那些部分。我会感兴趣的。

  1. Download the sample from http://xbox.create.msdn.com/en-US/education/catalog/sample/picking_triangle http://xbox.create.msdn.com/en-US/education/catalog/sample/picking_triangle下载示例
  2. The bottom of the Cursor.cs file contains what you already know, calculating the Ray Cursor.cs文件的底部包含您已经知道的,计算Ray
  3. Go to the Game.cs file. 转到Game.cs文件。 There you'll find UpdatePicking() which calls RayIntersectsModel(...) which calls RayIntersectsTriangle(...) 在那里你会发现UpdatePicking()调用RayIntersectsModel(...)调用RayIntersectsTriangle(...)

The transform of the Ray is this part: Ray的变换就是这个部分:

Matrix inverseTransform = Matrix.Invert( modelTransform );

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

How deep you want to go (how accurate your picking) is up to your needs of course, but there you have it. 你想要去多深(你的选择的准确程度)当然符合你的需要,但是你有它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM