воскресенье, 28 апреля 2013 г.

Cone-код или чудеса оТПимизации.

Кодю генератор растительности. Собственно, сам генератор уже готов - теперь занимаюсь тем, чтобы мне не пришлось вручную указывать, какие модели грузить из архива. Они грузятся все :D

std::map< std::string, std::vector< Node*> >assets;

Bundle *b = Bundle::create( "res/assets/tree.gpb" );
_loader = b->loadScene();
for ( ; _loader->getFirstNode() != NULL; )
{
     Node* asset = _loader->getFirstNode();
     _scene->addNode(asset);
     asset->getModel()->setMaterial("res/anim.material");
     Animation* an = asset->getAnimation();
     AnimationClip* cl = an->createClip("idle", 0, an->getDuration() );
     cl->setSpeed(1);
     cl->setRepeatCount(0);
     cl->play();
     assets["trees"].push_back(asset);
}
_loader->release();
SAFE_RELEASE(b);

for (size_t i = 0; i < dots.size(); i++)
{
     dots[i].ID = rand() % assets["trees"].size();
}

Cхемка простейшая, но через полгода едва ли я смогу объяснить, как она работает, поэтому сейчас расскажу :D

В игре есть две сцены - _scene и _loader. Одна отвечает за отрисовку, а другая только за загрузку дополнительных ресурсов. А всё потому, что в этом движке невозможно заранее узнать, какие именно объекты хранятся в архиве, поэтому ресурсы из архивов я гружу целиком в _loader.

Открывается файл "tree.gpb" со скелетными моделями, из него все ресурсы грузятся во временную сцену _loader, а дальше начинается МАГИЯ. Если из сцены _loader добавить объект в сцену _scene, то из _loader он попросту удалится - поэтому цикл for организован таким странным образом (скорее всего лучше было бы обойтись while do).

Node* asset - это указатель на внутриигровой объект, у которого есть матрица трансформации, модель, материал, физический объект, источник звука и эмиттер системы частиц (аналог DummyCube из GLScene). Этому объектику в качестве мамы указываем совсем не родную сцену _scene, тем самым уменьшая счетчик объектов в сцене _loader.
Присваиваем модели объекта asset материал "aim.material", чтобы заработала скелетная анимация, рассчитываемая на GPU. Создаем анимационный клип длиной со всю анимацию, устанавливаем ему скорость, зацикливаем и запускаем.

А дальше - мое маленькое чудо (в любое другое время я вряд ли бы стал юзать такую страшную, но ужасно удобную конструкцию) - есть мап assets, в котором сразу же создастся раздел "trees", хранящий в себе вектор указателей на игровые объекты. В этот вектор и добавится наш объект.

Зачем это нужно: вместо того, чтобы создавать тысячу разных векторов под всякие нужды (для моделей персонажей, деревьев, предметов, других объектов), я аккуратно запаковал всё это дело в подобие словаря, где я могу обратиться к нужной странице ("tree") и отрисовать определенный объект ( assets["tree"][dots[i].ID]->getModel()->draw() ).

Днем таким же макаром буду запаковывать модели из другого архива в раздел "actors".

1 комментарий: