вторник, 6 марта 2012 г.

Практическое применение XNA. Часть 7.

Рисуем первую модель.

Перед тем, как мы нарисуем нашу первую модель, давайте разберемся, что же такое трёхмерное пространство, и каким образом организовано отображение моделей в нем. Первое с чего мы начнем, это система трехмерных координат. Важно отметить, что в XNA используется правосторонняя система координат, в DirectX левосторонняя, и это следует помнить. Вся разница между ними в том, что если ось X (ширина, начинается в нижнем левом углу экрана монитора и направлена вправо) и ось Y (высота, начинается в нижнем левом углу экрана монитора и направлена вверх), и в левосторонней и правосторонней системах одинаковы, то с осью Z дела обстоят диаметрально противоположно. В правосторонней системе ось Z своим положительным лучом направлена к вам , как бы выходя из экрана монитора.
В левосторонней системе ось Z положительным лучом наоборот уходит вдаль от вас вглубь монитора. Если представить, что камера находится в начале системы координат, то - есть X=0, Y=0, Z=0, а модель которую предстоит отобразить в координатах X=0, Y=0, Z=5 , то в правосторонней системе координат мы ее не увидим, так как фактически она должна будет находиться в воздухе между монитором и вами. Если же координаты модели будут X=0, Y=0, Z=-5, то ее местоположение переместится вглубь монитора, и наша видеокарта сможет ее отобразить. Однако важно понимать, что если камеру переместить в отрицательную часть системы координат по оси Z, и развернуть на 180 градусов, например для того чтобы посмотреть на объект с обратной стороны, то теперь чтобы отдалить объект нам надо его двигать в положительном направлении по оси Z.
С пространством, в котором нам предстоит отображать нашу игру, вроде бы всё понятно. Теперь движемся дальше. Как уже было сказано, игра и ее игровой мир состоит из примитивов и моделей. Давайте рассмотрим примитив как простейшую форму модели. и пойдем мы от сложного к простому. Любой примитив состоит из полигонов, а любой полигон из вершин и линий соединяющих эти вершины. Итак, у нас появились новые понятия, суть которых такова:
 Вершина – это точка в трехмерном пространстве имеющая координаты X,Y,Z.
Полигон – это совокупность трех вершин соединенных между собой линиями и образующих треугольник, вершины которого теперь имеют не только координаты, но еще и индекс, так называемый порядковый номер вершины.
Все модели и примитивы состоят из полигонов (треугольников). Модели сложной формы могут включать в себя сотни тысяч полигонов и называются они, на языке создателей игр, высокополигональными моделями (highpoly) , и наоборот, модели, состоящие из нескольких десятков полигонов, которые называются низкополигональными (lowpoly). Чем больше полигонов в модели, тем правильней и точней будет ее форма, округлые части станут менее угловатые и более округлые. Однако высокополигональная модель требует больше компьютерных ресурсов для обработки, поэтому здесь также необходим компромисс между качеством и производительностью.
Для того чтобы вывести на экран нашу модель, создадим новый проект SimplyModel. В папку Content мы добавляем папку models, а в неё модель под названием BTR.x. Следующий код показывает реализацию.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace SimplyModel
{
  public class Game1 : Microsoft.Xna.Framework.Game
  {
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Model myModel;
    Matrix world;
    Matrix view;
    Matrix proj;
    float rotation;
    public Game1()
    {
      graphics = new GraphicsDeviceManager(this);
      Content.RootDirectory = "Content";
    }
    protected override void Initialize()
    {
      base.Initialize();
    }
    protected override void LoadContent()
    {
      spriteBatch = new SpriteBatch(GraphicsDevice);
      myModel = Content.Load<Model>("models/BTR");
    }
    protected override void UnloadContent()
    {
    }
    protected override void Update(GameTime gameTime)
    {
      rotation += MathHelper.ToRadians(1);
      base.Update(gameTime);
    }
    protected override void Draw(GameTime gameTime)
    {
      GraphicsDevice.Clear(Color.CornflowerBlue);
      world = Matrix.CreateRotationY(rotation) * Matrix.CreateTranslation(0, 0, 5);
      view = Matrix.CreateLookAt(new Vector3(0, 0, -1f), Vector3.Zero, Vector3.Up);
      proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(90),
                                                (float)graphics.GraphicsDevice.Viewport.Width /
                                                (float)graphics.GraphicsDevice.Viewport.Height, 1, 1000);
      foreach (ModelMesh mesh in myModel.Meshes)
      {
        foreach (BasicEffect effect in mesh.Effects)
        {
          effect.World = world;
          effect.View = view;
          effect.Projection = proj;
        }
        mesh.Draw();
      }
      base.Draw(gameTime);
    }
  }
}
В этом примере, тоже все достаточно просто. Аналогично предыдущим урокам, мы загружаем
модель из предварительно созданного файла. Далее проходим по всем сеткам модели, их может быть несколько, и вызываем у каждой из них метод Draw(), который и изобразит ее на экране.
Для рисования модели нам так-же потребуются три матрицы.
  Мировая матрица – позволяет производить такие преобразования объекта как масштабирование, перемещение, вращение, различные трансформации сетки на вершинном уровне. Этой матрицей наделяется каждый объект, это локальная система координат каждой модели. Новая локальная система координат значительно упрощает аффинные преобразования объекта в пространстве. Например, чтобы перенести объект с левого верхнего угла дисплея в нижний правый угол дисплея, необходимо просто перенести его локальную точку отсчета, системы координат на новое место. А представьте, если бы не было мировой матрицы и этот объект пришлось переносить по одной вершине из угла в угол монитора... Поэтому любой объект, а точнее все вершины этого объекта проходят через мировую матрицу преобразования.
Матрица вида – определяет местоположение камеры в игровом пространстве. Это вторая по счету матрица, на которую умножаются все вершины моделей. С ее помощью задается направление просмотра 3D объекта или сцены.
Матрица проекции – это наиболее сложная из трех матриц, которая создает проекцию нашего трехмерного игрового мира, на плоскую двухмерную поверхность нашего монитора. С помощью этой матрицы задаются передняя и задняя плоскости отсечения пространства, чтобы снизить нагрузку на видеопроцессор. Чтобы лучше понять выше сказанное, представьте себе, будто вы стоите перед аквариумом прямоугольной формы и смотрите на плавающих внутри него рыб. Стеклянная стенка аквариума, которая ближе к вам – это передняя плоскость отсечения, стенка, которая дальше от вас – это дальняя плоскость. Все что находится к нам ближе, чем ближняя плоскость нас не интересует, равно как и все, что находится за дальней плоскостью отсечения. Наше внимание, как и внимание видеопроцессора, привлекает только содержимое аквариума, а именно все что находится между ближней и дальней плоскостями отсечения. Соответственно увеличивая или уменьшая этот диапазон, мы регулируем нагрузку видеокарты.
А вот и наша моделька.
Как вы снова могли заметить, вся основная работа выполнена внутри классов XNA, мы лишь указали какую модель загрузить, и как ее нарисовать.

Комментариев нет:

Отправить комментарий

Physically Based Rendering