使用哪种投影和相机来制作3D/2D自上而下的视图
本文关键字:3D 2D 自上而下 视图 投影 相机 | 更新日期: 2023-09-27 18:04:30
一旦答案变得清晰,我可能会打自己的脸,但我担心我不知道如何使用我的相机来有效地混合滚动的2D和3D对象。
目前我正在使用位移相机,这是我在这仍然只是一个2D项目时实现的。摄像机根据物体在世界中的位置来置换所有2D物体的绘制位置。如果不是很清楚,下面是代码:
public void DrawSprite(Sprite sprite)
{
Vector2 drawtopLeftPosition = ApplyTransformation(sprite.Position);
//TODO: add culling logic here
sprite.Draw(spriteBatch, drawtopLeftPosition);
}
private Vector2 ApplyTransformation(Vector2 spritetopLeftPosition)
{
return (spritetopLeftPosition - topLeftPosition);
}
很简单。在我尝试将3D元素引入游戏之前,这种方法一直有效。我有几个球体,我想在2D游戏对象旁边显示。我已经弄清楚了如何正确地对所有东西进行z轴排序,但我无法让球体正确地投影。它们的出现和消失取决于相机的位置,并且经常不规律地飞来飞去,即使是最轻微的相机运动。以下是我的相机矩阵:
viewMatrix = Matrix.CreateLookAt(new Vector3(Position, 1f), new Vector3(Position , 0), Vector3.Up);
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, graphics.Viewport.AspectRatio, 1f, 1000f);
注意,Vector2位置是相机视口的绝对中心,而不是左上角或类似的地方。我也尝试过使用OrthographicOffCenter和Orthographic投影。viewMatrix基于当前摄像机位置使用相同的CreateLookAt函数更新每一帧。下面是绘制3D对象的Camera方法:
public void DrawModel(Sprite3D sprite, GraphicsDevice device)
{
device.BlendState = BlendState.Opaque;
device.DepthStencilState = DepthStencilState.Default;
device.SamplerStates[0] = SamplerState.LinearWrap;
sprite.DrawBasic(this, device);
}
我的主要困惑是我是否应该像替换2D对象一样替换3D对象。我试过这样做,但如果我不这样做,实际上在屏幕上瞥见3D物体会更成功。
这是Sprite3D绘图部分:
public Matrix GenerateWorld()
{
return Matrix.CreateScale(Scale) * Matrix.CreateTranslation(new Vector3(Position, -ZPosition)) * Matrix.CreateFromYawPitchRoll(Rotation3D.X, Rotation3D.Y, Rotation3D.Z);
}
private Matrix GenerateDEBUGWorld()
{
return Matrix.CreateScale(Scale) * Matrix.CreateTranslation(Vector3.Zero);
}
public void DrawBasic(Camera camera, GraphicsDevice device)
{
Matrix[] transforms = new Matrix[Model.Bones.Count];
Model.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in Model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = (transforms[mesh.ParentBone.Index] * GenerateDEBUGWorld());
effect.View = camera.ViewMatrix;
effect.Projection = camera.ProjectionMatrix;
}
mesh.Draw();
}
}
GenerateDEBUGWorld简单地将球体放置在0,0,这样我总是知道它应该在哪里。
我注意到的一些事情:
- 如果我将相机的Z位置设置为较大的数字(例如,10),球体的移动不那么不规律,但仍然错误
- 使用OrthographicOffCenter投影在屏幕中心显示微小的球体,它们不会改变位置或比例,即使我将Sprite3D的缩放变量乘以1000。
更新:如果我将摄像机移回z位置100,并使球体缩放100%,它们的行为就会正常一些——当摄像机向左移动时,它们向右移动,向上移动,向下移动,等等,就像你期望的透视投影一样。然而,相对于其他2D对象,它们移动得太多了。这是规模的问题吗?我觉得很难协调精灵的显示方式和3D对象在屏幕上的显示方式…
它听起来就像你正在寻找的是Unproject -这将采取一个2D点并将其"投射"到3D空间。如果你的所有对象都在3D空间中,你的典型Ortho/LookAt相机应该像你期望的那样工作……这里我也完全凭记忆,因为我懒得去查。div;)
只是一个想法,但是你的视图矩阵中的Z被限制在1和0之间。更新那些Vector3的Z分量为相机的实际Z,看看这对你有什么作用。
& lt; 2美分/>