понедельник, 30 мая 2011 г.

XNA 4.0 и 3ds Max Design 2011

Достаточно часто  у начинающих гейм девелоперов возникают трудности с выбором формата 3D моделей и последующей их загрузкой в свою игру. В XNA  4.0  существует 2 стандартных импортера 3D моделей. Это модели в формате x и fbx. В контексте использования XNA между этими форматами нет никакой разницы, так как XNA импортер все равно преобразует эти модели в свой внутренний формат xnb. Я лично предпочитаю использовать fbx формат, так как экспортер этого формата уже встроен в такие редакторы как 3D Studio Max и Blender. При необходимости можно отдельно скачать конвертор fbx с оф сайта.

И так рассмотрим процесс создание 3D модели в 3ds Max Design 2011.
Для простоты примера будем рисовать простую модель дома.
Открываем наш Max и рисуем куб со следующими параметрами:

Далее необходимо нарисовать окна и дверь. Для этого располагаем еще несколько боксов на месте наших окон и дверей. В результате должно получиться, что то вроде этого:

Переведем наш бокс в режим редактирования мешей и смещаем верхние 8 вертиксов вверх.

Далее делаем крышу и сужаем 4 верхних вертикса:

Применим к нашему боксу модификатор Boolean и с помощью этого модификатора выдавим поочередно наши окна и дверь.

Вот результат:

Далее наложим текстуру на наш домик. Накладывать текстуру мы будем при помощи модификатора Unwrap UVW. При помощи данного модификатора выделяем стены нашего дома
и жмахаем на кнопку Edit.

Как вы, наверное, уже догадались то весь наш домик развернулся на плоскости в окне Edit UVWs. Все части нашего домика обязательно должны поместиться в черный квадрат(окна Edit UVWs). После нажатия кнопки Flatten mapping выделенные части автоматически про масштабируются и поместятся в этот самый черный квадрат (масштаб в окне Edit меняется колесом мышки.). Подобные операции необходимо проделать и с остальными частями домика. В результате должно получиться, что то вроде этого:

Далее отрендерим нашу текстуру. Жмахаем на кнопку Render UV Template и сохраняем картинку. Которая нам будет служить заготовкой нашей текстуры.

В любом графическом редакторе нарисуем нашу текстуру. У меня получилась вот такая текстура.

Следующим шагом будет наложение текстуры на модель. Открываем в максе Material Editor(кнопка M) и делаем как на скриншотах ниже.

Выбираем созданную текстуру и нажимаем кнопку OK.
Далее выделяем наш домик и нажимаем в редакторе материалов на кнопку Assign Material to Selection.

Для просмотра реального результата можно отрендерить картинку нажав на кнопку с изображением чайника на панели инструментов 3DS. Напоследок нужно сконвертировать нашу созданную модель в меши. (Левая кнопка и Convert to ->editible Mesh).
Для полной ясности разъясняю:
Vertex (Вертекс) это точка.
Edge это грань.
Mesh это треугольник.
Если же модель в максе находиться в режиме редактирования Poly то модель экспортировать в формат fbx не удасться. Нужно перевести в Editible  Mesh. Все материалы наложенные на нашу модель должны быть стандартными.
И наконец, экспортируем модель в формат fbx.(File -> Export).
С максом все, теперь осталось загрузить нашу модель в проект XNA.

Открываем студию и создаем проект XNA 4.0.  Cразу первым делом добавляем нашу модель и текстуру в проект в раздел для контента. Для отрисовки нашей модели нам понадобиться обьявить 4 матрицы и класс модели в главном классе нашей игры.
Model _home;
Matrix _world;
Matrix _view;
Matrix _proj;
Matrix _gameWorldRotation;
В методе Initialize() проинициализируем наши матрицы.
_world = Matrix.Identity;
Заполняем мировую матрицу _world по главной диагоняли еденицами. Эта матрица необходима нам для хранения положения обьекта в пространстве. Эта матрица размерностью 4 на 4 то есть получается 16 переменных типа float. Из них 9 задают ориентацию объекта в пространстве, а ещё 3 - его позицию. Оставшиеся четыре всегда неизменны и нужны для корректного выполнения операции умножения. Внутри она выглядит так:

Rotx1 Roty1 Rotz1 0
Rotx2 Roty2 Rotz2 0
Rotx3 Roty3 Rotz3 0
PosX PosY PosZ 1
Где PosX, PosY, PosZ - позицию объекта, а Rotx1, Roty1, Rotz1 - вектор-направление оси X объекта, Rotx2, Roty2, Rotz2 - вектор-направление оси Y объекта, Rotx3, Roty3, Rotz3 - вектор-направление оси Z объекта.

Далее инициализируем видовую матрицу.Матрица вида хранит местоположение и ориентацию камеры в мире.

_view = Matrix.CreateLookAt(new Vector3(0, 700, 500), Vector3.Zero, Vector3.Up);

Матрица проекции нужна нам для того чтобы получить проекции всех 3D обьектов на нашем экране. Вообщем для рисования 2D графики.

_proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), GraphicsDevice.Viewport.AspectRatio, 1.0f, 1000);

С инициализацией все. Теперь прогрузим нашу модель при помощи контент менеджера.
_home = Content.Load<Model>(@"Home");

Осталось теперь отрисовать нашу модель на экране.
Делать мы это будем при помощи отдельного метода.

private void DrawModel(Model model, Matrix world, Matrix view, Matrix proj)
{
//локальная мировая матрица
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
 effect.EnableDefaultLighting();
 effect.View = view;
 effect.World = world * transforms[mesh.ParentBone.Index];
 effect.Projection = proj;
}
mesh.Draw();
 }
}
Для вращения обьекта на сцене в методе Update будем обновлять матрицу _gameWorldRotation следующим образом
_gameWorldRotation = Matrix.CreateRotationZ(MathHelper.ToRadians((float)gameTime.ElapsedGameTime.TotalMilliseconds / 100));
В метод Update вкачестве входного параметра приходит обьект gameTime. Этот обьект содержит свойство ElapsedGameTime. Т.е время с последнего вызова метода Update.
И наконец осталось только прорисовать нашу модель в методе Draw.
//Вращаем вокруг оси Z (локальных координат) нашу модель
_world = _world * _gameWorldRotation;
//Рисуем модель
DrawModel(_home, _world, _view, _proj);

Полный проект и модель можно скачать по ссылке 

2 комментария:

  1. Видела подобные домики в демонстрации Вашей игры.
    У Вас аккуратные код и комментарии!
    Сама мало работала с 3ds Max, у Вас понятные описания и Вы умело применяете метод вычитания объектов!

    ОтветитьУдалить
  2. Большое спасибо за изложенный урок. Теперь я понял, как связывать 3d max и язык программирования с помощью хорошего примера.

    ОтветитьУдалить