使用哪种投影和相机来制作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。
所以,主要问题是:我是否应该使用位移相机,或者是否有更好的方法有效地混合2D和3D(也许是广告牌)?但我不想给这个项目增加不必要的复杂性)?而且,如果我使用位移,我应该把3D物体和2D物体一起位移吗?最后,应该使用什么样的投影?

更新:如果我将摄像机移回z位置100,并使球体缩放100%,它们的行为就会正常一些——当摄像机向左移动时,它们向右移动,向上移动,向下移动,等等,就像你期望的透视投影一样。然而,相对于其他2D对象,它们移动得太多了。这是规模的问题吗?我觉得很难协调精灵的显示方式和3D对象在屏幕上的显示方式…

使用哪种投影和相机来制作3D/2D自上而下的视图

听起来就像你正在寻找的是Unproject -这将采取一个2D点并将其"投射"到3D空间。如果你的所有对象都在3D空间中,你的典型Ortho/LookAt相机应该像你期望的那样工作……这里我也完全凭记忆,因为我懒得去查。div;)

只是一个想法,但是你的视图矩阵中的Z被限制在1和0之间。更新那些Vector3的Z分量为相机的实际Z,看看这对你有什么作用。

& lt; 2美分/>