Глава 10. Использование 3d моделей 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Глава 10. Использование 3d моделей



Форматы моделей

 

Есть много распространенных форматов, в которых хранятся 3D модели. Как правило, эти модели — сложные объекты, которые тяжело смоделировать вручную примитивами. Поэтому для создания моделей используются 3D редакторы. Например Autodesk 3D Studio MAX, Maya 3D, Blender, MilkShape 3D, Lodka3D и многие другие.

Форматов 3D моделей очень много. Практически каждый 3D редактор или игра имеют собственный формат со своими особенностями, впрочем, существует ряд более-менее универсальных форматов, с которыми могут работать многи редакторы. В GLScene есть поддержка многих форматов, для их использования следует подключить соответствующий файл (как и с рисунками). Рассмотрим их подробнее (красным выделены частично поддерживаемые):

Формат Модуль Описание
3DS (3DS Max и многие другие). GLFile3DS Один из самых используемых форматов. Может содержать много дополнительной информации.
MD2 (Quake2, анимация) GLFileMD2 Содержит сеточную анимацию (хранится каждый кадр в целом), довольно удобен в использовании.
MD3 (Quake3, анимация) GLFileMD3 Аналогичен MD2, но немного совершеннее.
SMD (Half-Life, анимация) GLFileSMD Лучший формат анимации из поддерживае-мых, т. к. хранит скелетную анимацию (один файл содержит модель с привязанных скелетом, а данные об анимации этого скелета хранятся в других файлах). Формат является текстовым.
OBJ (WaveFront и многие другие) GLFileOBJ Простой текстовый формат данных, который содержит только 3D геометрию (вершины, грани, нормали) и текстурные координаты.
OCT (FSRad) GLFileOCT Octree Format проекта RADIANCE для построения реалистичных изображений, разрабатываемого при поддержке министерства энергетики США и Швейцарского федерального правительства. Официальный сайт проекта: radsite.lbl.gov/radiance/index.html.
NMF GLFileNMF  
GTS GLFileGTS GNU Triangulated Surface
GL2 (Ghoul2 aka MDX) GLFileGL2  
BSP (Quake3) GLBSP Имеет довольно хитрую структуру, представляет собой совокупность плоскостей, ограничивающих пространство.
PLY (Stanford) GLFilePLY Существуют модификации данного формата. Стандартный модуль будет работать только с самым простым вариантом.
LWO (LightWave) GLFileLWO  
MS3D (MilkShape) GLFileMS3D Формат редактора MilkShape 3D.
STL GLFileSTL  
TIN GLFileTIN  

GLActor

 

Для использования анимированных моделей существует специальный компонент GLActor.

Создайте стандартный проект и добавьте актера: Mesh objects — Actor. Установите его Position в (0;3;-1). Источнику света установите Position в (2;2;2).

Модель используем из образцов GLScene: зайдите в Demos\media, а там найдите файлы waste. md2, quake2animations. aaf и waste. jpg и скопируйте его в папку с нашем проектом. Мы используем файлы md2 и jpeg, поэтому в uses надо добавить модули GLFileMD2 и Jpeg. Теперь в FormCreate напишем:

GLActor1.LoadFromFile('waste.md2');

GLActor1.AddDataFromFile('quake2animations.aaf');

GLActor1.Material.Texture.Image.LoadFromFile('waste.jpg');

GLActor1.Material.Texture.Disabled:=false;

GLActor1.Scale.SetVector(0.04, 0.04, 0.04, 0);

GLActor1.AnimationMode:=aamLoop;

GLActor1.SwitchToAnimation('run');

Сначала мы загружаем модели из файла и список ее анимаций, затем одеваем на нее текстуру и масштабируем модель до нормальнх размеров. Потом устанавливаем ему режим анимации в циклический и устанавливаем анимацию бега. Кстати, проигрывание анимации было бы невозможно без GLCadencer.

Теперь сделаем так, чтобы при нажатии какой-нибудь клавиши актер останавливался. Для этого добавим модуль GLKeyboard и в OnProgress запишем:

var

s: string;

begin

if IsKeyDown(VK_RETURN) then

begin

if GLActor1.CurrentAnimation<>'run' then

GLActor1.SwitchToAnimation('run');

else

if GLActor1.CurrentAnimation<>'stand' then

GLActor1.SwitchToAnimation('stand');

end;

Рассмотрим теперь вещи, специфичные для сеточной и скелетной анимаций.

Морфная анимация

 

Модели с анимацией, реалиованной с помощью морфинга, содержат в себе целиком каждый кадр анимации. Благодаря этому, они меньше потребляют ресурсов процессора, т. к. не нужно производить никаких расчетов. В файлах формата MD2 не всегда содержится список анимаций, поэтому в таких случаях его следует загрузить из файла aaf с помощью AddDAtaFromFile(‘имя файла’). Их формат прост:

AAF

количество анимаций

имя анимации, начальный кадр, конечный кадр

имя анимации, начальный кадр, конечный кадр

Скелетная анимация

 

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

