简体   繁体   English

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

[英]Black screen when trying to draw model [read edit]

I'm trying to make a world object that can use a camera and draw multiple models at once, each with their own position (and rotation, etc. in the future). 我正在尝试制作一个可以使用相机的世界对象,并一次绘制多个模型,每个模型都有自己的位置(以及将来的旋转方式等)。 Except it comes up with a black screen and I don't know why. 除了它带有黑屏,我不知道为什么。

I've tried changing the way the matrices are created, adjusted the positions, and nothing. 我尝试过更改矩阵的创建方式,调整位置,但没有任何改变。

World: 世界:

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);
                }
            }
        }
    }
}

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: 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();
            }
        }
    }
}

And yes, I have made sure that all methods are being called correctly. 是的,我确保所有方法都可以正确调用。 What should be showing on screen is my landscape model. 屏幕上应该显示的是我的风景模型。

EDIT: Solved. 编辑:解决。 For some stupid, frustrating reason, MonoGame will not render your models if your camera's X and Y (not the up vector) are both 0. If anyone could somehow explain this, I would be infinitely grateful. 出于某些愚蠢而令人沮丧的原因,如果摄像机的X和Y(不是向上矢量)都为0,MonoGame将不会渲染您的模型。如果有人能以某种方式解释这一点,我将非常感激。

Your Camera's Position and LookAt vectors cannot both be equal on the two axes perpendicular to the Up vector. 相机的PositionLookAt向量在垂直于Up向量的两个轴上不能相等。 This results in a NaN(not a number). 结果为NaN(不是数字)。

This situation can also be characterized as a Gimbol Lock , since the rotations about the X(Roll) and Y(Pitch) axes are aligned, making it impossible to determine the Z(Yaw) from the information provided. 这种情况也可以称为Gimbol Lock ,因为绕X(Roll)Y(Pitch)轴的旋转是对齐的,因此无法从提供的信息中确定Z(Yaw)

The problem occurs in the creation of the View matrix in the following line: 在下面的行中创建View矩阵时会出现问题:

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

Substituting the argument values: 替换参数值:

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

Annotated partial source for CreateLookAt at implementation(see here for pass the through call) 在实现时带有CreateLookAt的带注释的部分源代码(有关通过调用的信息,请参见此处

 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 Normalize((0,0,1) - (0,0,0)) -> (x,y,z)/Length

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

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

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

Working inside out: 由内而外:

Cross((0,0,1),(0,0,1)) -> (y1 * z2 - z1 * y2, z1 * x2 - x1 *z2, x1 * y2 - y1 *x2) -> 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) *Mathematically OK, Geometrically undefined(does not define a plane perpendicular to the input points) (0 * 1 - 1 * 0, 1 * 0 - 0 * 1, 0 * 0 - 0 * 0) (0,0,0) * (0 * 1 - 1 * 0, 1 * 0 - 0 * 1, 0 * 0 - 0 * 0) (0,0,0) (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) 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 (0/Length,0/Length,0/Length) -> (0/0,0/0,0/0) -> (NaN,NaN,NaN) * UH-OH

The NaN results from the division by zero with the 0 being unsigned as defined by IEEE 754 . NaN由除以零得到,其中0表示IEEE 754定义的无符号。

Since any operation on a NaN results in NaN . 由于对NaN任何操作都会导致NaN The NaN propagates to the World and Projection matrices, resulting in a black screen. NaN传播到“ World和“ Projection矩阵,从而导致黑屏。

To put it another way: 换一种方式:

If you were standing up looking ( Camera.Position = (0,0,6) ), ignoring the fact your head has to tilt to see them, at your feet( Camera.LookAt = (0,0,0) ), is it possible to determine the compass direction, where the Up vector equals Vector3.UnitZ , that you are facing? 如果您站着看( Camera.Position = (0,0,6) ),则忽略了您的头部必须倾斜才能看到它们的事实( Camera.LookAt = (0,0,0) )是是否有可能确定罗盘方向,即Up矢量等于Vector3.UnitZ所面对的方向? No. It is not possible, you could be facing any direction on the plane. 不可以。您可能会面对飞机上的任何方向。

If I ask for the World coordinate one unit in front of your feet (1,0,0) , I can tell which direction you are facing. 如果我要求世界坐标在你脚前(1,0,0)前面一个单位,那么我可以说出您所面对的方向。

Fixed. 固定。 All I had to do was move my camera off of 0,0,0. 我要做的就是将相机移开0,0,0。 0,1,0 1,0,0 and 1,1,0 all seemed to work, which means the camera's other two coordinates (not the one that determines whether it's up or down) can't be at the origin. 0,1,0 1,0,0和1,1,0似乎都可以工作,这意味着相机的其他两个坐标(而不是确定它是向上还是向下的坐标)不能位于原点。 Not too sure why this is a thing, but at least it's fixed now. 不太确定为什么会这样,但至少现在已解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM