尝试绘制模型时黑屏[阅读编辑]

时间:2019-01-23 04:38:31

标签: c# monogame

我正在尝试制作一个可以使用相机的世界对象,并一次绘制多个模型,每个模型都有自己的位置(以及将来的旋转方式等)。除了黑屏,我也不知道为什么。

我尝试过更改矩阵的创建方式,调整位置,但是没有做任何事情。

世界:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Xna.Framework;

using Simple3DWorld.Objects;

namespace Simple3DWorld
{
    public class World
    {
        public Camera Camera;
        public ModelObject[] Objects;

        public World()
        {
            Camera = new Camera(new Vector3(0, 0, 1), Vector3.Zero);
            Objects = new ModelObject[100];
            AddObject(new Landscape(new Vector3(0, 0, -1)));
        }

        public void AddObject(ModelObject obj)
        {
            bool added = false;

            for (int i = 0; i < Objects.Length && !added; i++)
            {
                if (Objects[i] == null)
                {
                    Objects[i] = obj;
                    added = true;
                }
            }
        }

        public void Update(GameTime gt)
        {
            for (int i = 0; i < Objects.Length; i++)
            {
                if (Objects[i] != null)
                {
                    Objects[i].Update(gt);
                }
            }
        }

        public void Draw()
        {
            for (int i = 0; i < Objects.Length; i++)
            {
                if (Objects[i] != null)
                {
                    Objects[i].Draw(Camera);
                }
            }
        }
    }
}

相机:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Simple3DWorld
{
    public class Camera
    {
        public Vector3 Position;
        public Vector3 LookingAt;
        public float FieldOfView;
        public float AspectRatio;

        public Camera(Vector3 pos, Vector3 lookAt)
        {
            Position = pos;
            LookingAt = lookAt;
            FieldOfView = MathHelper.PiOver4;
            AspectRatio = STDW.Width / STDW.Height;
        }
    }
}

ModelObject:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Simple3DWorld
{
    public class ModelObject
    {
        public Model Model;
        public Vector3 Position;

        public ModelObject(Model model, Vector3 pos)
        {
            Model = model;
            Position = pos;
        }

        public virtual void Update(GameTime gt)
        {

        }

        public virtual void Draw(Camera camera)
        {
            foreach (ModelMesh mesh in Model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;
                    effect.World = Matrix.CreateTranslation(Position);
                    effect.View = Matrix.CreateLookAt(camera.Position, camera.LookingAt, Vector3.UnitZ);
                    effect.Projection = Matrix.CreatePerspectiveFieldOfView(camera.FieldOfView, camera.AspectRatio, 1f, 100f);
                }

                mesh.Draw();
            }
        }
    }
}

是的,我确保所有方法都被正确调用。屏幕上应该显示的是我的风景模型。

编辑:已解决。出于某些愚蠢而令人沮丧的原因,如果摄像机的X和Y(不是向上向量)均为0,MonoGame将不会渲染您的模型。如果有人能以某种方式解释这一点,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

相机的PositionLookAt向量在垂直于Up向量的两个轴上不能相等。这将导致NaN(不是数字)。

这种情况也可以描述为Gimbol Lock,因为围绕X(Roll)Y(Pitch)轴的旋转是对齐的,因此无法从CreateLookAt中确定Z(Yaw)。提供的信息。

在下面的行中创建View矩阵时出现问题:

effect.View = Matrix.CreateLookAt(camera.Position, camera.LookingAt, Vector3.UnitZ);

替换参数值:

effect.View = Matrix.CreateLookAt(new Vector3(0,0,1), new Vector3(0,0,0), new Vector3(0,0,1));

在实施时为here带注释的部分源(通过传递请参见IEEE 754

 public static void CreateLookAt(ref Vector3 cameraPosition, ref Vector3 cameraTarget, ref Vector3 cameraUpVector, out Matrix result)
 {
    var vector = Vector3.Normalize(cameraPosition - cameraTarget);

Normalize((0,0,1) - (0,0,0))-> (x,y,z)/Length

Length = (0 - 0)² + (0 - 0)² + (0 - 1)²-> 1

(0/Length,0/Length,1/Length)-> (0/1,0/1,1/1)-> (0,0,1) *确定

    var vector2 = Vector3.Normalize(Vector3.Cross(cameraUpVector, vector));

由内而外:

Cross((0,0,1),(0,0,1))-> (y1 * z2 - z1 * y2, z1 * x2 - x1 *z2, x1 * y2 - y1 *x2)->

(0 * 1 - 1 * 0, 1 * 0 - 0 * 1, 0 * 0 - 0 * 0)-> (0,0,0) *在数学上还可以,在几何上未定义(未定义垂直于输入点的平面)

Normalize(Cross((0,0,1),(0,0,1)))-> Normalize(0,0,0)

Length = (0 - 0)² + (0 - 0)² + (0 - 0)² -> 0

(0/Length,0/Length,0/Length)-> (0/0,0/0,0/0)-> (NaN,NaN,NaN) * UH-OH

NaN由零除,而org.wildfly.security.auth.server.SecurityIdentity定义的0为无符号。

由于对NaN的任何操作都会导致NaNNaN传播到WorldProjection矩阵,导致黑屏。

换句话说:

如果您站着看(Camera.Position = (0,0,6),而忽略了您的头必须倾斜才能看到它们的事实(Camera.LookAt = (0,0,0) ),是否可以确定您面对的罗盘方向(Up矢量等于Vector3.UnitZ)?不能。您不可能面对飞机上的任何方向。

如果我要求世界坐标在你脚前一个单位(1,0,0),我可以说出你所面对的方向。

答案 1 :(得分:0)

已修复。我要做的就是将相机移开0,0,0。 0,1,0 1,0,0和1,1,0似乎都可以工作,这意味着相机的其他两个坐标(而不是确定它是向上还是向下的坐标)不能位于原点。不太确定为什么会这样,但至少现在已解决。