Пятница, 19.04.2024, 06:08
Приветствую Вас Гость | RSS

Кузница миров

Меню сайта
Категории раздела
Мои статьи [2]
Курс : "Основы С++ для начинающих программистов игр." [25]
WindMill Engine [3]
XNA4 RPG [0]
Перевод туториалов но созданию RPG на C# c XNA4.
C# & Leadwerks [5]
Программирование Leadwerks Engine на языке С# с помощью врапера Le.NET.

Каталог статей и уроков

Главная » Статьи » C# & Leadwerks

4. Leadwerks Engine. Введение в меши.

1. Введение в меши

----------------------------------------------------------------------------------------------------------------------------

Приступать к изучению этого материала желательно после знакомства с уроками:

2. Работа с освещением

С исходного кода этого урока мы и начнем. Также для работы понадобятся некоторые файлы, которые можно скачать здесь.

----------------------------------------------------------------------------------------------------------------------------

В 3D графике мешем является любой рисуемый трехмерный объект. Получил он свое название от английского mesh (сетка), потому что трехмерный объект состоит из точек, вершин, соединенных линиями, в результате выглядит как сеть.

С простыми мешами мы уже работали на предыдущих уроках, создавая куб.

 

//Создаем куб

TEntity cube = LE.CreateCube();

 

Здесь созданный куб присваивался переменной, имеющей тип TEntity. Но ничто не мешает нам явно указать, что это меш, подставив тип TMesh.

 

//Создаем куб

TMesh cube = LE.CreateCube();

 

Постольку TEntity является базовым для TMesh, никаких проблем в коде такое переименование не вызовет, а мы будем точно знать, что работаем с мешем.

Помимо создания графических примитивов, вроде куба, Leadwerks engine позволяет загружать ранее созданные с помощью 3D редакторов меши из файлов или же собирать их вручную из вершин и полигонов. Изучением всех этих возможностей мы сейчас и займемся.

Leadwerks Engine умеет загружать такие форматы трехмерной графики: OBJ, MD3, 3DW, GMF. Разработчики движка рекомендуют GMF.

Распакуйте из указанной в шапке этой статьи ссылки файлы и поместите их в свой проект к исполняемому файлу.

В архиве находятся 4 файла:

normal_map.dds – текстура, содержащая карту нормалей;

color_map.dds – текстура, которая будет наложена на меш;

brick.mat – информация об используемом для меша материале, в данном случае о текстурах и шейдерах; О материалах мы еще поговорим.

box.gmf – файл, содержащий информацию о меше.

Чтобы загрузить box.gmf нужно добавить в код перед главным циклом следующую функцию:

 

//Загружаем меш из файла

TMesh cube2 = LE.LoadMesh("box.gmf");

 

Будьте осторожны. Если вы случайно поставите функцию загрузки в главный цикл, то меш будет загружаться в каждом кадре, игра начнет тормозить и, в конце концов, повиснет.

Скомпилировав и запустив программу, мы увидим следующее:

[image]

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

 

LE.PositionEntity(cube, LE.Vec3(-2,0,0));

 

Теперь объекты не накладываются друг на друга:

[image]

Хватит уже наблюдать за невзрачными серыми кубиками, пора делать их красивее. Для этого загрузим файл материалов brick.mat.

 

// Загружаем материал

TMaterial mat = LE.LoadMaterial("brick.mat");

 

Материалы в движке представлены типом TMaterial.

И применяем его на оба наших куба, не забыв при этом проверить, действительно ли материал загрузился:

 

if (mat!=null)

{

//Применяем материал к мещам

LE.PaintEntity(cube, mat);

LE.PaintEntity(cube2, mat);

}

 

Если вы все сделали правильно, то при запуске вас ждет такая картина:

[image]

Ну и весь код, который имеется на текущий момент:

 

class Program

