mirror of
https://github.com/minetest/irrlicht.git
synced 2024-12-27 11:10:31 +01:00
123 lines
12 KiB
HTML
123 lines
12 KiB
HTML
|
<html>
|
||
|
<head>
|
||
|
<title>Irrlicht Engine Tutorial</title>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||
|
</head>
|
||
|
|
||
|
<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
|
||
|
<br>
|
||
|
<table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
|
||
|
<tr>
|
||
|
<td bgcolor="#666699" width="10"><b><a href="http://irrlicht.sourceforge.net" target="_blank"><img src="../../media/irrlichtlogo.jpg" width="88" height="31" border="0"></a></b></td>
|
||
|
<td bgcolor="#666699" width="100%">
|
||
|
<div align="center">
|
||
|
<div align="left"><b><font color="#FFFFFF">Tutorial 12. Terrain Rendering</font></b></div>
|
||
|
</div>
|
||
|
</td>
|
||
|
</tr>
|
||
|
<tr bgcolor="#eeeeff">
|
||
|
<td height="90" colspan="2">
|
||
|
<div align="left">
|
||
|
<p> This tutorial will briefly show how to use the terrain renderer of
|
||
|
Irrlicht. It will also show the terrain renderer triangle selector to
|
||
|
be able to do collision detection with terrain.</p>
|
||
|
<p>The program which is described here will look like this:</p>
|
||
|
<p align="center"><img src="../../media/012shot.jpg" width="258" height="202"></p>
|
||
|
<p align="left"><br>
|
||
|
Note that the terrain renderer in Irrlicht is based the terrain renderer
|
||
|
by Soconne and the GeoMipMapSceneNode developed by Spinz, lots of thanks
|
||
|
go to them.</p>
|
||
|
</div>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<br>
|
||
|
<table width="95%" border="0" cellspacing="0" cellpadding="2" align="center">
|
||
|
<tr>
|
||
|
<td bgcolor="#666699"> <b><font color="#FFFFFF">Lets start!</font></b></td>
|
||
|
</tr>
|
||
|
<tr>
|
||
|
<td height="90" bgcolor="#eeeeff" valign="top"> <div align="left">
|
||
|
<div align="left">
|
||
|
<p> In the beginning there is nothing special. We include the needed
|
||
|
header files and create an event listener to listen if the user presses
|
||
|
the 'W' key so we can switch to wireframe mode and if he presses 'D'
|
||
|
we toggle to material between solid and detail mapped.</p>
|
||
|
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
|
||
|
<tr>
|
||
|
<td> <pre>#include <irrlicht.h><br>#include <iostream><br>using namespace irr;<br><br>#pragma comment(lib, "Irrlicht.lib")<br><br>class MyEventReceiver : public IEventReceiver<br>{<br>public:<br> MyEventReceiver(scene::ISceneNode* terrain)<br> {<br><font color="#006600"> // store pointer to terrain so we can change its drawing mode<br></font> Terrain = terrain;<br> }<br><br> bool OnEvent(const SEvent& event)<br> {<br> <font color="#006600"> // check if user presses the key 'W' or 'D'</font><br> if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)<br> {<br> switch (event.KeyInput.Key)<br> {<br> case irr::KEY_KEY_W:<font color="#006600"> // switch wire frame mode</font><br> Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe);<br> return true;<br> case irr::KEY_KEY_D:<font color="#006600"> // toggle detail map</font><br> Terrain->setMaterialType(<br> Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ? <br> video::EMT_DETAIL_MAP : video::EMT_SOLID);<br> return true;<br> }<br> }<br> return false;<br> }<br><br>private:<br> scene::ISceneNode* Terrain;<br>};<br><br></pre></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<p>The start of the main function starts like in most other example.
|
||
|
We ask the user for the desired renderer and start it up. </p>
|
||
|
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
|
||
|
<tr>
|
||
|
<td> <pre>int main()<br>{<br><font color="#006600"> // let user select driver type<br></font><br> video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;<br><br> printf("Please select the driver you want for this example:\n"\<br> " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\<br> " (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\<br> " (f) NullDevice\n (otherKey) exit\n\n");<br><br> char i;<br> std::cin >> i;<br><br> switch(i)<br> {<br> case 'a': driverType = video::EDT_DIRECT3D9;break;<br> case 'b': driverType = video::EDT_DIRECT3D8;break;<br> case 'c': driverType = video::EDT_OPENGL; break;<br> case 'd': driverType = video::EDT_SOFTWARE; break;<br> case 'e': driverType = video::EDT_BURNINGSVIDEO;break;<br> case 'f': driverType = video::EDT_NULL; break;<br> default: return 1;<br> } <br><font color="#006600"><br> // create device<br></font> IrrlichtDevice* device = createDevice(driverType, core::dimension2d<s32>(640, 480));<br><br> if (device == 0)<br> return 1; <font color="#006600">// could not create selected driver.</font><br></pre></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<p> First, we add standard stuff to the scene: A nice irrlicht engine
|
||
|
logo, a small help text, a user controlled camera, and we disable
|
||
|
the mouse cursor.</p>
|
||
|
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
|
||
|
<tr>
|
||
|
<td> <pre>video::IVideoDriver* driver = device->getVideoDriver();<br>scene::ISceneManager* smgr = device->getSceneManager();<br>gui::IGUIEnvironment* env = device->getGUIEnvironment();<br><br>driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);<br><br><font color="#006600">// add irrlicht logo<br></font>env->addImage(driver->getTexture("../../media/irrlichtlogoalpha.tga"),<br> core::position2d<s32>(10,10));<br>
|
||
|
<font color="#006600">// add some help text<br></font>gui::IGUIStaticText* text = env->addStaticText(<br> L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map",<br> core::rect<s32>(10,453,200,475), true, true, 0, -1, true);<br>
|
||
|
<font color="#006600">// add camera<br></font>scene::ICameraSceneNode* camera = <br> smgr->addCameraSceneNodeFPS(0,100.0f,1200.0f);<br>camera->setPosition(core::vector3df(1900*2,255*2,3700*2));<br>camera->setTarget(core::vector3df(2397*2,343*2,2700*2));<br>camera->setFarValue(12000.0f);<br><br><font color="#006600">// disable mouse cursor<br></font>device->getCursorControl()->setVisible(false);</pre></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<p> Here comes the terrain renderer scene node: We add it just like
|
||
|
any other scene node to the scene using ISceneManager::addTerrainSceneNode().
|
||
|
The only parameter we use is a file name to the heightmap we use.
|
||
|
A heightmap is simply a gray scale texture. The terrain renderer loads
|
||
|
it and creates the 3D terrain from it.<br>
|
||
|
To make the terrain look more big, we change the scale factor of it
|
||
|
to (40, 4.4, 40). Because we don't have any dynamic lights in the
|
||
|
scene, we switch off the lighting, and we set the file terrain-texture.jpg
|
||
|
as texture for the terrain and detailmap3.jpg as second texture, called
|
||
|
detail map. At last, we set the scale values for the texture: The
|
||
|
first texture will be repeated only one time over the whole terrain,
|
||
|
and the second one (detail map) 20 times. </p>
|
||
|
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
|
||
|
<tr>
|
||
|
<td> <pre><font color="#006600">// add terrain scene node<br></font>scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( <br> "../../media/terrain-heightmap.bmp");<br><br>terrain->setScale(core::vector3df(40, 4.4f, 40));<br>terrain->setMaterialFlag(video::EMF_LIGHTING, false);<br><br>terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg"));<br>terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg"));<br> <br>terrain->setMaterialType(video::EMT_DETAIL_MAP);<br>terrain->scaleTexture(1.0f, 20.0f);<font color="#006600"><br></font></pre></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<p> To be able to do collision with the terrain, we create a triangle
|
||
|
selector. If you want to know what triangle selectors do, just take
|
||
|
a look into the collision tutorial. The terrain triangle selector
|
||
|
works together with the terrain. To demonstrate this, we create a
|
||
|
collision response animator and attach it to the camera, so that the
|
||
|
camera will not be able to fly through the terrain. </p>
|
||
|
</div>
|
||
|
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
|
||
|
<tr>
|
||
|
<td> <pre><font color="#006600">// create triangle selector for the terrain <br></font>scene::ITriangleSelector* selector =<br> smgr->createTerrainTriangleSelector(terrain, 0);<br>terrain->setTriangleSelector(selector);<br><br><font color="#006600">// create collision response animator and attach it to the camera<br></font>scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(<br> selector, camera, core::vector3df(60,100,60),<br> core::vector3df(0,0,0), <br> core::vector3df(0,50,0));<br>selector->drop();<br>camera->addAnimator(anim);<br>anim->drop();</pre></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<p> To make the user be able to switch between normal and wireframe mode,
|
||
|
we create an instance of the event reciever from above and let Irrlicht
|
||
|
know about it. In addition, we add the skybox which we already used
|
||
|
in lots of Irrlicht examples.</p>
|
||
|
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
|
||
|
<tr>
|
||
|
<td><pre><font color="#006600">// create event receiver<br></font>MyEventReceiver receiver(terrain);<br>device->setEventReceiver(&receiver);<br><br><font color="#006600">// create skybox<br></font>driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);<br><br>smgr->addSkyBoxSceneNode(<br> driver->getTexture("../../media/irrlicht2_up.jpg"),<br> driver->getTexture("../../media/irrlicht2_dn.jpg"),<br> driver->getTexture("../../media/irrlicht2_lf.jpg"),<br> driver->getTexture("../../media/irrlicht2_rt.jpg"),<br> driver->getTexture("../../media/irrlicht2_ft.jpg"),<br> driver->getTexture("../../media/irrlicht2_bk.jpg"));<br>
|
||
|
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);<br></pre></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<p> That's it, draw everything. Now you know how to use terrain in Irrlicht.</p>
|
||
|
<table width="95%" border="0" cellspacing="2" cellpadding="0" bgcolor="#CCCCCC" align="center">
|
||
|
<tr>
|
||
|
<td><pre> int lastFPS = -1;<br><br> while(device->run())<br> if (device->isWindowActive())<br> {<br> driver->beginScene(true, true, 0 );<br><br> smgr->drawAll();<br> env->drawAll();<br><br> driver->endScene();
|
||
|
<br><font color="#006600"> // display frames per second in window title
|
||
|
</font> int fps = driver->getFPS();<br><br> if (lastFPS != fps)<br> {<br> core::stringw str = L"Terrain Renderer - Irrlicht Engine [";<br> str += driver->getName();<br> str += "] FPS:";<br> str += fps;<br> device->setWindowCaption(str.c_str());<br> lastFPS = fps;<br> }<br> }<br><br> device->drop();<br> <br> return 0;<br>}</pre></td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<p> </p>
|
||
|
</div>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
<p> </p>
|
||
|
</body>
|
||
|
</html>
|