Оригинал:
http://irrlicht.sourceforge.net/tut002.html
Урок 2: Карта Quake 3
Этот Урок покажет, как загрузить карту Quake 3 в движок, создать SceneNode для оптимизации скорости рендеринга, и создать управляемую пользователем камеру. Пожалуйста, обратите внимание, что вы должны знать основы движка, прежде чем начнете этот урок. Рекомендуется коротко ознакомиться с первым уроком, 1. HelloWorld, если вы этого еще не сделали.
Результат примера будит выглядеть подобно этому:
Давайте начнем!
Давайте начнем, как и в примере HelloWorld: Мы подключим заголовочные файлы irrlicht и добавим файл, чтобы можно было спрашивать у пользователя через консоль, какой тип устройства использовать.
Код:
#include <irrlicht.h>
#include <iostream>
Как еже писалось в примере HelloWorld , в Irrlicht Engine, все может быть создано в пространстве имен 'irr'. чтобы освободится от irr:: в начале имени каждого класса, мы укажем компилятору что мы теперь используем пространство имен, и мы не будим должны писать этот 'irr::'.
Также другие 5 подпространств имен 'core', 'scene', 'video', 'io' и 'gui'. В отличии от примера HelloWorld, мы не напишем 'using namespace'для этих 5 пространств имен потому что таким образом мы сможем увидеть что расположено в каждом пространстве имен. Но если вам нравится, вы можете также включить пространства имен, как и в предыдущем примере. Код точно, такой как вы хотите.
Код:
using namespace irr;
Опять, чтобы можно было использовать файл Irrlicht.DLL, мы должны указать Irrlicht.lib. Мы могли бы установить это в опциях в настройках проекта, но мы сделаем это проще, мы используем псевдокомментарий:
Код:
#pragma comment(lib, "Irrlicht.lib")
Хорошо, давайте начнем. Снова, мы используем метод main() как начало, а не WinMain(), потому что это короче писать.
Код:
int main()
{
Как в примере HelloWorld, мы создаем IrrlichtDevice с createDevice(). Различие теперь о что мы просим пользователя выбрать какой драйвер аппаратного ускорения использовать. Программное устройство слишком медленно рисует большую карту Quake 3, но только для забавы, мы тоже сделаем этот вариант возможным.
Код:
// ask user for driver
video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_SOFTWARE2;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
}
// create device and exit if creation failed
IrrlichtDevice *device =
createDevice(driverType, core::dimension2d<s32>(640, 480));
if (device == 0)
return 1;
Получим указатель на видео драйвер и SceneManager, так чтобы нам всегда не приходилось писать device->getVideoDriver() и device->getSceneManager().
Код:
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
Чтобы отобразить карту Quake, мы сначала должны загрузить ее. Карта Quake 3 упакована в файл .pk3 что есть нечто иное как файлы .zip. Так мы добавляем файл .pk3 к нашей Файловой Системе. После того как он будит добавлен, мы сможем читать файлы в архиве так как будто они прямо на диске.
Код:
device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3");
Теперь мы сможем загрузить карту вызвав getMesh(). Мы получаем указатель возвращенный IAnimatedMesh. Как вы знаете, карты Quake 3 не анимированы, они всего лишь огромный кусок статической геометрии с некоторыми привязанными материалами. Следовательно, уровень IAnimated состоит всего лишь из одного кадра, так мы получаем "первый кадр" из "анимации", который является нашим уровнем quake и создаем узел сцены OctTree с ним, используя addOctTreeSceneNode().OctTree немного оптимизирует сцену, пытаясь нарисовать только геометрию видимую сейчас. Альтернатива OctTree это AnimatedMeshSceneNode, которая рисует всегда всю геометрию карты, без оптимизации. Испытайте это: напишите addAnimatedMeshSceneNode вместо addOctTreeSceneNode и сравните примитивы, выводимые видео драйвером. (Есть метод getPrimitiveCountDrawed() в классе IVideoDriver). Замете что это оптимизация Octree полезна только когда выводится огромная карта состоящей из массы геометрий.
Код:
scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* node = 0;
if (mesh)
node = smgr->addOctTreeSceneNode(mesh->getMesh(0));
Так как уровень был смоделирован не вокруг начального адреса (0,0,0), мы немножко сдвинем весь уровень.
Код:
if (node)
node->setPosition(core::vector3df(-1300,-144,-1249));
Теперь нам нужна Камера, чтобы видеть карту Quake 3. И нам необходимо создать пользовательское управление камерой. Есть несколько различных камер доступных в Irrlicht engine. Для примера Maya Camera которой можно управлять подобно камере в Maya: Вращать с нажатой левой кнопкой мыши, Масштабировать с обеими нажатыми кнопками, Перемещаться с нажатой правой кнопкой мыши. Это может быть сделано с помощью addCameraSceneNodeMaya(). Но для этого примера, мы создадим камеру, которая ведет себя также как те, которые в шутерах от первого лица (FPS):
Код:
smgr->addCameraSceneNodeFPS();
Курсор мыши должен быть невидим, так мы сделаем его невидимым.
Код:
device->getCursorControl()->setVisible(false);
Мы сделали все, так что можем выводить это. Мы также напишем количество кадров в секунду и выводимые примитивы в заголовок окна. Эта 'if (device->isWindowActive())' строка необязательна, она лишь предотвращает рендер движку устанавливать позицию курсора мышки после переключения задач, когда другая программа активна.
Код:
int lastFPS = -1;
while(device->run())
{
driver->beginScene(true, true, video::SColor(0,200,200,200));
smgr->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"Irrlicht Engine - Quake 3 Map example [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
В конце, удаляем Irrlicht device.
Код:
device->drop();
return 0;
}
Вот. Скомпилируйте и манипулируйте с программой.