Вначале следует загрузить файл модели, после чего с помощью той же процедуры AddDataFromFile загрузить нужные анимации. После этого для всех анимаций следует выполнить процедуру MakeSkeletalTranslationStatic (без этого модель будет нежелательно двигаться вперед при проигрывании).

Рассмотрим скелет моделей и как его использовать. Создадим стандартный проект и добавим туда актера. Для начала получим список всех имеющихся костей.

for i:=0 to GLActor1.Skeleton.BoneCount-2 do

bones_list.Items.Add(GLActor1.Skeleton.BoneByID(i).Name);

Чтобы обратиться к отдельной кости, можно использовать BoneByName(‘имя кости’) или BoneByID(‘индекс кости’), через имя удобнее — оно обычно мнемонично и его можно узнать в редакторе при подготовке модели.

Тепеь посмотрим, как «прикрепить» какой-либо объект к актеру. Это очень удобно: объект (оружие, щит,…) будет двигаться естественно безо всяких ухищрений (если, конечно, тщательно сделать анимации). Для этого добавим в uses модуль VectorGeometry, в сцену что-нибудь с именем «weapon», поместим на форму GLCadencer и запишем в его OnProgress:

var

m: TMatrix4f;

begin

m:=GLActor1.Skeleton.BoneByName('Bip01 R Finger02').GlobalMatrix;

weapon.Matrix:=MatrixMultiply(m,GLActor1.AbsoluteMatrix);

end;

Сначала получаем матрицу 2 пальца (Finger02) правой руки (R), а затем оружию устанавливаем ее абсолютную матрицу (чтобы при повороте или перемещении всей модели оружие не отставало).

Напоследок напомним, что у актеров формата SMD на каждом полигоне модели должна быть текстура, иначе модель не загрузится. Кроме того, в TGLActor можно грузить и статические модели (3DS, OBJ), но этим лучше не пользоваться, т.к. TGLFreeForm дает большую производительность.

GLFreeForm

 

Кроме GLActor есть ещё один объект — GLFreeForm. Он предназначен только для статичной геометрии. Для загрузки моделей используйте те же функции, что и для GLActor.

Свойство ObjectStyle управляет включением или выключением использования дисплейных списков. Я рекомендую их всегда отключать:

GLFreeForm.ObjectStyle:=[osDirectDraw];

потому что Khronos Group (консорциум разработчиков OpenGL) исключил дисплейные списки из OpenGL. Свойство GLFreeForm. MeshObjects. UseVBO определяет, будут ли использоваться буферы вершинных массивов (Vertex Buffer Objects) или нет. Я рекомендую включать его всегда.

В модуле GLVectorFileObjects есть глобальная переменная vGLVectorFileObjectsEnableVBOByDefault типа Boolean, которая включает или выключает использования буферов вершинных массивов еще при создании объекта.

 

Также важно знать, что GLFreeForm поддерживает octree-деревья. Построение этого дерева вызывается командой BuildOctree([TreeDepth:Integer = 3]). По сути, эта команда разбивает модель на множество кубов. На первом шаге мы получаем 8 кубов (отсюда и слог «Oct»), на втором шаге разбиваем каждый из кубов еще на 8, на третьем разбиваем ещё на 8 и т. д. столько раз, сколько передано в TreeDepth. Для каждого куба хранятся координаты его вершин (по сути - минимальные и максимальные координаты среди всех полигонов, попавших в этот куб). В дальнейшем, при проверке видимости или при проверке пересечений с лучами и другими объектами мы пропускаем те кубы (и все полигоны, заключенные в них), которые целиком находятся вне видимости камеры или в стороне от луча, значительно увеличивая скорость отрисовки и трассировки.

Одно из важнейших действий с сеточными объеками — проверка, пересекаются ли они с прямой, или нет. Рассмотрим его на примере стрельбы в типичном шутере. После выстрела мы должны проверить а) попадает он в противника (тип GLActor, назовем enemy) или нет и 2) не было ли перед противником преграды (предположим, что все преграды вроде зданий, рельфа и т. д. находятся в одном GLFreeForm). Как это сделать?

a) Для проверки попадания в противника проверяем, пересекает ли его луч, пущенный из положения игрока (назовем его player) в направлении стрельбы (предположим, оно совпадает с направлением игрока, как это часто и бывает). Пишем:

if enemy.RayCastIntersect(player.Position.AsVector,

player.Direction.AsVector, @int_point1, @int_normal) then

 

Функция вернет, произошло ли пересечение луча. Два необязательных последних параметра - это указатель на точку пересечения и нормаль к точке пересечения.

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

int_map:=map.OctreeRayCastIntersect(player.Position.AsVector,

player.Direction.AsVector, @int_point2);

if (int_map=false)or

