~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to examples/21.Quake3Explorer/q3factory.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

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