C# 如何计算xna中目标光标的位置和方向?

C# 如何计算xna中目标光标的位置和方向?,c#,xna,cursor,position,game-engine,C#,Xna,Cursor,Position,Game Engine,我开发了一个像“minecraft”这样的小游戏。我花了几天时间计算光标的方向。 让我解释一下。 我想把一个立方体用光标放在屏幕中间,然后点击它消失。但我不知道如何恢复这些信息。。 有人能给我指一个“示例/教程”或解释吗? 多谢各位 我的截图游戏: 当然,这在很大程度上取决于数据的组织方式。 但是如果你把多边形和网格存储在某个地方(我不是说顶点缓冲区!!),比如八叉树,你可以这样做: 从摄影机设置创建光线,并在场景中“发射”光线。通常,八叉树或类似结构可以扩展,以便轻松进行光线测试以返回命中元素

我开发了一个像“minecraft”这样的小游戏。我花了几天时间计算光标的方向。 让我解释一下。 我想把一个立方体用光标放在屏幕中间,然后点击它消失。但我不知道如何恢复这些信息。。 有人能给我指一个“示例/教程”或解释吗? 多谢各位

我的截图游戏:
当然,这在很大程度上取决于数据的组织方式。 但是如果你把多边形和网格存储在某个地方(我不是说顶点缓冲区!!),比如八叉树,你可以这样做:

从摄影机设置创建光线,并在场景中“发射”光线。通常,八叉树或类似结构可以扩展,以便轻松进行光线测试以返回命中元素。当然,您可以对所有四边形进行暴力迭代,但这很快就会成为性能瓶颈。 从那里你可以用你想要的任何结果


整个过程通常被称为“挑选”,这是一个非常好的教程。

当然,这在很大程度上取决于数据的组织方式。 但是如果你把多边形和网格存储在某个地方(我不是说顶点缓冲区!!),比如八叉树,你可以这样做:

从摄影机设置创建光线,并在场景中“发射”光线。通常,八叉树或类似结构可以扩展,以便轻松进行光线测试以返回命中元素。当然,您可以对所有四边形进行暴力迭代,但这很快就会成为性能瓶颈。 从那里你可以用你想要的任何结果


整个过程通常被称为“挑选”,这是一个非常好的教程。

我不认为这是我在3D XNA游戏中使用的,而且很有效。这些评论相当具有解释性。基本上,它会直接从光标位置投影一条光线,并检查它是否与任何地图对象的边界球相交(
Unit
s)

//
///创建将屏幕光标位置转换为屏幕位置的光线
/// 
/// 
/// 
/// 
公共光线计算矩阵(矩阵投影矩阵,矩阵视图矩阵)
{
//使用光标位置在屏幕空间中创建2个位置。0为
//尽可能靠近摄像机,1尽可能远。
Vector3 nearSource=新Vector3(鼠标位置,0f);
矢量3远源=新矢量3(鼠标位置,1f);
//使用Viewport.Unproject告诉您这两个屏幕空间的位置
//将在世界空间中。我们需要投影矩阵和视图
//矩阵,我们将其保存为成员变量。我们还需要一个世界
//矩阵,可以是恒等式。
Vector3 nearPoint=GraphicsDevice.Viewport.Unproject(近源、,
投影矩阵、视图矩阵、矩阵.恒等式);
Vector3 farPoint=GraphicsDevice.Viewport.Unproject(远源、,
投影矩阵、视图矩阵、矩阵.恒等式);
//找到从近点到远点的方向向量
//并使之正常化。。。。
矢量3方向=远点-近点;
方向。规范化();
//然后使用nearPoint作为源创建一条新光线。
返回新光线(近点、方向);
}
专用Vector3 cursorRayToCoords(光线、Vector3摄像机)
{
可空距离=光线相交(新平面(矢量3.0以上,0.0f));
如果(距离==null)
返回向量3.0;
其他的
{
返回cameraPos+光线方向*(浮动)距离;
}
}
公共覆盖无效更新(游戏时间游戏时间)
{
cursorRay=CalculateCursorRay(camera.Projection,camera.View);
cursorOnMapPos=cursorraytoords(cursorRay,cursorRay.Position);
检查输入(游戏时间);
更新(游戏时间);
}
/// 
///返回与光标最近的单位
/// 
///离光标最近的单位
私有单元getCursorUnit()
{
单位:it=null;
浮动?最近距离=零;
float?checkIntersect=null;
foreach(map.Units中的单位)//检查是否选择了单位
{
checkIntersect=cursorRay.Intersects(unit.BoundingSphere);
if(checkIntersect!=null)//如果检测到相交
{
if(nearestDistance==null)//找到第一个单元
{
闭合时间=单位;
最近距离=(浮动)选中相交;
}
否则如果((float)checkIntersect<(float)nearestDistance)//对于任何其他,只查找最近的
{
闭合时间=单位;
最近距离=(浮动)选中相交;
}
}
}
归还它;
}

