Začínáme podobně jako v první lekci: Přidáme hlavičkový soubor irrlichtu a oproti první lekci přidáme taky iostream který se postará o vstup/výstup z konzole. Budeme totiž dotazovat uživatele, zda chce použít OpenGL, DirectX, nebo jiný render.
#include <irrlicht.h> #include <iostream>
|
Stejně jako v minulém tutoriálu, i zde použijeme irr namespace. Kód je samozřejmě:
Také znovu, použijeme knihovnu irrlicht.
#pragma comment(lib, "Irrlicht.lib") |
Ok, tak začínáme. Použijeme main() a do složených závorek začneme psát samotný kod aplikace.
Podobně jako v prvním tutoriálu vytvoříme device. Rozdíl však je v tom, že nyní necháme uživatele vybrat, jaké rozhraní bude chtít použít. Výběr se provádí pomocí konzole. Za jednotlivá písmena dosadíme zařízení. Po jejich vybrání se hodnota předá proměnné driverType kterou použijeme v příkazu createDevice. Pokud se nevybere žádná možnost, celý proces se opakuje až do vybrání typu zařízení.Ze začátku se vám kód může zdát více či méně chaotický, ale sami brzo přijdete na to, že tomu tak není.
// 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; |
Přidáme ukazatele:
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager(); |
Pro nahrání Quake3 (*.bsp) mapy musíme nejprve otevřít celý archiv, ve kterém se mapa nachází. Jedná se o formát *.pk3 (je to vlastně jen jiná forma ZIPu). Takže přidáme do fileSytemu archiv pk3 (to znamená že všechny soubory se budou nahrávat z něj). Až po tomto kroku můžeme přistoupit na samotný load mapy.
device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3"); |
Nyní můžeme nahrát mapu voláním funkce getMesh(). Dále ji přidáme jako Octree (to je hlavní rozdíl oproti první lekci). Alternativou by mohla být funkce addAnimatedMeshSceneNode, Octree však používáme u modelu který obsahuje velké množství geometrie(právě například mapa). Pokud použijeme Octree, zrychlí to také běh našeho programu.
scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp"); scene::ISceneNode* node = 0;
if (mesh) node = smgr->addOctTreeSceneNode(mesh->getMesh(0)); |
Nastavíme pozici mapy (u datového typu vector3df je pořadí hodnot vždy x,y,z):
if (node) node->setPosition(core::vector3df(-1300,-144,-1249)); |
Ted potřebujeme kameru, aby jsme se na Quake 3 mapu mohli podívat. Kameru bude kontrolovat uživatel. V irrlicht enginu je takových kamer hned několik. Například Maya kamera je ovládána srovnatelně jako v 3d modeleru Maya: rotaci provádíte se stisknutým levým tlačítkem myši a zoom (přiblížení) stisknutím obou tlačítek myši. V našem případě ale použijeme kameru podobnou FPS hrám(z pohledu vlastních očí):
smgr->addCameraSceneNodeFPS(); |
Kurzor myši vidět nepotřebujeme, tak ho uděláme neviditelným
device->getCursorControl()->setVisible(false); |
Nyní je vše hotovo. Vykreslíme celou scénu a přidáme počítadlo fps (frame per second) tedy počtu snímků za sekundu.
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;
}
}
|
Pokud se createDevice nezdaří, ukončíme běh programu.
device->drop(); return 0; } |
Zkompilujte a spusťte a pokud máte nějaké nápady o co by tento kód šel obohatit, nebo jinak upravit, tak jste na správné cestě k samostatnému programátorovi :)