Черный экран при попытке нарисовать модель [прочитать, отредактировать] - PullRequest
0 голосов
/ 23 января 2019

Я пытаюсь создать объект мира, который может использовать камеру и рисовать сразу несколько моделей, каждая из которых имеет свою позицию (и вращение и т. Д. В будущем). За исключением того, что у него черный экран, и я не знаю почему.

Я пытался изменить способ создания матриц, скорректировал позиции и ничего.

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

Камера:

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

И да, я убедился, что все методы вызываются правильно. На экране должна появиться моя модель ландшафта.

РЕДАКТИРОВАТЬ: Решено. По какой-то глупой и разочаровывающей причине MonoGame не будет отображать ваши модели, если X и Y вашей камеры (а не вектор вверх) оба равны 0. Если кто-то может как-то объяснить это, я был бы бесконечно благодарен.

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Векторы Position и LookAt вашей камеры не могут быть одинаковыми по двум осям, перпендикулярным вектору Up. В результате получается NaN (не число).

Эту ситуацию также можно охарактеризовать как Gimbol Lock , поскольку повороты вокруг осей X(Roll) и Y(Pitch) выровнены, что делает невозможным определение 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));

Аннотированный частичный источник для 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

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

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

    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 Результат деления на ноль с нулем без знака, как определено IEEE 754 .

Поскольку любая операция с NaN приводит к NaN. NaN распространяется на матрицы World и Projection, что приводит к черному экрану.

Другими словами:

Если вы стоите, глядя (Camera.Position = (0,0,6)), игнорируя тот факт, что ваша голова должна наклониться, чтобы увидеть их, у ваших ног (Camera.LookAt = (0,0,0)), возможно ли определить направление компаса, где вектор Up равен Vector3.UnitZ, с которым вы столкнулись? Нет, это невозможно, вы можете быть лицом к плоскости в любом направлении.

Если я прошу координаты Мира на одну единицу перед вашими ногами (1,0,0), я могу сказать, в каком направлении вы находитесь.

0 голосов
/ 24 января 2019

Fixed.Все, что мне нужно было сделать, это переместить мою камеру с 0,0,0.0,1,0 1,0,0 и 1,1,0 все, казалось, работало, что означает, что две другие координаты камеры (не та, которая определяет, будет ли она вверх или вниз) не могут быть в начале координат.Не совсем уверен, почему это так, но, по крайней мере, сейчас это исправлено.

...