IQ3Shader.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. // Copyright (C) 2006-2012 Nikolaus Gebhardt / Thomas Alten
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #ifndef IRR_I_Q3_LEVEL_SHADER_H_INCLUDED
  5. #define IRR_I_Q3_LEVEL_SHADER_H_INCLUDED
  6. #include "irrArray.h"
  7. #include "fast_atof.h"
  8. #include "IFileSystem.h"
  9. #include "IVideoDriver.h"
  10. #include "coreutil.h"
  11. namespace irr
  12. {
  13. namespace scene
  14. {
  15. namespace quake3
  16. {
  17. static core::stringc irrEmptyStringc("");
  18. //! Hold the different Mesh Types used for getMesh
  19. enum eQ3MeshIndex
  20. {
  21. E_Q3_MESH_GEOMETRY = 0,
  22. E_Q3_MESH_ITEMS,
  23. E_Q3_MESH_BILLBOARD,
  24. E_Q3_MESH_FOG,
  25. E_Q3_MESH_UNRESOLVED,
  26. E_Q3_MESH_SIZE
  27. };
  28. /*! used to customize Quake3 BSP Loader
  29. */
  30. struct Q3LevelLoadParameter
  31. {
  32. Q3LevelLoadParameter ()
  33. :defaultLightMapMaterial ( video::EMT_LIGHTMAP_M4 ),
  34. defaultModulate ( video::EMFN_MODULATE_4X ),
  35. defaultFilter ( video::EMF_BILINEAR_FILTER ),
  36. patchTessellation ( 8 ),
  37. verbose ( 0 ),
  38. startTime ( 0 ), endTime ( 0 ),
  39. mergeShaderBuffer ( 1 ),
  40. cleanUnResolvedMeshes ( 1 ),
  41. loadAllShaders ( 0 ),
  42. loadSkyShader ( 0 ),
  43. alpharef ( 1 ),
  44. swapLump ( 0 ),
  45. #ifdef __BIG_ENDIAN__
  46. swapHeader ( 1 )
  47. #else
  48. swapHeader ( 0 )
  49. #endif
  50. {
  51. memcpy ( scriptDir, "scripts\x0", 8 );
  52. }
  53. video::E_MATERIAL_TYPE defaultLightMapMaterial;
  54. video::E_MODULATE_FUNC defaultModulate;
  55. video::E_MATERIAL_FLAG defaultFilter;
  56. s32 patchTessellation;
  57. s32 verbose;
  58. u32 startTime;
  59. u32 endTime;
  60. s32 mergeShaderBuffer;
  61. s32 cleanUnResolvedMeshes;
  62. s32 loadAllShaders;
  63. s32 loadSkyShader;
  64. s32 alpharef;
  65. s32 swapLump;
  66. s32 swapHeader;
  67. c8 scriptDir [ 64 ];
  68. };
  69. // some useful typedefs
  70. typedef core::array< core::stringc > tStringList;
  71. typedef core::array< video::ITexture* > tTexArray;
  72. // string helper.. TODO: move to generic files
  73. inline s16 isEqual ( const core::stringc &string, u32 &pos, const c8 * const list[], u16 listSize )
  74. {
  75. const char * in = string.c_str () + pos;
  76. for ( u16 i = 0; i != listSize; ++i )
  77. {
  78. if (string.size() < pos)
  79. return -2;
  80. u32 len = (u32) strlen ( list[i] );
  81. if (string.size() < pos+len)
  82. continue;
  83. if ( in [len] != 0 && in [len] != ' ' )
  84. continue;
  85. if ( strncmp ( in, list[i], len ) )
  86. continue;
  87. pos += len + 1;
  88. return (s16) i;
  89. }
  90. return -2;
  91. }
  92. inline f32 getAsFloat ( const core::stringc &string, u32 &pos )
  93. {
  94. const char * in = string.c_str () + pos;
  95. f32 value = 0.f;
  96. pos += (u32) ( core::fast_atof_move ( in, value ) - in ) + 1;
  97. return value;
  98. }
  99. //! get a quake3 vector translated to irrlicht position (x,-z,y )
  100. inline core::vector3df getAsVector3df ( const core::stringc &string, u32 &pos )
  101. {
  102. core::vector3df v;
  103. v.X = getAsFloat ( string, pos );
  104. v.Z = getAsFloat ( string, pos );
  105. v.Y = getAsFloat ( string, pos );
  106. return v;
  107. }
  108. /*
  109. extract substrings
  110. */
  111. inline void getAsStringList ( tStringList &list, s32 max, const core::stringc &string, u32 &startPos )
  112. {
  113. list.clear ();
  114. s32 finish = 0;
  115. s32 endPos;
  116. do
  117. {
  118. endPos = string.findNext ( ' ', startPos );
  119. if ( endPos == -1 )
  120. {
  121. finish = 1;
  122. endPos = string.size();
  123. }
  124. list.push_back ( string.subString ( startPos, endPos - startPos ) );
  125. startPos = endPos + 1;
  126. if ( list.size() >= (u32) max )
  127. finish = 1;
  128. } while ( !finish );
  129. }
  130. //! A blend function for a q3 shader.
  131. struct SBlendFunc
  132. {
  133. SBlendFunc ( video::E_MODULATE_FUNC mod )
  134. : type ( video::EMT_SOLID ), modulate ( mod ),
  135. param0( 0.f ),
  136. isTransparent ( 0 ) {}
  137. video::E_MATERIAL_TYPE type;
  138. video::E_MODULATE_FUNC modulate;
  139. f32 param0;
  140. u32 isTransparent;
  141. };
  142. // parses the content of Variable cull
  143. inline bool getCullingFunction ( const core::stringc &cull )
  144. {
  145. if ( cull.size() == 0 )
  146. return true;
  147. bool ret = true;
  148. static const c8 * funclist[] = { "none", "disable", "twosided" };
  149. u32 pos = 0;
  150. switch ( isEqual ( cull, pos, funclist, 3 ) )
  151. {
  152. case 0:
  153. case 1:
  154. case 2:
  155. ret = false;
  156. break;
  157. }
  158. return ret;
  159. }
  160. // parses the content of Variable depthfunc
  161. // return a z-test
  162. inline u8 getDepthFunction ( const core::stringc &string )
  163. {
  164. u8 ret = video::ECFN_LESSEQUAL;
  165. if ( string.size() == 0 )
  166. return ret;
  167. static const c8 * funclist[] = { "lequal","equal" };
  168. u32 pos = 0;
  169. switch ( isEqual ( string, pos, funclist, 2 ) )
  170. {
  171. case 0:
  172. ret = video::ECFN_LESSEQUAL;
  173. break;
  174. case 1:
  175. ret = video::ECFN_EQUAL;
  176. break;
  177. }
  178. return ret;
  179. }
  180. /*!
  181. parses the content of Variable blendfunc,alphafunc
  182. it also make a hint for rendering as transparent or solid node.
  183. we assume a typical quake scene would look like this..
  184. 1) Big Static Mesh ( solid )
  185. 2) static scene item ( may use transparency ) but rendered in the solid pass
  186. 3) additional transparency item in the transparent pass
  187. it's not 100% accurate! it just empirical..
  188. */
  189. inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc )
  190. {
  191. if ( string.size() == 0 )
  192. return;
  193. // maps to E_BLEND_FACTOR
  194. static const c8 * funclist[] =
  195. {
  196. "gl_zero",
  197. "gl_one",
  198. "gl_dst_color",
  199. "gl_one_minus_dst_color",
  200. "gl_src_color",
  201. "gl_one_minus_src_color",
  202. "gl_src_alpha",
  203. "gl_one_minus_src_alpha",
  204. "gl_dst_alpha",
  205. "gl_one_minus_dst_alpha",
  206. "gl_src_alpha_sat",
  207. "add",
  208. "filter",
  209. "blend",
  210. "ge128",
  211. "gt0",
  212. };
  213. u32 pos = 0;
  214. s32 srcFact = isEqual ( string, pos, funclist, 16 );
  215. if ( srcFact < 0 )
  216. return;
  217. u32 resolved = 0;
  218. s32 dstFact = isEqual ( string, pos, funclist, 16 );
  219. switch ( srcFact )
  220. {
  221. case video::EBF_ZERO:
  222. switch ( dstFact )
  223. {
  224. // gl_zero gl_src_color == gl_dst_color gl_zero
  225. case video::EBF_SRC_COLOR:
  226. blendfunc.type = video::EMT_ONETEXTURE_BLEND;
  227. blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate );
  228. blendfunc.isTransparent = 1;
  229. resolved = 1;
  230. break;
  231. } break;
  232. case video::EBF_ONE:
  233. switch ( dstFact )
  234. {
  235. // gl_one gl_zero
  236. case video::EBF_ZERO:
  237. blendfunc.type = video::EMT_SOLID;
  238. blendfunc.isTransparent = 0;
  239. resolved = 1;
  240. break;
  241. // gl_one gl_one
  242. case video::EBF_ONE:
  243. blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR;
  244. blendfunc.isTransparent = 1;
  245. resolved = 1;
  246. break;
  247. } break;
  248. case video::EBF_SRC_ALPHA:
  249. switch ( dstFact )
  250. {
  251. // gl_src_alpha gl_one_minus_src_alpha
  252. case video::EBF_ONE_MINUS_SRC_ALPHA:
  253. blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
  254. blendfunc.param0 = 1.f/255.f;
  255. blendfunc.isTransparent = 1;
  256. resolved = 1;
  257. break;
  258. } break;
  259. case 11:
  260. // add
  261. blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR;
  262. blendfunc.isTransparent = 1;
  263. resolved = 1;
  264. break;
  265. case 12:
  266. // filter = gl_dst_color gl_zero or gl_zero gl_src_color
  267. blendfunc.type = video::EMT_ONETEXTURE_BLEND;
  268. blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate );
  269. blendfunc.isTransparent = 1;
  270. resolved = 1;
  271. break;
  272. case 13:
  273. // blend = gl_src_alpha gl_one_minus_src_alpha
  274. blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
  275. blendfunc.param0 = 1.f/255.f;
  276. blendfunc.isTransparent = 1;
  277. resolved = 1;
  278. break;
  279. case 14:
  280. // alphafunc ge128
  281. blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
  282. blendfunc.param0 = 0.5f;
  283. blendfunc.isTransparent = 1;
  284. resolved = 1;
  285. break;
  286. case 15:
  287. // alphafunc gt0
  288. blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
  289. blendfunc.param0 = 1.f / 255.f;
  290. blendfunc.isTransparent = 1;
  291. resolved = 1;
  292. break;
  293. }
  294. // use the generic blender
  295. if ( 0 == resolved )
  296. {
  297. blendfunc.type = video::EMT_ONETEXTURE_BLEND;
  298. blendfunc.param0 = video::pack_textureBlendFunc (
  299. (video::E_BLEND_FACTOR) srcFact,
  300. (video::E_BLEND_FACTOR) dstFact,
  301. blendfunc.modulate);
  302. blendfunc.isTransparent = 1;
  303. }
  304. }
  305. // random noise [-1;1]
  306. struct Noiser
  307. {
  308. static f32 get ()
  309. {
  310. static u32 RandomSeed = 0x69666966;
  311. RandomSeed = (RandomSeed * 3631 + 1);
  312. f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f;
  313. return value;
  314. }
  315. };
  316. enum eQ3ModifierFunction
  317. {
  318. TCMOD = 0,
  319. DEFORMVERTEXES = 1,
  320. RGBGEN = 2,
  321. TCGEN = 3,
  322. MAP = 4,
  323. ALPHAGEN = 5,
  324. FUNCTION2 = 0x10,
  325. SCROLL = FUNCTION2 + 1,
  326. SCALE = FUNCTION2 + 2,
  327. ROTATE = FUNCTION2 + 3,
  328. STRETCH = FUNCTION2 + 4,
  329. TURBULENCE = FUNCTION2 + 5,
  330. WAVE = FUNCTION2 + 6,
  331. IDENTITY = FUNCTION2 + 7,
  332. VERTEX = FUNCTION2 + 8,
  333. TEXTURE = FUNCTION2 + 9,
  334. LIGHTMAP = FUNCTION2 + 10,
  335. ENVIRONMENT = FUNCTION2 + 11,
  336. DOLLAR_LIGHTMAP = FUNCTION2 + 12,
  337. BULGE = FUNCTION2 + 13,
  338. AUTOSPRITE = FUNCTION2 + 14,
  339. AUTOSPRITE2 = FUNCTION2 + 15,
  340. TRANSFORM = FUNCTION2 + 16,
  341. EXACTVERTEX = FUNCTION2 + 17,
  342. CONSTANT = FUNCTION2 + 18,
  343. LIGHTINGSPECULAR = FUNCTION2 + 19,
  344. MOVE = FUNCTION2 + 20,
  345. NORMAL = FUNCTION2 + 21,
  346. IDENTITYLIGHTING = FUNCTION2 + 22,
  347. WAVE_MODIFIER_FUNCTION = 0x30,
  348. SINUS = WAVE_MODIFIER_FUNCTION + 1,
  349. COSINUS = WAVE_MODIFIER_FUNCTION + 2,
  350. SQUARE = WAVE_MODIFIER_FUNCTION + 3,
  351. TRIANGLE = WAVE_MODIFIER_FUNCTION + 4,
  352. SAWTOOTH = WAVE_MODIFIER_FUNCTION + 5,
  353. SAWTOOTH_INVERSE = WAVE_MODIFIER_FUNCTION + 6,
  354. NOISE = WAVE_MODIFIER_FUNCTION + 7,
  355. UNKNOWN = -2
  356. };
  357. struct SModifierFunction
  358. {
  359. SModifierFunction ()
  360. : masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ),
  361. tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ),
  362. base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ),
  363. wave ( 1 ),
  364. x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {}
  365. // "tcmod","deformvertexes","rgbgen", "tcgen"
  366. eQ3ModifierFunction masterfunc0;
  367. // depends
  368. eQ3ModifierFunction masterfunc1;
  369. // depends
  370. eQ3ModifierFunction func;
  371. eQ3ModifierFunction tcgen;
  372. eQ3ModifierFunction rgbgen;
  373. eQ3ModifierFunction alphagen;
  374. union
  375. {
  376. f32 base;
  377. f32 bulgewidth;
  378. };
  379. union
  380. {
  381. f32 amp;
  382. f32 bulgeheight;
  383. };
  384. f32 phase;
  385. union
  386. {
  387. f32 frequency;
  388. f32 bulgespeed;
  389. };
  390. union
  391. {
  392. f32 wave;
  393. f32 div;
  394. };
  395. f32 x;
  396. f32 y;
  397. f32 z;
  398. u32 count;
  399. f32 evaluate ( f32 dt ) const
  400. {
  401. // phase in 0 and 1..
  402. f32 x = core::fract( (dt + phase ) * frequency );
  403. f32 y = 0.f;
  404. switch ( func )
  405. {
  406. case SINUS:
  407. y = sinf ( x * core::PI * 2.f );
  408. break;
  409. case COSINUS:
  410. y = cosf ( x * core::PI * 2.f );
  411. break;
  412. case SQUARE:
  413. y = x < 0.5f ? 1.f : -1.f;
  414. break;
  415. case TRIANGLE:
  416. y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f;
  417. break;
  418. case SAWTOOTH:
  419. y = x;
  420. break;
  421. case SAWTOOTH_INVERSE:
  422. y = 1.f - x;
  423. break;
  424. case NOISE:
  425. y = Noiser::get();
  426. break;
  427. default:
  428. break;
  429. }
  430. return base + ( y * amp );
  431. }
  432. };
  433. inline core::vector3df getMD3Normal ( u32 i, u32 j )
  434. {
  435. const f32 lng = i * 2.0f * core::PI / 255.0f;
  436. const f32 lat = j * 2.0f * core::PI / 255.0f;
  437. return core::vector3df(cosf ( lat ) * sinf ( lng ),
  438. sinf ( lat ) * sinf ( lng ),
  439. cosf ( lng ));
  440. }
  441. //
  442. inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos )
  443. {
  444. if ( string.size() == 0 )
  445. return;
  446. static const c8 * funclist[] =
  447. {
  448. "sin","cos","square",
  449. "triangle", "sawtooth","inversesawtooth", "noise"
  450. };
  451. fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 );
  452. fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1);
  453. fill.base = getAsFloat ( string, pos );
  454. fill.amp = getAsFloat ( string, pos );
  455. fill.phase = getAsFloat ( string, pos );
  456. fill.frequency = getAsFloat ( string, pos );
  457. }
  458. // name = "a b c .."
  459. struct SVariable
  460. {
  461. core::stringc name;
  462. core::stringc content;
  463. SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {}
  464. virtual ~SVariable () {}
  465. void clear ()
  466. {
  467. name = "";
  468. content = "";
  469. }
  470. s32 isValid () const
  471. {
  472. return name.size();
  473. }
  474. bool operator == ( const SVariable &other ) const
  475. {
  476. return 0 == strcmp ( name.c_str(), other.name.c_str () );
  477. }
  478. bool operator < ( const SVariable &other ) const
  479. {
  480. return 0 > strcmp ( name.c_str(), other.name.c_str () );
  481. }
  482. };
  483. // string database. "a" = "Hello", "b" = "1234.6"
  484. struct SVarGroup
  485. {
  486. SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); }
  487. virtual ~SVarGroup () {}
  488. u32 isDefined ( const c8 * name, const c8 * content = 0 ) const
  489. {
  490. for ( u32 i = 0; i != Variable.size (); ++i )
  491. {
  492. if ( 0 == strcmp ( Variable[i].name.c_str(), name ) &&
  493. ( 0 == content || strstr ( Variable[i].content.c_str(), content ) )
  494. )
  495. {
  496. return i + 1;
  497. }
  498. }
  499. return 0;
  500. }
  501. // searches for Variable name and returns is content
  502. // if Variable is not found a reference to an Empty String is returned
  503. const core::stringc &get( const c8 * name ) const
  504. {
  505. SVariable search ( name );
  506. s32 index = Variable.linear_search ( search );
  507. if ( index < 0 )
  508. return irrEmptyStringc;
  509. return Variable [ index ].content;
  510. }
  511. // set the Variable name
  512. void set ( const c8 * name, const c8 * content = 0 )
  513. {
  514. u32 index = isDefined ( name, 0 );
  515. if ( 0 == index )
  516. {
  517. Variable.push_back ( SVariable ( name, content ) );
  518. }
  519. else
  520. {
  521. Variable [ index ].content = content;
  522. }
  523. }
  524. core::array < SVariable > Variable;
  525. };
  526. //! holding a group a variable
  527. struct SVarGroupList: public IReferenceCounted
  528. {
  529. SVarGroupList ()
  530. {
  531. VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE );
  532. }
  533. virtual ~SVarGroupList () {}
  534. core::array < SVarGroup > VariableGroup;
  535. };
  536. //! A Parsed Shader Holding Variables ordered in Groups
  537. struct IShader
  538. {
  539. IShader ()
  540. : ID ( 0 ), VarGroup ( 0 ) {}
  541. bool operator == (const IShader &other ) const
  542. {
  543. return 0 == strcmp ( name.c_str(), other.name.c_str () );
  544. //return name == other.name;
  545. }
  546. bool operator < (const IShader &other ) const
  547. {
  548. return strcmp ( name.c_str(), other.name.c_str () ) < 0;
  549. //return name < other.name;
  550. }
  551. u32 getGroupSize () const
  552. {
  553. if ( 0 == VarGroup )
  554. return 0;
  555. return VarGroup->VariableGroup.size ();
  556. }
  557. const SVarGroup * getGroup ( u32 stage ) const
  558. {
  559. if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () )
  560. return 0;
  561. return &VarGroup->VariableGroup [ stage ];
  562. }
  563. // id
  564. s32 ID;
  565. SVarGroupList *VarGroup; // reference
  566. // Shader: shader name ( also first variable in first Vargroup )
  567. // Entity: classname ( variable in Group(1) )
  568. core::stringc name;
  569. };
  570. typedef IShader IEntity;
  571. typedef core::array < IEntity > tQ3EntityList;
  572. /*
  573. dump shader like original layout, regardless of internal data holding
  574. no recursive folding..
  575. */
  576. inline void dumpVarGroup ( core::stringc &dest, const SVarGroup * group, s32 stack )
  577. {
  578. core::stringc buf;
  579. if ( stack > 0 )
  580. {
  581. buf = "";
  582. for (s32 i = 0; i < stack - 1; ++i )
  583. buf += '\t';
  584. buf += "{\n";
  585. dest.append ( buf );
  586. }
  587. for ( u32 g = 0; g != group->Variable.size(); ++g )
  588. {
  589. buf = "";
  590. for (s32 i = 0; i < stack; ++i )
  591. buf += '\t';
  592. buf += group->Variable[g].name;
  593. buf += " ";
  594. buf += group->Variable[g].content;
  595. buf += "\n";
  596. dest.append ( buf );
  597. }
  598. if ( stack > 1 )
  599. {
  600. buf = "";
  601. for (s32 i = 0; i < stack - 1; ++i )
  602. buf += '\t';
  603. buf += "}\n";
  604. dest.append ( buf );
  605. }
  606. }
  607. /*!
  608. dump a Shader or an Entity
  609. */
  610. inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false )
  611. {
  612. if ( 0 == shader )
  613. return dest;
  614. const u32 size = shader->VarGroup->VariableGroup.size ();
  615. for ( u32 i = 0; i != size; ++i )
  616. {
  617. const SVarGroup * group = &shader->VarGroup->VariableGroup[ i ];
  618. dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) );
  619. }
  620. if ( !entity )
  621. {
  622. if ( size <= 1 )
  623. {
  624. dest.append ( "{\n" );
  625. }
  626. dest.append ( "}\n" );
  627. }
  628. return dest;
  629. }
  630. /*
  631. quake3 doesn't care much about tga & jpg
  632. load one or multiple files stored in name started at startPos to the texture array textures
  633. if texture is not loaded 0 will be added ( to find missing textures easier)
  634. */
  635. inline void getTextures(tTexArray &textures,
  636. const core::stringc &name, u32 &startPos,
  637. const io::IFileSystem *fileSystem,
  638. video::IVideoDriver* driver)
  639. {
  640. static const char * const extension[] =
  641. {
  642. ".jpg",
  643. ".jpeg",
  644. ".png",
  645. ".dds",
  646. ".tga",
  647. ".bmp",
  648. ".pcx"
  649. };
  650. tStringList stringList;
  651. getAsStringList(stringList, -1, name, startPos);
  652. textures.clear();
  653. io::path loadFile;
  654. for ( u32 i = 0; i!= stringList.size (); ++i )
  655. {
  656. video::ITexture* texture = 0;
  657. for (u32 g = 0; g != 7; ++g)
  658. {
  659. core::cutFilenameExtension ( loadFile, stringList[i] );
  660. if ( loadFile == "$whiteimage" )
  661. {
  662. texture = driver->getTexture( "$whiteimage" );
  663. if ( 0 == texture )
  664. {
  665. core::dimension2du s ( 2, 2 );
  666. u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF };
  667. video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
  668. texture = driver->addTexture( "$whiteimage", w );
  669. w->drop ();
  670. }
  671. }
  672. else
  673. if ( loadFile == "$redimage" )
  674. {
  675. texture = driver->getTexture( "$redimage" );
  676. if ( 0 == texture )
  677. {
  678. core::dimension2du s ( 2, 2 );
  679. u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 };
  680. video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
  681. texture = driver->addTexture( "$redimage", w );
  682. w->drop ();
  683. }
  684. }
  685. else
  686. if ( loadFile == "$blueimage" )
  687. {
  688. texture = driver->getTexture( "$blueimage" );
  689. if ( 0 == texture )
  690. {
  691. core::dimension2du s ( 2, 2 );
  692. u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF };
  693. video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
  694. texture = driver->addTexture( "$blueimage", w );
  695. w->drop ();
  696. }
  697. }
  698. else
  699. if ( loadFile == "$checkerimage" )
  700. {
  701. texture = driver->getTexture( "$checkerimage" );
  702. if ( 0 == texture )
  703. {
  704. core::dimension2du s ( 2, 2 );
  705. u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF };
  706. video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
  707. texture = driver->addTexture( "$checkerimage", w );
  708. w->drop ();
  709. }
  710. }
  711. else
  712. if ( loadFile == "$lightmap" )
  713. {
  714. texture = 0;
  715. }
  716. else
  717. {
  718. loadFile.append ( extension[g] );
  719. }
  720. texture = driver->findTexture( loadFile );
  721. if ( texture )
  722. break;
  723. if ( fileSystem->existFile ( loadFile ) )
  724. {
  725. texture = driver->getTexture( loadFile );
  726. if ( texture )
  727. break;
  728. texture = 0;
  729. }
  730. }
  731. // take 0 Texture
  732. textures.push_back(texture);
  733. }
  734. }
  735. //! Manages various Quake3 Shader Styles
  736. class IShaderManager : public IReferenceCounted
  737. {
  738. };
  739. } // end namespace quake3
  740. } // end namespace scene
  741. } // end namespace irr
  742. #endif