什么样的投影和相机用于3D / 2D自上而下视图?

时间:2011-08-03 19:41:51

标签: c# xna xna-4.0

一旦答案变得清晰,我可能会打扮自己,但我恐怕无法弄清楚如何处理我的相机以有效地混合滚动的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 Position是摄像机视口的绝对中心,而不是左上角或类似的东西。我也尝试过使用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);
    }

我的主要困惑在于我是否应该移动3D对象以及2D。我已经尝试过这样做,但是如果不这样做,实际上可以在屏幕上瞥见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的Scale变量乘以1000,也不会改变位置或比例。

所以,主要问题是:我是否应该使用置换相机,或者是否有更好的方法来有效地混合2D和3D(也许是广告牌?但我不想为这个项目增加不必要的复杂性)?并且,如果我使用位移,我应该替换3D对象以及2D吗?最后,应该使用什么样的投影?

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

2 个答案:

答案 0 :(得分:0)

听起来就像你正在寻找的是Unproject - 这将采用2D点并将其“投射”到3D空间中。如果你的所有物体都在3D空间中,那么典型的Ortho / LookAt相机应该可以正常工作......我也完全从记忆中走出来,因为我无法查看它。 ;)

答案 1 :(得分:0)

只是一个想法,但你的视图矩阵中的Z被约束在1和0之间。将这些Vector3的Z分量更新为相机的实际Z,看看它为你做了什么。

< 2美分/>