我对大部分这一切都不感兴趣——这是我在3D XNA游戏中使用的东西,而且很管用。这些评论相当具有解释性。基本上,它会直接从光标位置投影一条光线,并检查它是否与任何地图对象的边界球相交(
Unit
s)

//
///创建将屏幕光标位置转换为屏幕位置的光线
/// 
/// 
/// 
/// 
公共光线计算矩阵(矩阵投影矩阵,矩阵视图矩阵)
{
//使用光标位置在屏幕空间中创建2个位置。0为
//尽可能靠近摄像机,1尽可能远。
Vector3 nearSource=新Vector3(鼠标位置,0f);
矢量3远源=新矢量3(鼠标位置,1f);
//使用Viewport.unprojecttotel
    /// <summary>
    /// Creates a Ray translating screen cursor position into screen position
    /// </summary>
    /// <param name="projectionMatrix"></param>
    /// <param name="viewMatrix"></param>
    /// <returns></returns>
    public Ray CalculateCursorRay(Matrix projectionMatrix, Matrix viewMatrix)
    {
        // create 2 positions in screenspace using the cursor position. 0 is as
        // close as possible to the camera, 1 is as far away as possible.
        Vector3 nearSource = new Vector3(mousePosition, 0f);
        Vector3 farSource = new Vector3(mousePosition, 1f);

        // use Viewport.Unproject to tell what those two screen space positions
        // would be in world space. we'll need the projection matrix and view
        // matrix, which we have saved as member variables. We also need a world
        // matrix, which can just be identity.
        Vector3 nearPoint = GraphicsDevice.Viewport.Unproject(nearSource,
            projectionMatrix, viewMatrix, Matrix.Identity);

        Vector3 farPoint = GraphicsDevice.Viewport.Unproject(farSource,
            projectionMatrix, viewMatrix, Matrix.Identity);

        // find the direction vector that goes from the nearPoint to the farPoint
        // and normalize it....
        Vector3 direction = farPoint - nearPoint;
        direction.Normalize();

        // and then create a new ray using nearPoint as the source.
        return new Ray(nearPoint, direction);
    }

    private Vector3 cursorRayToCoords(Ray ray, Vector3 cameraPos)
    {
        Nullable<float> distance = ray.Intersects(new Plane(Vector3.Up, 0.0f));
        if (distance == null)
            return Vector3.Zero;
        else
        {
            return cameraPos + ray.Direction * (float)distance;
        }
    }

    public override void Update(GameTime gameTime)
    {
        cursorRay = CalculateCursorRay(camera.Projection, camera.View);
        cursorOnMapPos = cursorRayToCoords(cursorRay, cursorRay.Position);
        checkInput(gameTime);

        base.Update(gameTime);
    }

    /// <summary>
    /// Returns the nearest unit to the cursor
    /// </summary>
    /// <returns>The unit nearest to the cursor</returns>
    private Unit getCursorUnit()
    {
        Unit closestUnit = null;
        float? nearestDistance = null;
        float? checkIntersect = null;

        foreach (Unit unit in map.Units)//checks to see if unit selection
        {
            checkIntersect = cursorRay.Intersects(unit.BoundingSphere);
            if (checkIntersect != null)//if intersection detected
            {
                if (nearestDistance == null) //first unit found
                {
                    closestUnit = unit;
                    nearestDistance = (float)checkIntersect;
                }
                else if ((float)checkIntersect < (float)nearestDistance)//for any others, only find the nearest
                {
                    closestUnit = unit;
                    nearestDistance = (float)checkIntersect;
                }
            }
        }

        return closestUnit;
    }