Irrlicht 3D Engine: IQ3Shader.h Source File

| Irrlicht 3D Engine |

IQ3Shader.h
Go to the documentation of this file.

    00001 // Copyright (C) 2006-2012 Nikolaus Gebhardt / Thomas Alten
    00002 // This file is part of the "Irrlicht Engine".
    00003 // For conditions of distribution and use, see copyright notice in irrlicht.h
    00004
    00005 #ifndef __I_Q3_LEVEL_SHADER_H_INCLUDED__
    00006 #define __I_Q3_LEVEL_SHADER_H_INCLUDED__
    00007
    00008 #include "irrArray.h"
    00009 #include "fast_atof.h"
    00010 #include "IFileSystem.h"
    00011 #include "IVideoDriver.h"
    00012 #include "coreutil.h"
    00013
    00014 namespace irr
    00015 {
    00016 namespace scene
    00017 {
    00018 namespace quake3
    00019 {
    00020
    00021     static core::stringc irrEmptyStringc("");
    00022
    00024     enum eQ3MeshIndex
    00025     {
    00026         E_Q3_MESH_GEOMETRY = 0,
    00027         E_Q3_MESH_ITEMS,
    00028         E_Q3_MESH_BILLBOARD,
    00029         E_Q3_MESH_FOG,
    00030         E_Q3_MESH_UNRESOLVED,
    00031         E_Q3_MESH_SIZE
    00032     };
    00033
    00037     struct Q3LevelLoadParameter
    00038     {
    00039         Q3LevelLoadParameter ()
    00040             :defaultLightMapMaterial ( video::EMT_LIGHTMAP_M4 ),
    00041             defaultModulate ( video::EMFN_MODULATE_4X ),
    00042             defaultFilter ( video::EMF_BILINEAR_FILTER ),
    00043             patchTesselation ( 8 ),
    00044             verbose ( 0 ),
    00045             startTime ( 0 ), endTime ( 0 ),
    00046             mergeShaderBuffer ( 1 ),
    00047             cleanUnResolvedMeshes ( 1 ),
    00048             loadAllShaders ( 0 ),
    00049             loadSkyShader ( 0 ),
    00050             alpharef ( 1 ),
    00051             swapLump ( 0 ),
    00052     #ifdef __BIG_ENDIAN__
    00053             swapHeader ( 1 )
    00054     #else
    00055             swapHeader ( 0 )
    00056     #endif
    00057             {
    00058                 memcpy ( scriptDir, "scripts\x0", 8 );
    00059             }
    00060
    00061         video::E_MATERIAL_TYPE defaultLightMapMaterial;
    00062         video::E_MODULATE_FUNC defaultModulate;
    00063         video::E_MATERIAL_FLAG defaultFilter;
    00064         s32 patchTesselation;
    00065         s32 verbose;
    00066         u32 startTime;
    00067         u32 endTime;
    00068         s32 mergeShaderBuffer;
    00069         s32 cleanUnResolvedMeshes;
    00070         s32 loadAllShaders;
    00071         s32 loadSkyShader;
    00072         s32 alpharef;
    00073         s32 swapLump;
    00074         s32 swapHeader;
    00075         c8 scriptDir [ 64 ];
    00076     };
    00077
    00078     // some useful typedefs
    00079     typedef core::array< core::stringc > tStringList;
    00080     typedef core::array< video::ITexture* > tTexArray;
    00081
    00082     // string helper.. TODO: move to generic files
    00083     inline s16 isEqual ( const core::stringc &string, u32 &pos, const c8 *list[], u16 listSize )
    00084     {
    00085         const char * in = string.c_str () + pos;
    00086
    00087         for ( u16 i = 0; i != listSize; ++i )
    00088         {
    00089             if (string.size() < pos)
    00090                 return -2;
    00091             u32 len = (u32) strlen ( list[i] );
    00092             if (string.size() < pos+len)
    00093                 continue;
    00094             if ( in [len] != 0 && in [len] != ' ' )
    00095                 continue;
    00096             if ( strncmp ( in, list[i], len ) )
    00097                 continue;
    00098
    00099             pos += len + 1;
    00100             return (s16) i;
    00101         }
    00102         return -2;
    00103     }
    00104
    00105     inline f32 getAsFloat ( const core::stringc &string, u32 &pos )
    00106     {
    00107         const char * in = string.c_str () + pos;
    00108
    00109         f32 value = 0.f;
    00110         pos += (u32) ( core::fast_atof_move ( in, value ) - in ) + 1;
    00111         return value;
    00112     }
    00113
    00115     inline core::vector3df getAsVector3df ( const core::stringc &string, u32 &pos )
    00116     {
    00117         core::vector3df v;
    00118
    00119         v.X = getAsFloat ( string, pos );
    00120         v.Z = getAsFloat ( string, pos );
    00121         v.Y = getAsFloat ( string, pos );
    00122
    00123         return v;
    00124     }
    00125
    00126
    00127     /*
    00128         extract substrings
    00129     */
    00130     inline void getAsStringList ( tStringList &list, s32 max, const core::stringc &string, u32 &startPos )
    00131     {
    00132         list.clear ();
    00133
    00134         s32 finish = 0;
    00135         s32 endPos;
    00136         do
    00137         {
    00138             endPos = string.findNext ( ' ', startPos );
    00139             if ( endPos == -1 )
    00140             {
    00141                 finish = 1;
    00142                 endPos = string.size();
    00143             }
    00144
    00145             list.push_back ( string.subString ( startPos, endPos - startPos ) );
    00146             startPos = endPos + 1;
    00147
    00148             if ( list.size() >= (u32) max )
    00149                 finish = 1;
    00150
    00151         } while ( !finish );
    00152
    00153     }
    00154
    00156     struct SBlendFunc
    00157     {
    00158         SBlendFunc ( video::E_MODULATE_FUNC mod )
    00159             : type ( video::EMT_SOLID ), modulate ( mod ),
    00160                 param0( 0.f ),
    00161             isTransparent ( 0 ) {}
    00162
    00163         video::E_MATERIAL_TYPE type;
    00164         video::E_MODULATE_FUNC modulate;
    00165
    00166         f32 param0;
    00167         u32 isTransparent;
    00168     };
    00169
    00170     // parses the content of Variable cull
    00171     inline bool getCullingFunction ( const core::stringc &cull )
    00172     {
    00173         if ( cull.size() == 0 )
    00174             return true;
    00175
    00176         bool ret = true;
    00177         static const c8 * funclist[] = { "none", "disable", "twosided" };
    00178
    00179         u32 pos = 0;
    00180         switch ( isEqual ( cull, pos, funclist, 3 ) )
    00181         {
    00182             case 0:
    00183             case 1:
    00184             case 2:
    00185                 ret = false;
    00186                 break;
    00187         }
    00188         return ret;
    00189     }
    00190
    00191     // parses the content of Variable depthfunc
    00192     // return a z-test
    00193     inline u8 getDepthFunction ( const core::stringc &string )
    00194     {
    00195         u8 ret = video::ECFN_LESSEQUAL;
    00196
    00197         if ( string.size() == 0 )
    00198             return ret;
    00199
    00200         static const c8 * funclist[] = { "lequal","equal" };
    00201
    00202         u32 pos = 0;
    00203         switch ( isEqual ( string, pos, funclist, 2 ) )
    00204         {
    00205             case 0:
    00206                 ret = video::ECFN_LESSEQUAL;
    00207                 break;
    00208             case 1:
    00209                 ret = video::ECFN_EQUAL;
    00210                 break;
    00211         }
    00212         return ret;
    00213     }
    00214
    00215
    00227     inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc )
    00228     {
    00229         if ( string.size() == 0 )
    00230             return;
    00231
    00232         // maps to E_BLEND_FACTOR
    00233         static const c8 * funclist[] =
    00234         {
    00235             "gl_zero",
    00236             "gl_one",
    00237             "gl_dst_color",
    00238             "gl_one_minus_dst_color",
    00239             "gl_src_color",
    00240             "gl_one_minus_src_color",
    00241             "gl_src_alpha",
    00242             "gl_one_minus_src_alpha",
    00243             "gl_dst_alpha",
    00244             "gl_one_minus_dst_alpha",
    00245             "gl_src_alpha_sat",
    00246
    00247             "add",
    00248             "filter",
    00249             "blend",
    00250
    00251             "ge128",
    00252             "gt0",
    00253         };
    00254
    00255
    00256         u32 pos = 0;
    00257         s32 srcFact = isEqual ( string, pos, funclist, 16 );
    00258
    00259         if ( srcFact < 0 )
    00260             return;
    00261
    00262         u32 resolved = 0;
    00263         s32 dstFact = isEqual ( string, pos, funclist, 16 );
    00264
    00265         switch ( srcFact )
    00266         {
    00267             case video::EBF_ZERO:
    00268                 switch ( dstFact )
    00269                 {
    00270                     // gl_zero gl_src_color == gl_dst_color gl_zero
    00271                     case video::EBF_SRC_COLOR:
    00272                         blendfunc.type = video::EMT_ONETEXTURE_BLEND;
    00273                         blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate );
    00274                         blendfunc.isTransparent = 1;
    00275                         resolved = 1;
    00276                         break;
    00277                 } break;
    00278
    00279             case video::EBF_ONE:
    00280                 switch ( dstFact )
    00281                 {
    00282                     // gl_one gl_zero
    00283                     case video::EBF_ZERO:
    00284                         blendfunc.type = video::EMT_SOLID;
    00285                         blendfunc.isTransparent = 0;
    00286                         resolved = 1;
    00287                         break;
    00288
    00289                     // gl_one gl_one
    00290                     case video::EBF_ONE:
    00291                         blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR;
    00292                         blendfunc.isTransparent = 1;
    00293                         resolved = 1;
    00294                         break;
    00295                 } break;
    00296
    00297             case video::EBF_SRC_ALPHA:
    00298                 switch ( dstFact )
    00299                 {
    00300                     // gl_src_alpha gl_one_minus_src_alpha
    00301                     case video::EBF_ONE_MINUS_SRC_ALPHA:
    00302                         blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
    00303                         blendfunc.param0 = 1.f/255.f;
    00304                         blendfunc.isTransparent = 1;
    00305                         resolved = 1;
    00306                         break;
    00307                 } break;
    00308
    00309             case 11:
    00310                 // add
    00311                 blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR;
    00312                 blendfunc.isTransparent = 1;
    00313                 resolved = 1;
    00314                 break;
    00315             case 12:
    00316                 // filter = gl_dst_color gl_zero or gl_zero gl_src_color
    00317                 blendfunc.type = video::EMT_ONETEXTURE_BLEND;
    00318                 blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate );
    00319                 blendfunc.isTransparent = 1;
    00320                 resolved = 1;
    00321                 break;
    00322             case 13:
    00323                 // blend = gl_src_alpha gl_one_minus_src_alpha
    00324                 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
    00325                 blendfunc.param0 = 1.f/255.f;
    00326                 blendfunc.isTransparent = 1;
    00327                 resolved = 1;
    00328                 break;
    00329             case 14:
    00330                 // alphafunc ge128
    00331                 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
    00332                 blendfunc.param0 = 0.5f;
    00333                 blendfunc.isTransparent = 1;
    00334                 resolved = 1;
    00335                 break;
    00336             case 15:
    00337                 // alphafunc gt0
    00338                 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
    00339                 blendfunc.param0 = 1.f / 255.f;
    00340                 blendfunc.isTransparent = 1;
    00341                 resolved = 1;
    00342                 break;
    00343
    00344         }
    00345
    00346         // use the generic blender
    00347         if ( 0 == resolved )
    00348         {
    00349             blendfunc.type = video::EMT_ONETEXTURE_BLEND;
    00350             blendfunc.param0 = video::pack_textureBlendFunc (
    00351                     (video::E_BLEND_FACTOR) srcFact,
    00352                     (video::E_BLEND_FACTOR) dstFact,
    00353                     blendfunc.modulate);
    00354
    00355             blendfunc.isTransparent = 1;
    00356         }
    00357     }
    00358
    00359     // random noise [-1;1]
    00360     struct Noiser
    00361     {
    00362         static f32 get ()
    00363         {
    00364             static u32 RandomSeed = 0x69666966;
    00365             RandomSeed = (RandomSeed * 3631 + 1);
    00366
    00367             f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f;
    00368             return value;
    00369         }
    00370     };
    00371
    00372     enum eQ3ModifierFunction
    00373     {
    00374         TCMOD               = 0,
    00375         DEFORMVERTEXES      = 1,
    00376         RGBGEN              = 2,
    00377         TCGEN               = 3,
    00378         MAP                 = 4,
    00379         ALPHAGEN            = 5,
    00380
    00381         FUNCTION2           = 0x10,
    00382         SCROLL              = FUNCTION2 + 1,
    00383         SCALE               = FUNCTION2 + 2,
    00384         ROTATE              = FUNCTION2 + 3,
    00385         STRETCH             = FUNCTION2 + 4,
    00386         TURBULENCE          = FUNCTION2 + 5,
    00387         WAVE                = FUNCTION2 + 6,
    00388
    00389         IDENTITY            = FUNCTION2 + 7,
    00390         VERTEX              = FUNCTION2 + 8,
    00391         TEXTURE             = FUNCTION2 + 9,
    00392         LIGHTMAP            = FUNCTION2 + 10,
    00393         ENVIRONMENT         = FUNCTION2 + 11,
    00394         DOLLAR_LIGHTMAP     = FUNCTION2 + 12,
    00395         BULGE               = FUNCTION2 + 13,
    00396         AUTOSPRITE          = FUNCTION2 + 14,
    00397         AUTOSPRITE2         = FUNCTION2 + 15,
    00398         TRANSFORM           = FUNCTION2 + 16,
    00399         EXACTVERTEX         = FUNCTION2 + 17,
    00400         CONSTANT            = FUNCTION2 + 18,
    00401         LIGHTINGSPECULAR    = FUNCTION2 + 19,
    00402         MOVE                = FUNCTION2 + 20,
    00403         NORMAL              = FUNCTION2 + 21,
    00404         IDENTITYLIGHTING    = FUNCTION2 + 22,
    00405
    00406         WAVE_MODIFIER_FUNCTION  = 0x30,
    00407         SINUS               = WAVE_MODIFIER_FUNCTION + 1,
    00408         COSINUS             = WAVE_MODIFIER_FUNCTION + 2,
    00409         SQUARE              = WAVE_MODIFIER_FUNCTION + 3,
    00410         TRIANGLE            = WAVE_MODIFIER_FUNCTION + 4,
    00411         SAWTOOTH            = WAVE_MODIFIER_FUNCTION + 5,
    00412         SAWTOOTH_INVERSE    = WAVE_MODIFIER_FUNCTION + 6,
    00413         NOISE               = WAVE_MODIFIER_FUNCTION + 7,
    00414
    00415
    00416         UNKNOWN             = -2
    00417
    00418     };
    00419
    00420     struct SModifierFunction
    00421     {
    00422         SModifierFunction ()
    00423             : masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ),
    00424             tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ),
    00425             base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ),
    00426             wave ( 1 ),
    00427             x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {}
    00428
    00429         // "tcmod","deformvertexes","rgbgen", "tcgen"
    00430         eQ3ModifierFunction masterfunc0;
    00431         // depends
    00432         eQ3ModifierFunction masterfunc1;
    00433         // depends
    00434         eQ3ModifierFunction func;
    00435
    00436         eQ3ModifierFunction tcgen;
    00437         eQ3ModifierFunction rgbgen;
    00438         eQ3ModifierFunction alphagen;
    00439
    00440         union
    00441         {
    00442             f32 base;
    00443             f32 bulgewidth;
    00444         };
    00445
    00446         union
    00447         {
    00448             f32 amp;
    00449             f32 bulgeheight;
    00450         };
    00451
    00452         f32 phase;
    00453
    00454         union
    00455         {
    00456             f32 frequency;
    00457             f32 bulgespeed;
    00458         };
    00459
    00460         union
    00461         {
    00462             f32 wave;
    00463             f32 div;
    00464         };
    00465
    00466         f32 x;
    00467         f32 y;
    00468         f32 z;
    00469         u32 count;
    00470
    00471         f32 evaluate ( f32 dt ) const
    00472         {
    00473             // phase in 0 and 1..
    00474             f32 x = core::fract( (dt + phase ) * frequency );
    00475             f32 y = 0.f;
    00476
    00477             switch ( func )
    00478             {
    00479                 case SINUS:
    00480                     y = sinf ( x * core::PI * 2.f );
    00481                     break;
    00482                 case COSINUS:
    00483                     y = cosf ( x * core::PI * 2.f );
    00484                     break;
    00485                 case SQUARE:
    00486                     y = x < 0.5f ? 1.f : -1.f;
    00487                     break;
    00488                 case TRIANGLE:
    00489                     y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f;
    00490                     break;
    00491                 case SAWTOOTH:
    00492                     y = x;
    00493                     break;
    00494                 case SAWTOOTH_INVERSE:
    00495                     y = 1.f - x;
    00496                     break;
    00497                 case NOISE:
    00498                     y = Noiser::get();
    00499                     break;
    00500                 default:
    00501                     break;
    00502             }
    00503
    00504             return base + ( y * amp );
    00505         }
    00506
    00507
    00508     };
    00509
    00510     inline core::vector3df getMD3Normal ( u32 i, u32 j )
    00511     {
    00512         const f32 lng = i * 2.0f * core::PI / 255.0f;
    00513         const f32 lat = j * 2.0f * core::PI / 255.0f;
    00514         return core::vector3df(cosf ( lat ) * sinf ( lng ),
    00515                 sinf ( lat ) * sinf ( lng ),
    00516                 cosf ( lng ));
    00517     }
    00518
    00519     //
    00520     inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos )
    00521     {
    00522         if ( string.size() == 0 )
    00523             return;
    00524
    00525         static const c8 * funclist[] =
    00526         {
    00527             "sin","cos","square",
    00528             "triangle", "sawtooth","inversesawtooth", "noise"
    00529         };
    00530
    00531         fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 );
    00532         fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1);
    00533
    00534         fill.base = getAsFloat ( string, pos );
    00535         fill.amp = getAsFloat ( string, pos );
    00536         fill.phase = getAsFloat ( string, pos );
    00537         fill.frequency = getAsFloat ( string, pos );
    00538     }
    00539
    00540
    00541     // name = "a b c .."
    00542     struct SVariable
    00543     {
    00544         core::stringc name;
    00545         core::stringc content;
    00546
    00547         SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {}
    00548         virtual ~SVariable () {}
    00549
    00550         void clear ()
    00551         {
    00552             name = "";
    00553             content = "";
    00554         }
    00555
    00556         s32 isValid () const
    00557         {
    00558             return name.size();
    00559         }
    00560
    00561         bool operator == ( const SVariable &other ) const
    00562         {
    00563             return 0 == strcmp ( name.c_str(), other.name.c_str () );
    00564         }
    00565
    00566         bool operator < ( const SVariable &other ) const
    00567         {
    00568             return 0 > strcmp ( name.c_str(), other.name.c_str () );
    00569         }
    00570
    00571     };
    00572
    00573
    00574     // string database. "a" = "Hello", "b" = "1234.6"
    00575     struct SVarGroup
    00576     {
    00577         SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); }
    00578         virtual ~SVarGroup () {}
    00579
    00580         u32 isDefined ( const c8 * name, const c8 * content = 0 ) const
    00581         {
    00582             for ( u32 i = 0; i != Variable.size (); ++i )
    00583             {
    00584                 if ( 0 == strcmp ( Variable[i].name.c_str(), name ) &&
    00585                     (  0 == content || strstr ( Variable[i].content.c_str(), content ) )
    00586                     )
    00587                 {
    00588                     return i + 1;
    00589                 }
    00590             }
    00591             return 0;
    00592         }
    00593
    00594         // searches for Variable name and returns is content
    00595         // if Variable is not found a reference to an Empty String is returned
    00596         const core::stringc &get( const c8 * name ) const
    00597         {
    00598             SVariable search ( name );
    00599             s32 index = Variable.linear_search ( search );
    00600             if ( index < 0 )
    00601                 return irrEmptyStringc;
    00602
    00603             return Variable [ index ].content;
    00604         }
    00605
    00606         // set the Variable name
    00607         void set ( const c8 * name, const c8 * content = 0 )
    00608         {
    00609             u32 index = isDefined ( name, 0 );
    00610             if ( 0 == index )
    00611             {
    00612                 Variable.push_back ( SVariable ( name, content ) );
    00613             }
    00614             else
    00615             {
    00616                 Variable [ index ].content = content;
    00617             }
    00618         }
    00619
    00620
    00621         core::array < SVariable > Variable;
    00622     };
    00623
    00625     struct SVarGroupList: public IReferenceCounted
    00626     {
    00627         SVarGroupList ()
    00628         {
    00629             VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE );
    00630         }
    00631         virtual ~SVarGroupList () {}
    00632
    00633         core::array < SVarGroup > VariableGroup;
    00634     };
    00635
    00636
    00638     struct IShader
    00639     {
    00640         IShader ()
    00641             : ID ( 0 ), VarGroup ( 0 )  {}
    00642         virtual ~IShader () {}
    00643
    00644         void operator = (const IShader &other )
    00645         {
    00646             ID = other.ID;
    00647             VarGroup = other.VarGroup;
    00648             name = other.name;
    00649         }
    00650
    00651         bool operator == (const IShader &other ) const
    00652         {
    00653             return 0 == strcmp ( name.c_str(), other.name.c_str () );
    00654             //return name == other.name;
    00655         }
    00656
    00657         bool operator < (const IShader &other ) const
    00658         {
    00659             return strcmp ( name.c_str(), other.name.c_str () ) < 0;
    00660             //return name < other.name;
    00661         }
    00662
    00663         u32 getGroupSize () const
    00664         {
    00665             if ( 0 == VarGroup )
    00666                 return 0;
    00667             return VarGroup->VariableGroup.size ();
    00668         }
    00669
    00670         const SVarGroup * getGroup ( u32 stage ) const
    00671         {
    00672             if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () )
    00673                 return 0;
    00674
    00675             return &VarGroup->VariableGroup [ stage ];
    00676         }
    00677
    00678         // id
    00679         s32 ID;
    00680         SVarGroupList *VarGroup; // reference
    00681
    00682         // Shader: shader name ( also first variable in first Vargroup )
    00683         // Entity: classname ( variable in Group(1) )
    00684         core::stringc name;
    00685     };
    00686
    00687     typedef IShader IEntity;
    00688
    00689     typedef core::array < IEntity > tQ3EntityList;
    00690
    00691     /*
    00692         dump shader like original layout, regardless of internal data holding
    00693         no recursive folding..
    00694     */
    00695     inline void dumpVarGroup ( core::stringc &dest, const SVarGroup * group, s32 stack )
    00696     {
    00697         core::stringc buf;
    00698         s32 i;
    00699
    00700
    00701         if ( stack > 0 )
    00702         {
    00703             buf = "";
    00704             for ( i = 0; i < stack - 1; ++i )
    00705                 buf += '\t';
    00706
    00707             buf += "{\n";
    00708             dest.append ( buf );
    00709         }
    00710
    00711         for ( u32 g = 0; g != group->Variable.size(); ++g )
    00712         {
    00713             buf = "";
    00714             for ( i = 0; i < stack; ++i )
    00715                 buf += '\t';
    00716
    00717             buf += group->Variable[g].name;
    00718             buf += " ";
    00719             buf += group->Variable[g].content;
    00720             buf += "\n";
    00721             dest.append ( buf );
    00722         }
    00723
    00724         if ( stack > 1 )
    00725         {
    00726             buf = "";
    00727             for ( i = 0; i < stack - 1; ++i )
    00728                 buf += '\t';
    00729
    00730             buf += "}\n";
    00731             dest.append ( buf );
    00732         }
    00733
    00734     }
    00735
    00739     inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false )
    00740     {
    00741         if ( 0 == shader )
    00742             return dest;
    00743
    00744         const SVarGroup * group;
    00745
    00746         const u32 size = shader->VarGroup->VariableGroup.size ();
    00747         for ( u32 i = 0; i != size; ++i )
    00748         {
    00749             group = &shader->VarGroup->VariableGroup[ i ];
    00750             dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) );
    00751         }
    00752
    00753         if ( !entity )
    00754         {
    00755             if ( size <= 1 )
    00756             {
    00757                 dest.append ( "{\n" );
    00758             }
    00759             dest.append ( "}\n" );
    00760         }
    00761         return dest;
    00762     }
    00763
    00764
    00765     /*
    00766         quake3 doesn't care much about tga & jpg
    00767         load one or multiple files stored in name started at startPos to the texture array textures
    00768         if texture is not loaded 0 will be added ( to find missing textures easier)
    00769     */
    00770     inline void getTextures(tTexArray &textures,
    00771                 const core::stringc &name, u32 &startPos,
    00772                 io::IFileSystem *fileSystem,
    00773                 video::IVideoDriver* driver)
    00774     {
    00775         static const char* extension[] =
    00776         {
    00777             ".jpg",
    00778             ".jpeg",
    00779             ".png",
    00780             ".dds",
    00781             ".tga",
    00782             ".bmp",
    00783             ".pcx"
    00784         };
    00785
    00786         tStringList stringList;
    00787         getAsStringList(stringList, -1, name, startPos);
    00788
    00789         textures.clear();
    00790
    00791         io::path loadFile;
    00792         for ( u32 i = 0; i!= stringList.size (); ++i )
    00793         {
    00794             video::ITexture* texture = 0;
    00795             for (u32 g = 0; g != 7 ; ++g)
    00796             {
    00797                 core::cutFilenameExtension ( loadFile, stringList[i] );
    00798
    00799                 if ( loadFile == "$whiteimage" )
    00800                 {
    00801                     texture = driver->getTexture( "$whiteimage" );
    00802                     if ( 0 == texture )
    00803                     {
    00804                         core::dimension2du s ( 2, 2 );
    00805                         u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF };
    00806                         video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
    00807                         texture = driver->addTexture( "$whiteimage", w );
    00808                         w->drop ();
    00809                     }
    00810
    00811                 }
    00812                 else
    00813                 if ( loadFile == "$redimage" )
    00814                 {
    00815                     texture = driver->getTexture( "$redimage" );
    00816                     if ( 0 == texture )
    00817                     {
    00818                         core::dimension2du s ( 2, 2 );
    00819                         u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 };
    00820                         video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
    00821                         texture = driver->addTexture( "$redimage", w );
    00822                         w->drop ();
    00823                     }
    00824                 }
    00825                 else
    00826                 if ( loadFile == "$blueimage" )
    00827                 {
    00828                     texture = driver->getTexture( "$blueimage" );
    00829                     if ( 0 == texture )
    00830                     {
    00831                         core::dimension2du s ( 2, 2 );
    00832                         u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF };
    00833                         video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
    00834                         texture = driver->addTexture( "$blueimage", w );
    00835                         w->drop ();
    00836                     }
    00837                 }
    00838                 else
    00839                 if ( loadFile == "$checkerimage" )
    00840                 {
    00841                     texture = driver->getTexture( "$checkerimage" );
    00842                     if ( 0 == texture )
    00843                     {
    00844                         core::dimension2du s ( 2, 2 );
    00845                         u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF };
    00846                         video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
    00847                         texture = driver->addTexture( "$checkerimage", w );
    00848                         w->drop ();
    00849                     }
    00850                 }
    00851                 else
    00852                 if ( loadFile == "$lightmap" )
    00853                 {
    00854                     texture = 0;
    00855                 }
    00856                 else
    00857                 {
    00858                     loadFile.append ( extension[g] );
    00859                 }
    00860
    00861                 if ( fileSystem->existFile ( loadFile ) )
    00862                 {
    00863                     texture = driver->getTexture( loadFile );
    00864                     if ( texture )
    00865                         break;
    00866                     texture = 0;
    00867                 }
    00868             }
    00869             // take 0 Texture
    00870             textures.push_back(texture);
    00871         }
    00872     }
    00873
    00874
    00876     class IShaderManager : public IReferenceCounted
    00877     {
    00878     };
    00879
    00880 } // end namespace quake3
    00881 } // end namespace scene
    00882 } // end namespace irr
    00883
    00884 #endif
    00885