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.1/examples/21.Quake3Explorer/q3factory.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 '')
-rw-r--r-- | libraries/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.cpp | 824 |
1 files changed, 824 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.cpp b/libraries/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.cpp new file mode 100644 index 0000000..d0f09b2 --- /dev/null +++ b/libraries/irrlicht-1.8.1/examples/21.Quake3Explorer/q3factory.cpp | |||
@@ -0,0 +1,824 @@ | |||
1 | /*! | ||
2 | Model Factory. | ||
3 | create the additional scenenodes for ( bullets, health... ) | ||
4 | |||
5 | Defines the Entities for Quake3 | ||
6 | */ | ||
7 | |||
8 | #include <irrlicht.h> | ||
9 | #include "q3factory.h" | ||
10 | #include "sound.h" | ||
11 | |||
12 | using namespace irr; | ||
13 | using namespace scene; | ||
14 | using namespace gui; | ||
15 | using namespace video; | ||
16 | using namespace core; | ||
17 | using namespace quake3; | ||
18 | |||
19 | //! This list is based on the original quake3. | ||
20 | static const SItemElement Quake3ItemElement [] = { | ||
21 | { "item_health", | ||
22 | {"models/powerups/health/medium_cross.md3", | ||
23 | "models/powerups/health/medium_sphere.md3"}, | ||
24 | "sound/items/n_health.wav", | ||
25 | "icons/iconh_yellow", | ||
26 | "25 Health", | ||
27 | 25, | ||
28 | HEALTH, | ||
29 | SUB_NONE, | ||
30 | SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 | ||
31 | }, | ||
32 | { "item_health_large", | ||
33 | "models/powerups/health/large_cross.md3", | ||
34 | "models/powerups/health/large_sphere.md3", | ||
35 | "sound/items/l_health.wav", | ||
36 | "icons/iconh_red", | ||
37 | "50 Health", | ||
38 | 50, | ||
39 | HEALTH, | ||
40 | SUB_NONE, | ||
41 | SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 | ||
42 | }, | ||
43 | { | ||
44 | "item_health_mega", | ||
45 | "models/powerups/health/mega_cross.md3", | ||
46 | "models/powerups/health/mega_sphere.md3", | ||
47 | "sound/items/m_health.wav", | ||
48 | "icons/iconh_mega", | ||
49 | "Mega Health", | ||
50 | 100, | ||
51 | HEALTH, | ||
52 | SUB_NONE, | ||
53 | SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 | ||
54 | }, | ||
55 | { | ||
56 | "item_health_small", | ||
57 | "models/powerups/health/small_cross.md3", | ||
58 | "models/powerups/health/small_sphere.md3", | ||
59 | "sound/items/s_health.wav", | ||
60 | "icons/iconh_green", | ||
61 | "5 Health", | ||
62 | 5, | ||
63 | HEALTH, | ||
64 | SUB_NONE, | ||
65 | SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 | ||
66 | }, | ||
67 | { "ammo_bullets", | ||
68 | "models/powerups/ammo/machinegunam.md3", | ||
69 | "", | ||
70 | "sound/misc/am_pkup.wav", | ||
71 | "icons/icona_machinegun", | ||
72 | "Bullets", | ||
73 | 50, | ||
74 | AMMO, | ||
75 | MACHINEGUN, | ||
76 | SPECIAL_SFX_BOUNCE, | ||
77 | }, | ||
78 | { | ||
79 | "ammo_cells", | ||
80 | "models/powerups/ammo/plasmaam.md3", | ||
81 | "", | ||
82 | "sound/misc/am_pkup.wav", | ||
83 | "icons/icona_plasma", | ||
84 | "Cells", | ||
85 | 30, | ||
86 | AMMO, | ||
87 | PLASMAGUN, | ||
88 | SPECIAL_SFX_BOUNCE | ||
89 | }, | ||
90 | { "ammo_rockets", | ||
91 | "models/powerups/ammo/rocketam.md3", | ||
92 | "", | ||
93 | "", | ||
94 | "icons/icona_rocket", | ||
95 | "Rockets", | ||
96 | 5, | ||
97 | AMMO, | ||
98 | ROCKET_LAUNCHER, | ||
99 | SPECIAL_SFX_ROTATE | ||
100 | }, | ||
101 | { | ||
102 | "ammo_shells", | ||
103 | "models/powerups/ammo/shotgunam.md3", | ||
104 | "", | ||
105 | "sound/misc/am_pkup.wav", | ||
106 | "icons/icona_shotgun", | ||
107 | "Shells", | ||
108 | 10, | ||
109 | AMMO, | ||
110 | SHOTGUN, | ||
111 | SPECIAL_SFX_ROTATE | ||
112 | }, | ||
113 | { | ||
114 | "ammo_slugs", | ||
115 | "models/powerups/ammo/railgunam.md3", | ||
116 | "", | ||
117 | "sound/misc/am_pkup.wav", | ||
118 | "icons/icona_railgun", | ||
119 | "Slugs", | ||
120 | 10, | ||
121 | AMMO, | ||
122 | RAILGUN, | ||
123 | SPECIAL_SFX_ROTATE | ||
124 | }, | ||
125 | { | ||
126 | "item_armor_body", | ||
127 | "models/powerups/armor/armor_red.md3", | ||
128 | "", | ||
129 | "sound/misc/ar2_pkup.wav", | ||
130 | "icons/iconr_red", | ||
131 | "Heavy Armor", | ||
132 | 100, | ||
133 | ARMOR, | ||
134 | SUB_NONE, | ||
135 | SPECIAL_SFX_ROTATE | ||
136 | }, | ||
137 | { | ||
138 | "item_armor_combat", | ||
139 | "models/powerups/armor/armor_yel.md3", | ||
140 | "", | ||
141 | "sound/misc/ar2_pkup.wav", | ||
142 | "icons/iconr_yellow", | ||
143 | "Armor", | ||
144 | 50, | ||
145 | ARMOR, | ||
146 | SUB_NONE, | ||
147 | SPECIAL_SFX_ROTATE | ||
148 | }, | ||
149 | { | ||
150 | "item_armor_shard", | ||
151 | "models/powerups/armor/shard.md3", | ||
152 | "", | ||
153 | "sound/misc/ar1_pkup.wav", | ||
154 | "icons/iconr_shard", | ||
155 | "Armor Shared", | ||
156 | 5, | ||
157 | ARMOR, | ||
158 | SUB_NONE, | ||
159 | SPECIAL_SFX_ROTATE | ||
160 | }, | ||
161 | { | ||
162 | "weapon_gauntlet", | ||
163 | "models/weapons2/gauntlet/gauntlet.md3", | ||
164 | "", | ||
165 | "sound/misc/w_pkup.wav", | ||
166 | "icons/iconw_gauntlet", | ||
167 | "Gauntlet", | ||
168 | 0, | ||
169 | WEAPON, | ||
170 | GAUNTLET, | ||
171 | SPECIAL_SFX_ROTATE | ||
172 | }, | ||
173 | { | ||
174 | "weapon_shotgun", | ||
175 | "models/weapons2/shotgun/shotgun.md3", | ||
176 | "", | ||
177 | "sound/misc/w_pkup.wav", | ||
178 | "icons/iconw_shotgun", | ||
179 | "Shotgun", | ||
180 | 10, | ||
181 | WEAPON, | ||
182 | SHOTGUN, | ||
183 | SPECIAL_SFX_ROTATE | ||
184 | }, | ||
185 | { | ||
186 | "weapon_machinegun", | ||
187 | "models/weapons2/machinegun/machinegun.md3", | ||
188 | "", | ||
189 | "sound/misc/w_pkup.wav", | ||
190 | "icons/iconw_machinegun", | ||
191 | "Machinegun", | ||
192 | 40, | ||
193 | WEAPON, | ||
194 | MACHINEGUN, | ||
195 | SPECIAL_SFX_ROTATE | ||
196 | }, | ||
197 | { | ||
198 | "weapon_grenadelauncher", | ||
199 | "models/weapons2/grenadel/grenadel.md3", | ||
200 | "", | ||
201 | "sound/misc/w_pkup.wav", | ||
202 | "icons/iconw_grenade", | ||
203 | "Grenade Launcher", | ||
204 | 10, | ||
205 | WEAPON, | ||
206 | GRENADE_LAUNCHER, | ||
207 | SPECIAL_SFX_ROTATE | ||
208 | }, | ||
209 | { | ||
210 | "weapon_rocketlauncher", | ||
211 | "models/weapons2/rocketl/rocketl.md3", | ||
212 | "", | ||
213 | "sound/misc/w_pkup.wav", | ||
214 | "icons/iconw_rocket", | ||
215 | "Rocket Launcher", | ||
216 | 10, | ||
217 | WEAPON, | ||
218 | ROCKET_LAUNCHER, | ||
219 | SPECIAL_SFX_ROTATE | ||
220 | }, | ||
221 | { | ||
222 | "weapon_lightning", | ||
223 | "models/weapons2/lightning/lightning.md3", | ||
224 | "", | ||
225 | "sound/misc/w_pkup.wav", | ||
226 | "icons/iconw_lightning", | ||
227 | "Lightning Gun", | ||
228 | 100, | ||
229 | WEAPON, | ||
230 | LIGHTNING, | ||
231 | SPECIAL_SFX_ROTATE | ||
232 | }, | ||
233 | { | ||
234 | "weapon_railgun", | ||
235 | "models/weapons2/railgun/railgun.md3", | ||
236 | "", | ||
237 | "sound/misc/w_pkup.wav", | ||
238 | "icons/iconw_railgun", | ||
239 | "Railgun", | ||
240 | 10, | ||
241 | WEAPON, | ||
242 | RAILGUN, | ||
243 | SPECIAL_SFX_ROTATE | ||
244 | }, | ||
245 | { | ||
246 | "weapon_plasmagun", | ||
247 | "models/weapons2/plasma/plasma.md3", | ||
248 | "", | ||
249 | "sound/misc/w_pkup.wav", | ||
250 | "icons/iconw_plasma", | ||
251 | "Plasma Gun", | ||
252 | 50, | ||
253 | WEAPON, | ||
254 | PLASMAGUN, | ||
255 | SPECIAL_SFX_ROTATE | ||
256 | }, | ||
257 | { | ||
258 | "weapon_bfg", | ||
259 | "models/weapons2/bfg/bfg.md3", | ||
260 | "", | ||
261 | "sound/misc/w_pkup.wav", | ||
262 | "icons/iconw_bfg", | ||
263 | "BFG10K", | ||
264 | 20, | ||
265 | WEAPON, | ||
266 | BFG, | ||
267 | SPECIAL_SFX_ROTATE | ||
268 | }, | ||
269 | { | ||
270 | "weapon_grapplinghook", | ||
271 | "models/weapons2/grapple/grapple.md3", | ||
272 | "", | ||
273 | "sound/misc/w_pkup.wav", | ||
274 | "icons/iconw_grapple", | ||
275 | "Grappling Hook", | ||
276 | 0, | ||
277 | WEAPON, | ||
278 | GRAPPLING_HOOK, | ||
279 | SPECIAL_SFX_ROTATE | ||
280 | }, | ||
281 | { | ||
282 | 0 | ||
283 | } | ||
284 | |||
285 | }; | ||
286 | |||
287 | |||
288 | /*! | ||
289 | */ | ||
290 | const SItemElement * getItemElement ( const stringc& key ) | ||
291 | { | ||
292 | const SItemElement *item = Quake3ItemElement; | ||
293 | |||
294 | while ( item->key ) | ||
295 | { | ||
296 | if ( 0 == strcmp ( key.c_str(), item->key ) ) | ||
297 | return item; | ||
298 | item += 1; | ||
299 | } | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | /*! | ||
304 | Quake3 Model Factory. | ||
305 | Takes the mesh buffers and creates scenenodes for their associated shaders | ||
306 | */ | ||
307 | void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, | ||
308 | IrrlichtDevice *device, | ||
309 | IQ3LevelMesh* mesh, | ||
310 | eQ3MeshIndex meshIndex, | ||
311 | ISceneNode *parent, | ||
312 | IMetaTriangleSelector *meta, | ||
313 | bool showShaderName ) | ||
314 | { | ||
315 | if ( 0 == mesh || 0 == device ) | ||
316 | return; | ||
317 | |||
318 | IMeshSceneNode* node = 0; | ||
319 | ISceneManager* smgr = device->getSceneManager(); | ||
320 | ITriangleSelector * selector = 0; | ||
321 | |||
322 | // the additional mesh can be quite huge and is unoptimized | ||
323 | // Save to cast to SMesh | ||
324 | SMesh * additional_mesh = (SMesh*) mesh->getMesh ( meshIndex ); | ||
325 | if ( 0 == additional_mesh || additional_mesh->getMeshBufferCount() == 0) | ||
326 | return; | ||
327 | |||
328 | char buf[128]; | ||
329 | if ( loadParam.verbose > 0 ) | ||
330 | { | ||
331 | loadParam.startTime = device->getTimer()->getRealTime(); | ||
332 | if ( loadParam.verbose > 1 ) | ||
333 | { | ||
334 | snprintf(buf, 128, "q3shaderfactory start" ); | ||
335 | device->getLogger()->log( buf, ELL_INFORMATION); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | IGUIFont *font = 0; | ||
340 | if ( showShaderName ) | ||
341 | font = device->getGUIEnvironment()->getFont("fontlucida.png"); | ||
342 | |||
343 | IVideoDriver *driver = device->getVideoDriver(); | ||
344 | |||
345 | // create helper textures | ||
346 | if ( 1 ) | ||
347 | { | ||
348 | tTexArray tex; | ||
349 | u32 pos = 0; | ||
350 | getTextures ( tex, "$redimage $blueimage $whiteimage $checkerimage", pos, | ||
351 | device->getFileSystem(), driver ); | ||
352 | } | ||
353 | |||
354 | s32 sceneNodeID = 0; | ||
355 | for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount (); ++i ) | ||
356 | { | ||
357 | IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer ( i ); | ||
358 | const SMaterial &material = meshBuffer->getMaterial(); | ||
359 | |||
360 | //! The ShaderIndex is stored in the second material parameter | ||
361 | s32 shaderIndex = (s32) material.MaterialTypeParam2; | ||
362 | |||
363 | // the meshbuffer can be rendered without additional support, or it has no shader | ||
364 | IShader *shader = (IShader *) mesh->getShader ( shaderIndex ); | ||
365 | |||
366 | // no shader, or mapped to existing material | ||
367 | if ( 0 == shader ) | ||
368 | { | ||
369 | |||
370 | #if 1 | ||
371 | // clone mesh | ||
372 | SMesh * m = new SMesh (); | ||
373 | m->addMeshBuffer ( meshBuffer ); | ||
374 | SMaterial &mat = m->getMeshBuffer( 0 )->getMaterial(); | ||
375 | if ( mat.getTexture( 0 ) == 0 ) | ||
376 | mat.setTexture ( 0, driver->getTexture ( "$blueimage" ) ); | ||
377 | if ( mat.getTexture( 1 ) == 0 ) | ||
378 | mat.setTexture ( 1, driver->getTexture ( "$redimage" ) ); | ||
379 | |||
380 | IMesh * store = smgr->getMeshManipulator ()->createMeshWith2TCoords ( m ); | ||
381 | m->drop(); | ||
382 | |||
383 | node = smgr->addMeshSceneNode ( store, parent, sceneNodeID ); | ||
384 | node->setAutomaticCulling ( scene::EAC_OFF ); | ||
385 | store->drop (); | ||
386 | sceneNodeID += 1; | ||
387 | #endif | ||
388 | } | ||
389 | else if ( 1 ) | ||
390 | { | ||
391 | /* | ||
392 | stringc s; | ||
393 | dumpShader ( s, shader ); | ||
394 | printf ( s.c_str () ); | ||
395 | */ | ||
396 | // create sceneNode | ||
397 | node = smgr->addQuake3SceneNode ( meshBuffer, shader, parent, sceneNodeID ); | ||
398 | node->setAutomaticCulling ( scene::EAC_FRUSTUM_BOX ); | ||
399 | sceneNodeID += 1; | ||
400 | } | ||
401 | |||
402 | // show Debug Shader Name | ||
403 | if ( showShaderName && node ) | ||
404 | { | ||
405 | swprintf ( (wchar_t*) buf, 64, L"%hs:%d", node->getName(),node->getID() ); | ||
406 | smgr->addBillboardTextSceneNode( | ||
407 | font, | ||
408 | (wchar_t*) buf, | ||
409 | node, | ||
410 | dimension2d<f32>(80.0f, 8.0f), | ||
411 | vector3df(0, 10, 0), | ||
412 | sceneNodeID); | ||
413 | sceneNodeID += 1; | ||
414 | } | ||
415 | |||
416 | // create Portal Rendertargets | ||
417 | if ( shader ) | ||
418 | { | ||
419 | const SVarGroup *group = shader->getGroup(1); | ||
420 | if ( group->isDefined( "surfaceparm", "portal" ) ) | ||
421 | { | ||
422 | } | ||
423 | |||
424 | } | ||
425 | |||
426 | |||
427 | // add collision | ||
428 | // find out if shader is marked as nonsolid | ||
429 | u8 doCreate = meta !=0 ; | ||
430 | |||
431 | if ( shader ) | ||
432 | { | ||
433 | const SVarGroup *group = shader->getGroup(1); | ||
434 | if ( group->isDefined( "surfaceparm", "trans" ) | ||
435 | // || group->isDefined( "surfaceparm", "sky" ) | ||
436 | // || group->isDefined( "surfaceparm", "nonsolid" ) | ||
437 | ) | ||
438 | { | ||
439 | if ( !group->isDefined( "surfaceparm", "metalsteps" ) ) | ||
440 | { | ||
441 | doCreate = 0; | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | if ( doCreate ) | ||
447 | { | ||
448 | IMesh *m = 0; | ||
449 | |||
450 | //! controls if triangles are modified by the scenenode during runtime | ||
451 | bool takeOriginal = true; | ||
452 | |||
453 | if ( takeOriginal ) | ||
454 | { | ||
455 | m = new SMesh (); | ||
456 | ((SMesh*) m )->addMeshBuffer (meshBuffer); | ||
457 | } | ||
458 | else | ||
459 | { | ||
460 | m = node->getMesh(); | ||
461 | } | ||
462 | |||
463 | //selector = smgr->createOctreeTriangleSelector ( m, 0, 128 ); | ||
464 | selector = smgr->createTriangleSelector ( m, 0 ); | ||
465 | meta->addTriangleSelector ( selector ); | ||
466 | selector->drop (); | ||
467 | |||
468 | if ( takeOriginal ) | ||
469 | { | ||
470 | delete m; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | } | ||
475 | |||
476 | #if 0 | ||
477 | if ( meta ) | ||
478 | { | ||
479 | selector = smgr->createOctreeTriangleSelector ( additional_mesh, 0 ); | ||
480 | meta->addTriangleSelector ( selector ); | ||
481 | selector->drop (); | ||
482 | } | ||
483 | #endif | ||
484 | |||
485 | if ( loadParam.verbose > 0 ) | ||
486 | { | ||
487 | loadParam.endTime = device->getTimer()->getRealTime (); | ||
488 | snprintf(buf, 128, "q3shaderfactory needed %04d ms to create %d shader nodes", | ||
489 | loadParam.endTime - loadParam.startTime, | ||
490 | sceneNodeID | ||
491 | ); | ||
492 | device->getLogger()->log(buf, ELL_INFORMATION); | ||
493 | } | ||
494 | |||
495 | } | ||
496 | |||
497 | |||
498 | /*! | ||
499 | create Items from Entity | ||
500 | */ | ||
501 | void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, | ||
502 | IrrlichtDevice *device, | ||
503 | IQ3LevelMesh* masterMesh, | ||
504 | ISceneNode *parent, | ||
505 | bool showShaderName | ||
506 | ) | ||
507 | { | ||
508 | if ( 0 == masterMesh ) | ||
509 | return; | ||
510 | |||
511 | tQ3EntityList &entity = masterMesh->getEntityList (); | ||
512 | ISceneManager* smgr = device->getSceneManager(); | ||
513 | |||
514 | |||
515 | char buf[128]; | ||
516 | const SVarGroup *group; | ||
517 | IEntity search; | ||
518 | s32 index; | ||
519 | s32 lastIndex; | ||
520 | |||
521 | /* | ||
522 | stringc s; | ||
523 | FILE *f = 0; | ||
524 | f = fopen ( "entity.txt", "wb" ); | ||
525 | for ( index = 0; (u32) index < entityList.size (); ++index ) | ||
526 | { | ||
527 | const IEntity *entity = &entityList[ index ]; | ||
528 | s = entity->name; | ||
529 | dumpShader ( s, entity ); | ||
530 | fwrite ( s.c_str(), 1, s.size(), f ); | ||
531 | } | ||
532 | fclose ( f ); | ||
533 | */ | ||
534 | IAnimatedMeshMD3* model; | ||
535 | SMD3Mesh * mesh; | ||
536 | const SMD3MeshBuffer *meshBuffer; | ||
537 | IMeshSceneNode* node; | ||
538 | ISceneNodeAnimator* anim; | ||
539 | const IShader *shader; | ||
540 | u32 pos; | ||
541 | vector3df p; | ||
542 | u32 nodeCount = 0; | ||
543 | tTexArray textureArray; | ||
544 | |||
545 | IGUIFont *font = 0; | ||
546 | if ( showShaderName ) | ||
547 | font = device->getGUIEnvironment()->getFont("fontlucida.png"); | ||
548 | |||
549 | const SItemElement *itemElement; | ||
550 | |||
551 | // walk list | ||
552 | for ( index = 0; (u32) index < entity.size(); ++index ) | ||
553 | { | ||
554 | itemElement = getItemElement ( entity[index].name ); | ||
555 | if ( 0 == itemElement ) | ||
556 | continue; | ||
557 | |||
558 | pos = 0; | ||
559 | p = getAsVector3df ( entity[index].getGroup(1)->get ( "origin" ), pos ); | ||
560 | |||
561 | nodeCount += 1; | ||
562 | for ( u32 g = 0; g < 2; ++g ) | ||
563 | { | ||
564 | if ( 0 == itemElement->model[g] || itemElement->model[g][0] == 0 ) | ||
565 | continue; | ||
566 | model = (IAnimatedMeshMD3*) smgr->getMesh( itemElement->model[g] ); | ||
567 | if ( 0 == model ) | ||
568 | continue; | ||
569 | |||
570 | mesh = model->getOriginalMesh(); | ||
571 | for ( u32 j = 0; j != mesh->Buffer.size (); ++j ) | ||
572 | { | ||
573 | meshBuffer = mesh->Buffer[j]; | ||
574 | if ( 0 == meshBuffer ) | ||
575 | continue; | ||
576 | |||
577 | shader = masterMesh->getShader ( meshBuffer->Shader.c_str(), false ); | ||
578 | IMeshBuffer *final = model->getMesh(0)->getMeshBuffer(j); | ||
579 | if ( shader ) | ||
580 | { | ||
581 | //!TODO: Hack don't modify the vertexbuffer. make it better;-) | ||
582 | final->getMaterial().ColorMask = 0; | ||
583 | node = smgr->addQuake3SceneNode ( final, shader, parent ); | ||
584 | final->getMaterial().ColorMask = 15; | ||
585 | } | ||
586 | else | ||
587 | { | ||
588 | // clone mesh | ||
589 | SMesh * m = new SMesh (); | ||
590 | m->addMeshBuffer ( final ); | ||
591 | node = smgr->addMeshSceneNode ( m, parent ); | ||
592 | m->drop(); | ||
593 | } | ||
594 | |||
595 | if ( 0 == node ) | ||
596 | { | ||
597 | snprintf ( buf, 128, "q3ModelFactory shader %s failed", meshBuffer->Shader.c_str() ); | ||
598 | device->getLogger()->log ( buf ); | ||
599 | continue; | ||
600 | } | ||
601 | |||
602 | // node was maybe centered by shaderscenenode | ||
603 | node->setPosition ( p ); | ||
604 | node->setName ( meshBuffer->Shader ); | ||
605 | node->setAutomaticCulling ( scene::EAC_BOX ); | ||
606 | |||
607 | // add special effects to node | ||
608 | if ( itemElement->special & SPECIAL_SFX_ROTATE || | ||
609 | (g == 0 && itemElement->special & SPECIAL_SFX_ROTATE_1) | ||
610 | ) | ||
611 | { | ||
612 | anim = smgr->createRotationAnimator ( vector3df ( 0.f, | ||
613 | 2.f, 0.f ) ); | ||
614 | node->addAnimator ( anim ); | ||
615 | anim->drop (); | ||
616 | } | ||
617 | |||
618 | if ( itemElement->special & SPECIAL_SFX_BOUNCE ) | ||
619 | { | ||
620 | //anim = smgr->createFlyStraightAnimator ( | ||
621 | // p, p + vector3df ( 0.f, 60.f, 0.f ), 1000, true, true ); | ||
622 | anim = smgr->createFlyCircleAnimator ( | ||
623 | p + vector3df( 0.f, 20.f, 0.f ), | ||
624 | 20.f, | ||
625 | 0.005f, | ||
626 | vector3df ( 1.f, 0.f, 0.f ), | ||
627 | core::fract ( nodeCount * 0.05f ), | ||
628 | 1.f | ||
629 | ); | ||
630 | node->addAnimator ( anim ); | ||
631 | anim->drop (); | ||
632 | } | ||
633 | } | ||
634 | } | ||
635 | // show name | ||
636 | if ( showShaderName ) | ||
637 | { | ||
638 | swprintf ( (wchar_t*) buf, sizeof(buf) / 2, L"%hs", itemElement->key ); | ||
639 | smgr->addBillboardTextSceneNode( | ||
640 | font, | ||
641 | (wchar_t*) buf, | ||
642 | parent, | ||
643 | dimension2d<f32>(80.0f, 8.0f), | ||
644 | p + vector3df(0, 30, 0), | ||
645 | 0); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | // music | ||
650 | search.name = "worldspawn"; | ||
651 | index = entity.binary_search_multi ( search, lastIndex ); | ||
652 | |||
653 | if ( index >= 0 ) | ||
654 | { | ||
655 | group = entity[ index ].getGroup(1); | ||
656 | background_music ( group->get ( "music" ).c_str () ); | ||
657 | } | ||
658 | |||
659 | // music | ||
660 | search.name = "worldspawn"; | ||
661 | index = entity.binary_search_multi ( search, lastIndex ); | ||
662 | |||
663 | if ( index >= 0 ) | ||
664 | { | ||
665 | group = entity[ index ].getGroup(1); | ||
666 | background_music ( group->get ( "music" ).c_str () ); | ||
667 | } | ||
668 | |||
669 | //IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); | ||
670 | //IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); | ||
671 | |||
672 | } | ||
673 | |||
674 | /*! | ||
675 | so we need a good starting Position in the level. | ||
676 | we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" | ||
677 | */ | ||
678 | s32 Q3StartPosition ( IQ3LevelMesh* mesh, | ||
679 | ICameraSceneNode* camera, | ||
680 | s32 startposIndex, | ||
681 | const vector3df &translation | ||
682 | ) | ||
683 | { | ||
684 | if ( 0 == mesh ) | ||
685 | return 0; | ||
686 | |||
687 | tQ3EntityList &entityList = mesh->getEntityList (); | ||
688 | |||
689 | IEntity search; | ||
690 | search.name = "info_player_start"; // "info_player_deathmatch"; | ||
691 | |||
692 | // find all entities in the multi-list | ||
693 | s32 lastIndex; | ||
694 | s32 index = entityList.binary_search_multi ( search, lastIndex ); | ||
695 | |||
696 | if ( index < 0 ) | ||
697 | { | ||
698 | search.name = "info_player_deathmatch"; | ||
699 | index = entityList.binary_search_multi ( search, lastIndex ); | ||
700 | } | ||
701 | |||
702 | if ( index < 0 ) | ||
703 | return 0; | ||
704 | |||
705 | index += core::clamp ( startposIndex, 0, lastIndex - index ); | ||
706 | |||
707 | u32 parsepos; | ||
708 | |||
709 | const SVarGroup *group; | ||
710 | group = entityList[ index ].getGroup(1); | ||
711 | |||
712 | parsepos = 0; | ||
713 | vector3df pos = getAsVector3df ( group->get ( "origin" ), parsepos ); | ||
714 | pos += translation; | ||
715 | |||
716 | parsepos = 0; | ||
717 | f32 angle = getAsFloat ( group->get ( "angle"), parsepos ); | ||
718 | |||
719 | vector3df target ( 0.f, 0.f, 1.f ); | ||
720 | target.rotateXZBy ( angle - 90.f, vector3df () ); | ||
721 | |||
722 | if ( camera ) | ||
723 | { | ||
724 | camera->setPosition ( pos ); | ||
725 | camera->setTarget ( pos + target ); | ||
726 | //! New. FPSCamera and animators catches reset on animate 0 | ||
727 | camera->OnAnimate ( 0 ); | ||
728 | } | ||
729 | return lastIndex - index + 1; | ||
730 | } | ||
731 | |||
732 | |||
733 | /*! | ||
734 | gets a accumulated force on a given surface | ||
735 | */ | ||
736 | vector3df getGravity ( const c8 * surface ) | ||
737 | { | ||
738 | if ( 0 == strcmp ( surface, "earth" ) ) return vector3df ( 0.f, -90.f, 0.f ); | ||
739 | if ( 0 == strcmp ( surface, "moon" ) ) return vector3df ( 0.f, -6.f / 100.f, 0.f ); | ||
740 | if ( 0 == strcmp ( surface, "water" ) ) return vector3df ( 0.1f / 100.f, -2.f / 100.f, 0.f ); | ||
741 | if ( 0 == strcmp ( surface, "ice" ) ) return vector3df ( 0.2f / 100.f, -9.f / 100.f, 0.3f / 100.f ); | ||
742 | |||
743 | return vector3df ( 0.f, 0.f, 0.f ); | ||
744 | } | ||
745 | |||
746 | |||
747 | |||
748 | /* | ||
749 | Dynamically load the Irrlicht Library | ||
750 | */ | ||
751 | |||
752 | #if defined(_IRR_WINDOWS_API_) | ||
753 | #ifdef _MSC_VER | ||
754 | #pragma comment(lib, "Irrlicht.lib") | ||
755 | #endif | ||
756 | |||
757 | #include <windows.h> | ||
758 | |||
759 | funcptr_createDevice load_createDevice ( const c8 * filename) | ||
760 | { | ||
761 | return (funcptr_createDevice) GetProcAddress ( LoadLibrary ( filename ), "createDevice" ); | ||
762 | } | ||
763 | |||
764 | funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) | ||
765 | { | ||
766 | return (funcptr_createDeviceEx) GetProcAddress ( LoadLibrary ( filename ), "createDeviceEx" ); | ||
767 | } | ||
768 | |||
769 | #else | ||
770 | |||
771 | // TODO: Dynamic Loading for other os | ||
772 | funcptr_createDevice load_createDevice ( const c8 * filename) | ||
773 | { | ||
774 | return createDevice; | ||
775 | } | ||
776 | |||
777 | funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) | ||
778 | { | ||
779 | return createDeviceEx; | ||
780 | } | ||
781 | |||
782 | #endif | ||
783 | |||
784 | /* | ||
785 | get the current collision response camera animator | ||
786 | */ | ||
787 | ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ) | ||
788 | { | ||
789 | ICameraSceneNode *camera = device->getSceneManager()->getActiveCamera(); | ||
790 | ISceneNodeAnimatorCollisionResponse *a = 0; | ||
791 | |||
792 | list<ISceneNodeAnimator*>::ConstIterator it = camera->getAnimators().begin(); | ||
793 | for (; it != camera->getAnimators().end(); ++it) | ||
794 | { | ||
795 | a = (ISceneNodeAnimatorCollisionResponse*) (*it); | ||
796 | if ( a->getType() == ESNAT_COLLISION_RESPONSE ) | ||
797 | return a; | ||
798 | } | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | |||
804 | //! internal Animation | ||
805 | void setTimeFire ( TimeFire *t, u32 delta, u32 flags ) | ||
806 | { | ||
807 | t->flags = flags; | ||
808 | t->next = 0; | ||
809 | t->delta = delta; | ||
810 | } | ||
811 | |||
812 | |||
813 | void checkTimeFire ( TimeFire *t, u32 listSize, u32 now ) | ||
814 | { | ||
815 | u32 i; | ||
816 | for ( i = 0; i < listSize; ++i ) | ||
817 | { | ||
818 | if ( now < t[i].next ) | ||
819 | continue; | ||
820 | |||
821 | t[i].next = core::max_ ( now + t[i].delta, t[i].next + t[i].delta ); | ||
822 | t[i].flags |= FIRED; | ||
823 | } | ||
824 | } | ||