Создание 3D Engine. Часть 2.

12 Октября, 2012 Dunadan KSMПросмотров: 8037

В этой части рассмотрим еще один алгоритм формирования 3Д сцен, так же выложу исходники первых версий движка, 2 написаны под DirectX, 3-я под OpenGL, правда в этих проектах не будет множества эффектов, которые написаны для последней версии, нет в версиях столкновения со сценами, но они проще в разборе, т.к. нет того объема кода что в последней версии. 

3d_engine pics
Выше скриншот из предка окончательного движка, просто отображение сцен при помощи техники секторов и порталов, нет музыки, эффектов, столкновения с предметами и стенами, управление мышкой и курсором вверх.
Приступим к разбору алгоритма:
Алгоритм секторов и порталов

Для описания алгоритма введем некоторые понятия.
      Сектор - выпуклый объемный многоугольник, т.е. прямая проведенная через любые две диаметрально противоположные точки пересекает только граничные полигоны. 
3d_engine pics
Портал - полигон, который указывает на другой сектор. 
Портал является тем же полигоном, но не содержит текстуру и карт освещения, он используется как указатель на другой сектор.
Следует заметить, что если имеется сектора S1 и S2 и портал из сектора S1 указывает на сектор S2, то портал в секторе S2 должен указывать на S1.
Портал имеет свою матрицу преобразования, что позволяет добиться эффекта отражения. Использование портальной технологии позволяет динамически изменять нелинейную сцену (мир).
Например: в сцене состоящей из трех секторов S1, S2 и S3, портал в S1 указывает на S2, а портал в S2 указывает не на S1, а на S3, т.е. находясь в S1 можно видеть S2, а из сектора S2 будет виден сектор S3.
Порталы помогают решить проблему сортировки полигонов внутри секторов. Внутри сектора полигоны всегда видимы и их можно отрисовывать в любом порядке за исключением тех полигонов, которые находятся позади камеры обзора.
На рисунке  порталы обозначены «А», «В» и выделены жирной линией.
3d_engine pics
Схема работы алгоритма:
    1. Находим сектор в котором находится текущая камера.
    2. Преобразование сектора:
        - поворачиваем сектор относительно текущей камеры;
        - отбрасываем невидимые полигоны;
        - производим трехмерное отсечение по пирамиде всех полигонов сектора;
        - берем первый видимый полигон;
    3. Для текущего полигона:
        - если полигон является порталом, то рекурсивно вызываем шаг 2;
        - но с сектором, на который указывает портал;
        - берем из cache нужную текстуру;
        - отрисовываем данный полигон с коррекцией перспективы;
        - если следующий полигон существует, то текущий приравниваем;
        - следующему, переходим к шагу 3.
    4. Выбираем первый объект.
    5. Преобразование текущего объекта:
        - поворачиваем объект относительно текущей камеры;
        - отбрасываем невидимые полигоны;
        - отсекаем по пирамиде все полигоны;
        - рисуем все полигоны используя алгоритм "художника";
        - переходим к следующему непустому объекту.
Достоинства:
- очень быстрый алгоритм
- пригоден для создания динамических сцен
- легко представлять сцену
- алгоритм не содержит перерисовок
- легко реализовать спецэффекты (динамическое освещение, система соударений, зеркальные поверхности и т.д.)
Недостатки:
- не является общим алгоритмом
Структура представления информации 
Определение сцены (мира) 
          Сцена (мир) представлена набором секторов с содержащимися в них предметах и соединенных между собой порталами.
3d_engine pics
Все сектора и объекты составлены из трехмерных полигонов. Эти полигоны должны быть выпуклыми. Вершины каждого полигона должны быть ориентированы против часовой стрелки - данный факт используется для определения видимости полигона (полигон имеет только одну видимую сторону).
Каждый полигон растрируется с текстурой. Вид текстуры на полигоне задается следующими параметрами: угол поворота текстуры, коэффициенты масштабирования по осям t и s и смещение относительно каждой из осей.
Вся сцена представлена непрерывным динамически выделяемым массивом из структур описания полигонов (все полигоны одного сектора следуют последовательно друг за другом):

struct Map_Object

{

       int chrome;                //применяется или нет эффект хрома

       int n_tex_chrome;          //номер текстуры для хрома

       int f_blend_chrome;        //прозрачность

       float color_chrome[4];     //RGBA значения

       int Visible;               //видим или нет полигон

       int ntexture;              //номер текстуры для полигона

       float x1,x2,x3;            //координаты вершин полигона

       float y1,y2,y3;

       float z1,z2,z3;

       float t_x1,t_x2,t_x3;      //координаты текстуры (x-t,y-s)

       float t_y1,t_y2,t_y3;

       float nx1,nx2,nx3;         //нормали для вершин

       float ny1,ny2,ny3;

       float nz1,nz2,nz3;

};

Разбиение сцены на сектора хранится в динамически выделяемом массиве структур:

struct Portal{

       …

int polygon_begin;                       //номер 1-го полигона

int polygon_end;                         //номер последнего полигона

       int nsv;                          //кол-во порталов

       float *x1, *x2, *x3, *x4;         //описание портала

       float *y1, *y2, *y3, *y4;

       float *z1, *z2, *z3, *z4; 

       int *type;                        //тип портала

                    …

};

Структура хранения обектов сцены

В каждом секторе могут находиться различные обекты, которые могут содержать в себе анимацию. Обекты загружаются в программу из файлов формата 3DS, созданных в 3D StudioMax. Для хранения этих обектов была создана следующая структура:

struct G_Object

{

       …

       kfmesh3ds *obj;                   //ключи анимации

       int length_anim;                  //длина анимации

       float cur_key;                    //текущий ключ

       int num_obj;                      //кол-во подобъектов

       G_Object *Object;                        //подобъекты

       IA3dSource   *a3dsrc ;                   //хранится звук (A3D)

       char sound_name[250];             //имя звука

       float sound_length;               //дальность звучания

       int f_blend;                             //прозрачность есть/нет

       int type;                         //тип объекта

       int nVertex;                      //кол-во вершин

       float *Vertex;                    //вершины

       float *VColor;                    //цвет вершин

       int Visible;                      //видим или нет объект

       int nportal;                      //принадлежность сектору

       int texture;                      //номер текстуры

             …

};

Скачать исходные тексты первых трех версий.

twitter.com facebook.com vkontakte.ru odnoklassniki.ru mail.ru ya.ru rutvit.ru myspace.com technorati.com digg.com friendfeed.com pikabu.ru blogger.com liveinternet.ru livejournal.ru memori.ru google.com bobrdobr.ru mister-wong.ru yahoo.com yandex.ru del.icio.us

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

аноним

совет Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

комментатор / стать им

как?Укажите свой действующий email и пароль. При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные включая адрес сайта, ник, описание, контакты и т.д.

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

(обязательно)