diff options
author | David Walter Seikel | 2014-01-13 19:47:58 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-01-13 19:47:58 +1000 |
commit | f9158592e1478b2013afc7041d9ed041cf2d2f4a (patch) | |
tree | b16e389d7988700e21b4c9741044cefa536dcbae /libraries/irrlicht-1.8/examples/16.Quake3MapShader/main.cpp | |
parent | Libraries readme updated with change markers and more of the Irrlicht changes. (diff) | |
download | SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.zip SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.gz SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.bz2 SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.xz |
Update Irrlicht to 1.8.1. Include actual change markers this time. lol
Diffstat (limited to 'libraries/irrlicht-1.8/examples/16.Quake3MapShader/main.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/examples/16.Quake3MapShader/main.cpp | 388 |
1 files changed, 0 insertions, 388 deletions
diff --git a/libraries/irrlicht-1.8/examples/16.Quake3MapShader/main.cpp b/libraries/irrlicht-1.8/examples/16.Quake3MapShader/main.cpp deleted file mode 100644 index bd11c95..0000000 --- a/libraries/irrlicht-1.8/examples/16.Quake3MapShader/main.cpp +++ /dev/null | |||
@@ -1,388 +0,0 @@ | |||
1 | /** Example 016 Quake3 Map Shader Support | ||
2 | |||
3 | This Tutorial shows how to load a Quake 3 map into the | ||
4 | engine, create a SceneNode for optimizing the speed of | ||
5 | rendering and how to create a user controlled camera. | ||
6 | |||
7 | Lets start like the HelloWorld example: We include | ||
8 | the irrlicht header files and an additional file to be able | ||
9 | to ask the user for a driver type using the console. | ||
10 | */ | ||
11 | #include <irrlicht.h> | ||
12 | #include "driverChoice.h" | ||
13 | |||
14 | /* | ||
15 | define which Quake3 Level should be loaded | ||
16 | */ | ||
17 | #define IRRLICHT_QUAKE3_ARENA | ||
18 | //#define ORIGINAL_QUAKE3_ARENA | ||
19 | //#define CUSTOM_QUAKE3_ARENA | ||
20 | //#define SHOW_SHADER_NAME | ||
21 | |||
22 | #ifdef ORIGINAL_QUAKE3_ARENA | ||
23 | #define QUAKE3_STORAGE_FORMAT addFolderFileArchive | ||
24 | #define QUAKE3_STORAGE_1 "/baseq3/" | ||
25 | #ifdef CUSTOM_QUAKE3_ARENA | ||
26 | #define QUAKE3_STORAGE_2 "/cf/" | ||
27 | #define QUAKE3_MAP_NAME "maps/cf.bsp" | ||
28 | #else | ||
29 | #define QUAKE3_MAP_NAME "maps/q3dm8.bsp" | ||
30 | #endif | ||
31 | #endif | ||
32 | |||
33 | #ifdef IRRLICHT_QUAKE3_ARENA | ||
34 | #define QUAKE3_STORAGE_FORMAT addFileArchive | ||
35 | #define QUAKE3_STORAGE_1 "../../media/map-20kdm2.pk3" | ||
36 | #define QUAKE3_MAP_NAME "maps/20kdm2.bsp" | ||
37 | #endif | ||
38 | |||
39 | using namespace irr; | ||
40 | using namespace scene; | ||
41 | |||
42 | /* | ||
43 | Again, to be able to use the Irrlicht.DLL file, we need to link with the | ||
44 | Irrlicht.lib. We could set this option in the project settings, but | ||
45 | to make it easy, we use a pragma comment lib: | ||
46 | */ | ||
47 | #ifdef _MSC_VER | ||
48 | #pragma comment(lib, "Irrlicht.lib") | ||
49 | #endif | ||
50 | |||
51 | |||
52 | /* | ||
53 | A class to produce a series of screenshots | ||
54 | */ | ||
55 | class CScreenShotFactory : public IEventReceiver | ||
56 | { | ||
57 | public: | ||
58 | |||
59 | CScreenShotFactory( IrrlichtDevice *device, const c8 * templateName, ISceneNode* node ) | ||
60 | : Device(device), Number(0), FilenameTemplate(templateName), Node(node) | ||
61 | { | ||
62 | FilenameTemplate.replace ( '/', '_' ); | ||
63 | FilenameTemplate.replace ( '\\', '_' ); | ||
64 | } | ||
65 | |||
66 | bool OnEvent(const SEvent& event) | ||
67 | { | ||
68 | // check if user presses the key F9 | ||
69 | if ((event.EventType == EET_KEY_INPUT_EVENT) && | ||
70 | event.KeyInput.PressedDown) | ||
71 | { | ||
72 | if (event.KeyInput.Key == KEY_F9) | ||
73 | { | ||
74 | video::IImage* image = Device->getVideoDriver()->createScreenShot(); | ||
75 | if (image) | ||
76 | { | ||
77 | c8 buf[256]; | ||
78 | snprintf(buf, 256, "%s_shot%04d.jpg", | ||
79 | FilenameTemplate.c_str(), | ||
80 | ++Number); | ||
81 | Device->getVideoDriver()->writeImageToFile(image, buf, 85 ); | ||
82 | image->drop(); | ||
83 | } | ||
84 | } | ||
85 | else | ||
86 | if (event.KeyInput.Key == KEY_F8) | ||
87 | { | ||
88 | if (Node->isDebugDataVisible()) | ||
89 | Node->setDebugDataVisible(scene::EDS_OFF); | ||
90 | else | ||
91 | Node->setDebugDataVisible(scene::EDS_BBOX_ALL); | ||
92 | } | ||
93 | } | ||
94 | return false; | ||
95 | } | ||
96 | |||
97 | private: | ||
98 | IrrlichtDevice *Device; | ||
99 | u32 Number; | ||
100 | core::stringc FilenameTemplate; | ||
101 | ISceneNode* Node; | ||
102 | }; | ||
103 | |||
104 | |||
105 | /* | ||
106 | Ok, lets start. | ||
107 | */ | ||
108 | |||
109 | int IRRCALLCONV main(int argc, char* argv[]) | ||
110 | { | ||
111 | /* | ||
112 | Like in the HelloWorld example, we create an IrrlichtDevice with | ||
113 | createDevice(). The difference now is that we ask the user to select | ||
114 | which hardware accelerated driver to use. The Software device would be | ||
115 | too slow to draw a huge Quake 3 map, but just for the fun of it, we make | ||
116 | this decision possible too. | ||
117 | */ | ||
118 | |||
119 | // ask user for driver | ||
120 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); | ||
121 | if (driverType==video::EDT_COUNT) | ||
122 | return 1; | ||
123 | |||
124 | // create device and exit if creation failed | ||
125 | const core::dimension2du videoDim(800,600); | ||
126 | |||
127 | IrrlichtDevice *device = createDevice(driverType, videoDim, 32, false ); | ||
128 | |||
129 | if (device == 0) | ||
130 | return 1; // could not create selected driver. | ||
131 | |||
132 | const char* mapname=0; | ||
133 | if (argc>2) | ||
134 | mapname = argv[2]; | ||
135 | else | ||
136 | mapname = QUAKE3_MAP_NAME; | ||
137 | |||
138 | /* | ||
139 | Get a pointer to the video driver and the SceneManager so that | ||
140 | we do not always have to write device->getVideoDriver() and | ||
141 | device->getSceneManager(). | ||
142 | */ | ||
143 | video::IVideoDriver* driver = device->getVideoDriver(); | ||
144 | scene::ISceneManager* smgr = device->getSceneManager(); | ||
145 | gui::IGUIEnvironment* gui = device->getGUIEnvironment(); | ||
146 | |||
147 | //! add our private media directory to the file system | ||
148 | device->getFileSystem()->addFileArchive("../../media/"); | ||
149 | |||
150 | /* | ||
151 | To display the Quake 3 map, we first need to load it. Quake 3 maps | ||
152 | are packed into .pk3 files, which are nothing other than .zip files. | ||
153 | So we add the .pk3 file to our FileSystem. After it was added, | ||
154 | we are able to read from the files in that archive as they would | ||
155 | directly be stored on disk. | ||
156 | */ | ||
157 | if (argc>2) | ||
158 | device->getFileSystem()->QUAKE3_STORAGE_FORMAT(argv[1]); | ||
159 | else | ||
160 | device->getFileSystem()->QUAKE3_STORAGE_FORMAT(QUAKE3_STORAGE_1); | ||
161 | #ifdef QUAKE3_STORAGE_2 | ||
162 | device->getFileSystem()->QUAKE3_STORAGE_FORMAT(QUAKE3_STORAGE_2); | ||
163 | #endif | ||
164 | |||
165 | // Quake3 Shader controls Z-Writing | ||
166 | smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); | ||
167 | |||
168 | /* | ||
169 | Now we can load the mesh by calling getMesh(). We get a pointer returned | ||
170 | to a IAnimatedMesh. As you know, Quake 3 maps are not really animated, | ||
171 | they are only a huge chunk of static geometry with some materials | ||
172 | attached. Hence the IAnimated mesh consists of only one frame, | ||
173 | so we get the "first frame" of the "animation", which is our quake level | ||
174 | and create an Octree scene node with it, using addOctreeSceneNode(). | ||
175 | The Octree optimizes the scene a little bit, trying to draw only geometry | ||
176 | which is currently visible. An alternative to the Octree would be a | ||
177 | AnimatedMeshSceneNode, which would draw always the complete geometry of | ||
178 | the mesh, without optimization. Try it out: Write addAnimatedMeshSceneNode | ||
179 | instead of addOctreeSceneNode and compare the primitives drawn by the | ||
180 | video driver. (There is a getPrimitiveCountDrawed() method in the | ||
181 | IVideoDriver class). Note that this optimization with the Octree is only | ||
182 | useful when drawing huge meshes consisting of lots of geometry. | ||
183 | */ | ||
184 | scene::IQ3LevelMesh* const mesh = | ||
185 | (scene::IQ3LevelMesh*) smgr->getMesh(mapname); | ||
186 | |||
187 | /* | ||
188 | add the geometry mesh to the Scene ( polygon & patches ) | ||
189 | The Geometry mesh is optimised for faster drawing | ||
190 | */ | ||
191 | scene::ISceneNode* node = 0; | ||
192 | if (mesh) | ||
193 | { | ||
194 | scene::IMesh * const geometry = mesh->getMesh(quake3::E_Q3_MESH_GEOMETRY); | ||
195 | node = smgr->addOctreeSceneNode(geometry, 0, -1, 4096); | ||
196 | } | ||
197 | |||
198 | // create an event receiver for making screenshots | ||
199 | CScreenShotFactory screenshotFactory(device, mapname, node); | ||
200 | device->setEventReceiver(&screenshotFactory); | ||
201 | |||
202 | /* | ||
203 | now construct SceneNodes for each Shader | ||
204 | The Objects are stored in the quake mesh scene::E_Q3_MESH_ITEMS | ||
205 | and the Shader ID is stored in the MaterialParameters | ||
206 | mostly dark looking skulls and moving lava.. or green flashing tubes? | ||
207 | */ | ||
208 | if ( mesh ) | ||
209 | { | ||
210 | // the additional mesh can be quite huge and is unoptimized | ||
211 | const scene::IMesh * const additional_mesh = mesh->getMesh(quake3::E_Q3_MESH_ITEMS); | ||
212 | |||
213 | #ifdef SHOW_SHADER_NAME | ||
214 | gui::IGUIFont *font = device->getGUIEnvironment()->getFont("../../media/fontlucida.png"); | ||
215 | u32 count = 0; | ||
216 | #endif | ||
217 | |||
218 | for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount(); ++i ) | ||
219 | { | ||
220 | const IMeshBuffer* meshBuffer = additional_mesh->getMeshBuffer(i); | ||
221 | const video::SMaterial& material = meshBuffer->getMaterial(); | ||
222 | |||
223 | // The ShaderIndex is stored in the material parameter | ||
224 | const s32 shaderIndex = (s32) material.MaterialTypeParam2; | ||
225 | |||
226 | // the meshbuffer can be rendered without additional support, or it has no shader | ||
227 | const quake3::IShader *shader = mesh->getShader(shaderIndex); | ||
228 | if (0 == shader) | ||
229 | { | ||
230 | continue; | ||
231 | } | ||
232 | |||
233 | // we can dump the shader to the console in its | ||
234 | // original but already parsed layout in a pretty | ||
235 | // printers way.. commented out, because the console | ||
236 | // would be full... | ||
237 | // quake3::dumpShader ( Shader ); | ||
238 | |||
239 | node = smgr->addQuake3SceneNode(meshBuffer, shader); | ||
240 | |||
241 | #ifdef SHOW_SHADER_NAME | ||
242 | count += 1; | ||
243 | core::stringw name( node->getName() ); | ||
244 | node = smgr->addBillboardTextSceneNode( | ||
245 | font, name.c_str(), node, | ||
246 | core::dimension2d<f32>(80.0f, 8.0f), | ||
247 | core::vector3df(0, 10, 0)); | ||
248 | #endif | ||
249 | } | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | Now we only need a Camera to look at the Quake 3 map. And we want to | ||
254 | create a user controlled camera. There are some different cameras | ||
255 | available in the Irrlicht engine. For example the Maya Camera which can | ||
256 | be controlled comparable to the camera in Maya: Rotate with left mouse | ||
257 | button pressed, Zoom with both buttons pressed, translate with right | ||
258 | mouse button pressed. This could be created with | ||
259 | addCameraSceneNodeMaya(). But for this example, we want to create a | ||
260 | camera which behaves like the ones in first person shooter games (FPS). | ||
261 | */ | ||
262 | |||
263 | scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); | ||
264 | |||
265 | /* | ||
266 | so we need a good starting Position in the level. | ||
267 | we can ask the Quake3 Loader for all entities with class_name | ||
268 | "info_player_deathmatch" | ||
269 | we choose a random launch | ||
270 | */ | ||
271 | if ( mesh ) | ||
272 | { | ||
273 | quake3::tQ3EntityList &entityList = mesh->getEntityList(); | ||
274 | |||
275 | quake3::IEntity search; | ||
276 | search.name = "info_player_deathmatch"; | ||
277 | |||
278 | s32 index = entityList.binary_search(search); | ||
279 | if (index >= 0) | ||
280 | { | ||
281 | s32 notEndList; | ||
282 | do | ||
283 | { | ||
284 | const quake3::SVarGroup *group = entityList[index].getGroup(1); | ||
285 | |||
286 | u32 parsepos = 0; | ||
287 | const core::vector3df pos = | ||
288 | quake3::getAsVector3df(group->get("origin"), parsepos); | ||
289 | |||
290 | parsepos = 0; | ||
291 | const f32 angle = quake3::getAsFloat(group->get("angle"), parsepos); | ||
292 | |||
293 | core::vector3df target(0.f, 0.f, 1.f); | ||
294 | target.rotateXZBy(angle); | ||
295 | |||
296 | camera->setPosition(pos); | ||
297 | camera->setTarget(pos + target); | ||
298 | |||
299 | ++index; | ||
300 | /* | ||
301 | notEndList = ( index < (s32) entityList.size () && | ||
302 | entityList[index].name == search.name && | ||
303 | (device->getTimer()->getRealTime() >> 3 ) & 1 | ||
304 | ); | ||
305 | */ | ||
306 | notEndList = index == 2; | ||
307 | } while ( notEndList ); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | The mouse cursor needs not to be visible, so we make it invisible. | ||
313 | */ | ||
314 | |||
315 | device->getCursorControl()->setVisible(false); | ||
316 | |||
317 | // load the engine logo | ||
318 | gui->addImage(driver->getTexture("irrlichtlogo2.png"), | ||
319 | core::position2d<s32>(10, 10)); | ||
320 | |||
321 | // show the driver logo | ||
322 | const core::position2di pos(videoDim.Width - 128, videoDim.Height - 64); | ||
323 | |||
324 | switch ( driverType ) | ||
325 | { | ||
326 | case video::EDT_BURNINGSVIDEO: | ||
327 | gui->addImage(driver->getTexture("burninglogo.png"), pos); | ||
328 | break; | ||
329 | case video::EDT_OPENGL: | ||
330 | gui->addImage(driver->getTexture("opengllogo.png"), pos); | ||
331 | break; | ||
332 | case video::EDT_DIRECT3D8: | ||
333 | case video::EDT_DIRECT3D9: | ||
334 | gui->addImage(driver->getTexture("directxlogo.png"), pos); | ||
335 | break; | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | We have done everything, so lets draw it. We also write the current | ||
340 | frames per second and the drawn primitives to the caption of the | ||
341 | window. The 'if (device->isWindowActive())' line is optional, but | ||
342 | prevents the engine render to set the position of the mouse cursor | ||
343 | after task switching when other program are active. | ||
344 | */ | ||
345 | int lastFPS = -1; | ||
346 | |||
347 | while(device->run()) | ||
348 | if (device->isWindowActive()) | ||
349 | { | ||
350 | driver->beginScene(true, true, video::SColor(255,20,20,40)); | ||
351 | smgr->drawAll(); | ||
352 | gui->drawAll(); | ||
353 | driver->endScene(); | ||
354 | |||
355 | int fps = driver->getFPS(); | ||
356 | //if (lastFPS != fps) | ||
357 | { | ||
358 | io::IAttributes * const attr = smgr->getParameters(); | ||
359 | core::stringw str = L"Q3 ["; | ||
360 | str += driver->getName(); | ||
361 | str += "] FPS:"; | ||
362 | str += fps; | ||
363 | str += " Cull:"; | ||
364 | str += attr->getAttributeAsInt("calls"); | ||
365 | str += "/"; | ||
366 | str += attr->getAttributeAsInt("culled"); | ||
367 | str += " Draw: "; | ||
368 | str += attr->getAttributeAsInt("drawn_solid"); | ||
369 | str += "/"; | ||
370 | str += attr->getAttributeAsInt("drawn_transparent"); | ||
371 | str += "/"; | ||
372 | str += attr->getAttributeAsInt("drawn_transparent_effect"); | ||
373 | |||
374 | device->setWindowCaption(str.c_str()); | ||
375 | lastFPS = fps; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | In the end, delete the Irrlicht device. | ||
381 | */ | ||
382 | device->drop(); | ||
383 | |||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | /* | ||
388 | **/ | ||