q3factory.cpp 18 KB

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