{

static void Main(string[] args)

{

// подключение dll движка

LE.Initialize();

//Создание окна для вивода графики

LE.Graphics(640, 480, 0, 0, LE.GRAPHICS_BACKBUFFER + LE.GRAPHICS_DEPTHBUFFER);

//Создаем мир. Это делается в первую очередь.

LE.CreateWorld();

//Создаем камеру

TEntity cam = LE.CreateCamera();

// Устанавливаем координаты камеры

LE.MoveEntity(cam, LE.Vec3(0, 0, -5));

//Создаем куб

TMesh cube = LE.CreateCube();

LE.PositionEntity(cube, LE.Vec3(-2,0,0));

 

//Загружаем меш из файла

TMesh cube2 = LE.LoadMesh("box.gmf");

 

// Загружаем материал

TMaterial mat = LE.LoadMaterial("brick.mat");

if (mat!=null)

{

//Применяем материал к мещам

LE.PaintEntity(cube, mat);

LE.PaintEntity(cube2, mat);

}

 

//Создаем источник света

TEntity light = LE.CreateSpotLight();

//устанавливаем позицию

LE.PositionEntity(light, LE.Vec3(2, 2, -2));

LE.RotateEntity(light, LE.Vec3(45, 45, 0));

 

//создаем буфер

TBuffer buffer = LE.CreateBuffer(800, 600, LE.BUFFER_COLOR0 | LE.BUFFER_DEPTH | LE.BUFFER_NORMAL);

 

//Создаем куб

TMesh ground = LE.CreateCube();

//Меняем размеры и позицию

LE.ScaleMesh(ground, LE.Vec3(10, 0.1f, 10));

LE.PositionEntity(ground, LE.Vec3(0, -2, 0));

 

//Визуализация источников света

// LE.DebugLights(1);

 

//Главный цикл

while (!LE.KeyHit(Keys.KEY_ESCAPE)) // пока не нажата ESCAPE

{

//Вращаем куб

LE.TurnEntity(cube, LE.Vec3(0.5f));

//Обновляем мир

LE.UpdateWorld(1);

 

//Сделать созданный буфер активным.

LE.SetBuffer(buffer);

//Рисуем мир

LE.RenderWorld(LE.RENDER_ALL);

//Деактивировать свой буфер, вернув предыдущий

LE.SetBuffer(LE.BackBuffer());

//Провести расчет и отрисовку изображения на основе своего буфера

LE.RenderLights(buffer);

 

//Переключаем буфер

LE.Flip(1);

}

//Отключаем движок и выгружаем dll из памяти

LE.Terminate();

}

}

 

Ручное создание мешей

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

Как вы уже знаете, меш строится из точек называемых вершинами(или вертексами), три таких вершины образуют плоскость - полигон. У полигона имеются такие параметры как текстурные координаты, используемые при наложении текстур, и нормаль – перпендикуляр к плоскости полигона, указывающий направление отражения света. Более подробное объяснение терминов 3d графики советую поискать в интернете.

Так вот, самое сложное в ручной генерации – правильно задать все вершины с их параметрами.

Для начала сдвинем загруженный куб, чтобы он не загораживал обзов.

 

LE.PositionEntity(cube2, LE.Vec3(2, 0, 0));

 

Теперь создадим меш.

 

//Создаем пустой меш

TMesh cubScratch = LE.CreateMesh();

 

Этот меш полностью пуст, и не имеет никакой информации для отображения. Необходимо в меше создать поверхность (surface), к которой будут добавляться вершины и применятся материалы. Меш может содержать несколько поверхностей. Все полигоны одной поверхности используют один материал и рисуются одним пакетом за одно обращение к GPU.

 

//создаем поверхность

TSurface surf = LE.CreateSurface(cubScratch);

 

Теперь добавим к поверхности вершины:

 

//Добавляем вершины

LE.AddVertex(surf, LE.Vec3(-0.5f, 0, 0));

LE.AddVertex(surf, LE.Vec3(0.5f, 1, 0));

LE.AddVertex(surf, LE.Vec3(0.5f, 0, 0));

 

Вершина это всего лишь точка, поэтому она задается тремя координатами Vec3(x, y, z). Далее объединяем вершины в полигон:

 

// Создаем полигон

LE.AddTriangle(surf, 0, 1, 2);

 

Эта функция принимает номер вершины. Вершины нумеруются в порядке их создания, отсчет начинается от 0.

После редактирования меша нужно вызвать функцию UpdateMesh.

//Обновляем меш

LE.UpdateMesh(cubScratch);

 

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

Запустив код мы увидим невзрачный треугольник.

 

[image]

 

Применим к созданному мешу загруженный ранее материал и запустим программу.

 

LE.PaintEntity(cubScratch, mat);

 

[image]

 

Почти ничего не изменилось, разве что цвет треугольника, а вот красивой текстуры кирпича нет. Это потому, что меш не имеет текстурных координат и нормалей.

Добавьте этот код перед обновлением созданного меша:

 

//Добавляем нормали

LE.SetVertexNormal(surf, 0, LE.Vec3(0, 0, -1));

LE.SetVertexNormal(surf, 1, LE.Vec3(0, 0, -1));

LE.SetVertexNormal(surf, 2, LE.Vec3(0, 0, -1));

// Добавляем текстурные координаты

LE.SetVertexTexCoords(surf, 0, LE.Vec2(0, 1));

LE.SetVertexTexCoords(surf, 1, LE.Vec2(1, 0));

LE.SetVertexTexCoords(surf, 2, LE.Vec2(1, 1));

 

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

После внесенных изменений текстура будет наложена правильно.

 

[image]

 

Далее мы можем полностью построить куб. Для этого понадобится 24 вершины. Код довольно большой и однообразный. Главное правильно задать координаты. Его я приводить здесь не буду, скачивайте по этой ссылке.

После его запуска можно увидеть три вращающиеся кирпичных куба. Я добавил всем код вращения.

 

[image]

 

На скриншоте можно увидеть три одинаковых куба, но все они были созданы разными способами. Первый – функцией создания примитивов, второй – вручную из вершин, третий был загружен из файла, созданного в 3d редакторе.

Категория: C# & Leadwerks | Добавил: nilrem (09.09.2012)
Просмотров: 3074 | Теги: mesh, вершины, Игры, C#, Leadwerks Engine, полигон, 3D | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0