C# 如何计算xna中目标光标的位置和方向?
我开发了一个像“minecraft”这样的小游戏。我花了几天时间计算光标的方向。 让我解释一下。 我想把一个立方体用光标放在屏幕中间,然后点击它消失。但我不知道如何恢复这些信息。。 有人能给我指一个“示例/教程”或解释吗? 多谢各位 我的截图游戏:C# 如何计算xna中目标光标的位置和方向?,c#,xna,cursor,position,game-engine,C#,Xna,Cursor,Position,Game Engine,我开发了一个像“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;
}