![]() |
|
![]() |
![]() |
Новости | Конференция | Чат | База данных | Творчество | Сообщество | О сайте | English |
![]() |
Помощь сайту |
![]() |
![]() |
![]() |
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Глава 3. Основа движка Для начала разберемся со структурой движка. Должны быть такие объекты: Геометрия (собственно, модели). Источники света. Спрайты. Системы частиц. Камеры. Внимание! Данная структура не претендует на суперсовременную, она рассчитана на простые игры. Но как это хранить в сцене? Нужен массив объектов.. Но создавать отдельно массив геометрии, отдельно источников света и т.д. не очень удобно. Поэтому мы сделаем по-другому. Для начала нужно создать базовый класс с общими свойствами для всех объектов. Общих свойств не слишком много. Это: Имя. Уникальный идентификатор (Например, «камера_1» или «станция_5») Трансформация (матрица/кватернионы, короче что пожелаете) Еще есть общие процедуры такие как: Render (рисование) Update (обновление, например, при движении корабля) Загрузка из файла Сохранение в файл Копирование информации из другого объекта в этот. Код: type JLSceneObj=class IdName:string; Trans:PJLTransformation; constructor Create; virtual; procedure Render; virtual; abstract; procedure Update; virtual; abstract; procedure LoadFromFile(var f:file); virtual; abstract; procedure SaveToFile(var f:file); virtual; abstract; procedure Assign(a:JLSceneObj); virtual; end; Теперь тип трансформации. Я использую матрицы, но мне легко будет переделать все на кватернионы, например. Код: type JLTransformation=class rotMat:TDotMatrix3x3; pos:TDotVector3; constructor Create; procedure LoadTransform; procedure DoTransform; end; PJLTransformation=^JLTransformation; constructor JLTransformation.Create; begin rotMat:=DOT_IDENTITY3; pos:=DOT_ORIGIN3; end; OpenGL лучше давать матрицу не в представлении 4х4, а 1х16. Для этого объявим новый тип type TDotMatrix16=array [0..15] of single; procedure JLTransformation.LoadTransform; var MatGL:TDotMatrix16; begin MatGL:=jlMatToMat16(rotMat); jlSetPosMat(pos,MatGL); glLoadMatrixf(@MatGL); end; Вот код jlSetPosMat (из математической библиотеки): procedure jlSetPosMat(Pos:TDotVector3; var Mat:TDotMatrix16); overload; begin mat[12]:=pos.x; mat[13]:=pos.y; mat[14]:=pos.z; end; procedure JLTransformation.DoTransform; var MatGL:TDotMatrix16; begin MatGL:=jlMatToMat16(rotMat); jlSetPosMat(pos,MatGL); glMultMatrixf(@MatGL); end; Функция jlMatToMat16 просто переводит матрицу 3х3 в матрицу 16. Вот её Код: function jlMatToMat16(const m:TDotMatrix3x3):TDotMatrix16; begin result[0] :=m[0,0]; result[1] :=m[0,1]; result[2] :=m[0,2]; result[3] :=0; result[4] :=m[1,0]; result[5] :=m[1,1]; result[6] :=m[1,2]; result[7] :=0; result[8] :=m[2,0]; result[9] :=m[2,1]; result[10]:=m[2,2]; result[11]:=0; result[12]:=0; result[13]:=0; result[14]:=0; result[15]:=1; end; Все просто. Теперь, как же хранить это все в Сцене? Ну для начала опишем какой-нибудь класс-потомок. Особо выбирать не пришлось. Все же лучше посмотреть на геометрию, чем на источник света, который ничего не освещает за отсутствием геометрии. Итак, что нужно для геометрии? Как я уже писал, она описывается Вершинами, Нормалями и Текстурными Координатами (на самом деле там может быть несколько текстурных координат, цвет и еще много всего, но это уже дополнительно, то что я назвал – основа, хотя в формате 3ds нет нормалей, за что я его и не люблю). Заведем класс JLGeometry описывающий геометрию в сцене. Здесь возникает сложность. Хранить информацию о вершинах напрямую в классе JLGeometry – это неправильно. Например, у нас есть 2 одинаковых корабля. Информацию о вершинах придется дублировать, а если кораблей 20? Или 100? Проблема решается, если создать класс-хранитель именно этой информации. Называться он будет Mesh. JLMesh=class IdName:string; Vertex:JLGeomData3; Normal:JLGeomData3; TexCoord:JLGeomData2; Indx:array of cardinal; Count:integer; constructor Create; destructor Destroy; override; procedure LoadFromFile(var f:file); procedure SaveToFile(var f:file); procedure Assign(geo:PJLMesh); end; Описывать каждую процедуру не и имеет особого смысла, т.к. они довольно просты. Здесь нет работы с OpenGL. У класса JLGeometry должны быть ссылки на материал и mesh. JLGeometry=class(JLSceneObj) MeshId,MatID:string; и т.д. Так как же хранить JLGeometry в сцене? Нужно создать JLObjArray класс-хранитель объектов типа JLSceneObj и его наследников. Самое интересное, что объявив тип JLSceneObj вы можете превратить его в любой класс-наследник. Например: Var a: JLSceneObj; A:=JLGeometry.Create; или A:=JLSprite.Create; и т.д. Вот, попробуйте написать класс JLObjArray сами, потом посмотрим у кого лучше вышло. Возможности у этого класса должны быть следующие: Добавить объект (а: JLSceneObj) Взять последний из списка:JLSceneObj; Найти по имени(nam:String):integer; вернуть номер Найти по имени(nam:String):JLSceneObj; вернуть сам объект Очистить список. function IsChanged:boolean; вот такая функция, говорящая изменился ли список со времен предыдущего вызова ЭТОЙ функции. (по желанию) Пока удаление из списка, загрузка из файла тоже по желанию. Учтите, в массиве не должно быть двух объектов с одинаковыми именами. Так же могут быть проблемы с разным написанием имени. ‘Camera1’ и ‘camera1’-не одно и то же! Этот класс добавляется в Сцену. Теперь чтоб нарисовать, например, прямоугольник требуется сделать следующее. Meshes: хранитель mesh; Objects: хранитель JLObjArray; procedure TDelphi3DForm.CreateScene; var Geome:JLGeometry; убираем begin Geome:=JLGeometry.Create; Scene.Objects.AddObj(Geome); Geome.Free; // все, удалили end; а вместо Geome.Render; пишем Scene.Render; Материалов пока нет, а вот с mesh`ами нужно поработать – сделать класс-хранитель объектов mesh. Этот класс будет похож на хранитель JLObjArray. Попробуйте реализовать сами.
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
![]() |
![]() |
![]() |
Дизайн Elite Games V5 beta.18 EGM Elite Games Manager v5.17 02.05.2010 |
![]() |