((int_map)and(player.SqrDistanceTo(int_point_1)<

player.SqrDistanceTo(int_point_2)) then

begin

// Обрабатываем попадание

end;

 

Много ценной информации о GLFreeForm можно найти на форуме www.glscene.ru, например glscene.ru/forum_viewtopic.php?6.34065.0

glscene.ru/forum_viewtopic.php?6.36114.0

 


Глава 11. Прокси-объекты

Инстансинг в GLScene

 

Если нужно использовать много одинаковых объектов, то лучше не создавать их все по отдельности, а создать лишь один базовый объект, а для каждой его копии делать proxy. Proxy — это копия объекта, для визуализации которой используется ряд оптимизаций, что увеличивает FPS. На рисунке вы видите 9 копий одного и того же объекта и сам базовый объект.

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

Proxy в GLScene реализуется довольно хитро. Вся идея состоит в том, чтобы использовать один массив для хранения всех матриц трансформаций. Такой приём в компьютерной графике называется программным копированием объектов или более заумным словом — инстансинг (instancing). К слову, есть ещё два типа инстансинга — псевдо и аппаратный. Они работают намного быстрее встроенного в сцену, примерно в два раза.

Псевдо-инстансинг реализуется через GLSL-шейдеры. Урок по копированию объектов таким образом приведён в главе 45.

Аппаратный инстансинг стал возможен в 2009 году с выходом OpenGL 3.1, а именно расширения EXT_draw_instanced. На русском про него можете почитать здесь: http://steps3d.narod.ru/tutorials/draw-instanced-tutorial.html. В этой статье он не рассматривается.

В GLScene присутствуют семь компонентов для создания и использования proxy объектов. Это GLProxyObject, GLColorProxy, GLFreeFormProxy, GLMaterialProxy, GLActorProxy, GLMultiProxy и GLMaterialMultiProxy.

 

GLProxyObject служит для копирования примитивов.

GLFreeFormProxy оптимизирован для копирования FreeForm.

GLActorProxy используется для копирования GLActor. Здесь же стоит отметить, что анимация GLActor повторяется на всех его proxy-объектах.

GLActorProxy позволяет назначать копиям объекта разную анимацию по сравнению с мастер-объектом, в остальном он эквивалентен GLProxyObject.

GLMultiProxyObject — более передовая версия прокси объектов. Она имеет большие возможности и использует технологию оптимизации LOD.

LOD (Levels Of Detail) — это приём в программировании 3D-графики, заключающийся в создании нескольких вариантов одного объекта с различными степенями детализации, которые переключаются в зависимости от расстояния объекта до виртуальной камеры.

Существуют два подхода к управлению детализацией: статический и динамический LOD. В первом случае заранее создают упрощенные варианты максимально детализированного объекта. Предположим, что для модели танка, состоящей из 1200 полигонов, достаточно сделать упрощенные варианты из 600 и 300 полигонов. В ходе построения сцены рассчитывается расстояние от плоскости проецирования до танка и выбирается соответствующий вариант. Оно вызывает эффект «дерганья» изображения при смене детализации объекта. Если уровень LOD близок к граничному значению, иногда возникает циклическая смена моделей с разным уровнем детализации. К тому же приходится хранить несколько разных моделей для одного объекта.

Динамическое управление детализацией потребляет значительные вычислительные ресурсы, требуя непрерывного пересчета не только координат вершин треугольников, но и параметров освещенности. При частом переключении между уровнями иногда наблюдается эффект «волнистости» поверхности — форма объекта непрерывно меняется, что в неживой природе выглядит особенно нереально.

GLMultiProxy реализует статический LOD, позволяя proxy-объекту иметь несколько мастер-объектов. У него есть свойство MasterObjects, при нажатии на него появится окно Editing GLMultiProxy.MasterObjects. В нём программист создаёт абстрактные хранилища мастер-объектов. У каждого такого хранилища присутствуют следующие свойства:

Свойство Описание
DistanceMax Максимальное расстояние от камеры, на котором используется этот мастер-объект.
DistanceMin Минимальное расстояние, для самого высокополигонального объекта обычно устанавливается в нуль.
MasterObject Сам мастер-объект.
Visible Будет ли виден мастер-объект.

 

Добавлять прокси объект можно через инспектор объектов сцены или объявлять где-нибудь в программе.

Пример:

var

pro: TGLProxyObject;

i: integer;

begin

GLFreeForm1.LoadFromFile('mushroom.obj');

GLFreeForm1.Scale.Scale(0.2);

GLFreeForm1.Pitch(90);

for i:=1 to 100 do

begin

pro:=TGLProxyObject.CreateAsChild(GLScene1.Objects);

pro.MasterObject:=GLFreeForm1;

pro.ProxyOptions:=[pooObjects,pooTransformation];

pro.Position.X:=0.1*(500-i);

pro.Position.Z:=-50;

end;

end;

Появится 100 стоящих в ряд грибов.

Я приведу описание некоторых свойств.

Свойство Описание
MasterObject В это свойство записывается объект, который нужно скопировать.
ProxyOptions Множество, в котором могут быть следующие элементы: pooObjects — будет ли proxy будет копировать структуру мастер-объекта. pooTransformation — будет ли proxy копировать масштаб, положение и ориентацию мастер-объекта. pooEffects — будет ли proxy копировать эффекты мастер-объекта.

 

Демка по компоненту GLMultiProxyObject лежит здесь: Demos\rendering\multiproxy.



Поделиться:


Последнее изменение этой страницы: 2016-04-19; просмотров: 531; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.149.254.110 (0.046 с.)