Сейчас делаю редактор карт на движке IrrLicht, а потом может и игру сделаю, почему решил сначала редактор, а потому что собственно редактор контента игры содержит практически 50% функционала самой игры :)

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

map

Изначально мощение ландшафта выглядело так:

for (int z=0; z<128; z++)
for (int x=0; x<128; x++)
{
irr::scene::IMeshSceneNode* n = smgr->addMeshSceneNode( mes, 0, -1, irr::core::vector3df(-x, 0, z) );
n->setMaterialFlag( irr::video::EMF_LIGHTING, false ); //освещение пока не использую
n->setMaterialTexture( 0, tex );
n->getMesh()->setHardwareMappingHint(irr::scene::EHM_STATIC); //типа VBO
}

Не смотря на включенный VBO, при наличи ландшафта всего лишь из мозаики на 128х128 квадратика, сцена выдавала 9 фпс(fps) и собственно смысл дальнейшей разработки пропадал, т.к. неизвестно какой низкий будет фпс(fps) если этот ландшафт засадить и заселить.

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

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

greed

но почитав доки по OpenGL и о том как рисуются полигоны, я понял что я повелся на 3д редакторы и на самом деле в красной точке сосредоточены 4 вершины принадлежащие четырем окружающим полигонам. Все встало на свои места и генерация сцены стала выглядеть так:

irr::video::SColor cubeColour(255,255,255,255);

irr::scene::SMesh *dmes = new irr::scene::SMesh;
irr::scene::SMeshBuffer *buffer = new irr::scene::SMeshBuffer;

//вершины
int v_cnt = w * h * 4; //число вершин в полигонах
int p_cnt = 0; //счетчик полигонов, фактически номер первой вершины полигона из buffer->Vertices
buffer->Vertices.set_used(v_cnt);
for(int z=0; z<h; z++)
for(int x=0; x<w; x++)
{
buffer->Vertices[p_cnt]  = irr::video::S3DVertex(    -x,0,  z,   0,1,0, cubeColour, 0, 0);
buffer->Vertices[p_cnt+1]  = irr::video::S3DVertex(-x-1,0,  z,   0,1,0, cubeColour, 0, 1);
buffer->Vertices[p_cnt+2]  = irr::video::S3DVertex(-x-1,0,z+1,   0,1,0, cubeColour, 1, 1);
buffer->Vertices[p_cnt+3]  = irr::video::S3DVertex(  -x,0,z+1,   0,1,0, cubeColour, 1, 0);
p_cnt += 4;
}

//порядок обхода
int i_cnt = w * h * 6; //число индексов
p_cnt = 0; //счетчик полигонов, фактически номер первой вершины полигона из buffer->Vertices
buffer->Indices.set_used(i_cnt);
for(int i=0; i<i_cnt; i+=6) //за один шаг цикла описываем 2 треугольника из которых состоит полигон
{
buffer->Indices[i] = p_cnt;
buffer->Indices[i+1] = p_cnt+1;
buffer->Indices[i+2] = p_cnt+2;
buffer->Indices[i+3] = p_cnt;
buffer->Indices[i+4] = p_cnt+2;
buffer->Indices[i+5] = p_cnt+3;
p_cnt += 4;
}

buffer->recalculateBoundingBox();
dmes->addMeshBuffer(buffer);
buffer->drop();
dmes->setHardwareMappingHint(irr::scene::EHM_STATIC); //типа VBO

irr::scene::IMeshSceneNode *meshNode = smgr->addMeshSceneNode(dmes);
dmes->drop();
meshNode->setMaterialFlag(irr::video::EMF_LIGHTING, false);
meshNode->setMaterialTexture(0, tex);

вот так… число строк кода выросло, но приятно что геометрически выросло и быстродействие с 9 фпс до 1000, чтобы совсем уж наглядно было – выкладывают ТЕСТ С ИСХОДНИКОМ качайте, смотрите, используйте. По клавише «1″ сцена генерится из 128*128 нод, по «2″ из одной ноды с динамически сформированным массивом вершин на 128*128 полигонов без использования VBO, по «3″ ко второму медоту подключается VBO

осталось реализовать это в своем проекте и двигаться дальше :)

P.s. кстати буфера ирлихта 16битные, поэтому более 65к в них не запихнуть, так что 128*128 прямоугольных полигонов состоящих из двух треугольников каждый – это предел. вот так.

Примечания:

VBO – vertex buffer object (объект вершинного буфера)
FPS – frame per second (кадров в секунду)


Отзывов: 9 на “Быстродействие Irrlicht сильно зависит от числа нод(node) на сцене”

  1. online ()

    желаю все щастя в новом году

  2. Эльмиго ()

    Спасибо

  3. Эльмиго ()

    обновил чутка статью, добавил
    buffer->drop();
    dmes->drop();
    во избежание утечки памяти

    исходник в прежнем состоянии, прошу это учесть

  4. Vasiliy ()

    Спасибо, познавательно. ирлихт рулит!

  5. Костя ()

    Хороший способ повышение быстродйествия. Но если буферы должы быть активными (выделяться мышкой, например), придется писать новый triangleselector (или добавить функцию к существующему) который указывает не только узел, но и мешбуфер в ней.

  6. Эльмиго ()

    да придется, если есть необходимость, т.к. текущая реализация селектора позволит узнать тока ноду и полигон

  7. Костя ()

    Я нашел еще один способ повышения быстродействия. Правда там быстродействие всего в 2 раза повышается, но способ дает вомзожность манипулировать с нодами.

    Способ таков: нужно создать специальную ноду, которая сама будет рендерить дочерние, а не отдавать на стандартный конвеер. При этом ноды сохраняют свою самостоятельность и с ними можно работать обычными средствами движка. И способ достаточно прост в реализации.

  8. Эльмиго ()

    заинтриговал, а по детальнее изложить бы ;)

  9. Костя ()

    вот здесь тему начал с описанием


Оставьте свой отзыв

Вы должны войти, чтобы оставлять комментарии.