|
IrrlichtEngine
|
00001 // Copyright (C) 2006-2011 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 case 1: 00208 ret = video::ECFN_EQUAL; 00209 break; 00210 } 00211 return ret; 00212 } 00213 00214 00226 inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc ) 00227 { 00228 if ( string.size() == 0 ) 00229 return; 00230 00231 // maps to E_BLEND_FACTOR 00232 static const c8 * funclist[] = 00233 { 00234 "gl_zero", 00235 "gl_one", 00236 "gl_dst_color", 00237 "gl_one_minus_dst_color", 00238 "gl_src_color", 00239 "gl_one_minus_src_color", 00240 "gl_src_alpha", 00241 "gl_one_minus_src_alpha", 00242 "gl_dst_alpha", 00243 "gl_one_minus_dst_alpha", 00244 "gl_src_alpha_sat", 00245 00246 "add", 00247 "filter", 00248 "blend", 00249 00250 "ge128", 00251 "gt0", 00252 }; 00253 00254 00255 u32 pos = 0; 00256 s32 srcFact = isEqual ( string, pos, funclist, 16 ); 00257 00258 if ( srcFact < 0 ) 00259 return; 00260 00261 u32 resolved = 0; 00262 s32 dstFact = isEqual ( string, pos, funclist, 16 ); 00263 00264 switch ( srcFact ) 00265 { 00266 case video::EBF_ZERO: 00267 switch ( dstFact ) 00268 { 00269 // gl_zero gl_src_color == gl_dst_color gl_zero 00270 case video::EBF_SRC_COLOR: 00271 blendfunc.type = video::EMT_ONETEXTURE_BLEND; 00272 blendfunc.param0 = video::pack_texureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); 00273 blendfunc.isTransparent = 1; 00274 resolved = 1; 00275 break; 00276 } break; 00277 00278 case video::EBF_ONE: 00279 switch ( dstFact ) 00280 { 00281 // gl_one gl_zero 00282 case video::EBF_ZERO: 00283 blendfunc.type = video::EMT_SOLID; 00284 blendfunc.isTransparent = 0; 00285 resolved = 1; 00286 break; 00287 00288 // gl_one gl_one 00289 case video::EBF_ONE: 00290 blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; 00291 blendfunc.isTransparent = 1; 00292 resolved = 1; 00293 break; 00294 } break; 00295 00296 case video::EBF_SRC_ALPHA: 00297 switch ( dstFact ) 00298 { 00299 // gl_src_alpha gl_one_minus_src_alpha 00300 case video::EBF_ONE_MINUS_SRC_ALPHA: 00301 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; 00302 blendfunc.param0 = 1.f/255.f; 00303 blendfunc.isTransparent = 1; 00304 resolved = 1; 00305 break; 00306 } break; 00307 00308 case 11: 00309 // add 00310 blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; 00311 blendfunc.isTransparent = 1; 00312 resolved = 1; 00313 break; 00314 case 12: 00315 // filter = gl_dst_color gl_zero or gl_zero gl_src_color 00316 blendfunc.type = video::EMT_ONETEXTURE_BLEND; 00317 blendfunc.param0 = video::pack_texureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); 00318 blendfunc.isTransparent = 1; 00319 resolved = 1; 00320 break; 00321 case 13: 00322 // blend = gl_src_alpha gl_one_minus_src_alpha 00323 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; 00324 blendfunc.param0 = 1.f/255.f; 00325 blendfunc.isTransparent = 1; 00326 resolved = 1; 00327 break; 00328 case 14: 00329 // alphafunc ge128 00330 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; 00331 blendfunc.param0 = 0.5f; 00332 blendfunc.isTransparent = 1; 00333 resolved = 1; 00334 break; 00335 case 15: 00336 // alphafunc gt0 00337 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; 00338 blendfunc.param0 = 1.f / 255.f; 00339 blendfunc.isTransparent = 1; 00340 resolved = 1; 00341 break; 00342 00343 } 00344 00345 // use the generic blender 00346 if ( 0 == resolved ) 00347 { 00348 blendfunc.type = video::EMT_ONETEXTURE_BLEND; 00349 blendfunc.param0 = video::pack_texureBlendFunc ( 00350 (video::E_BLEND_FACTOR) srcFact, 00351 (video::E_BLEND_FACTOR) dstFact, 00352 blendfunc.modulate); 00353 00354 blendfunc.isTransparent = 1; 00355 } 00356 } 00357 00358 // random noise [-1;1] 00359 struct Noiser 00360 { 00361 static f32 get () 00362 { 00363 static u32 RandomSeed = 0x69666966; 00364 RandomSeed = (RandomSeed * 3631 + 1); 00365 00366 f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f; 00367 return value; 00368 } 00369 }; 00370 00371 enum eQ3ModifierFunction 00372 { 00373 TCMOD = 0, 00374 DEFORMVERTEXES = 1, 00375 RGBGEN = 2, 00376 TCGEN = 3, 00377 MAP = 4, 00378 ALPHAGEN = 5, 00379 00380 FUNCTION2 = 0x10, 00381 SCROLL = FUNCTION2 + 1, 00382 SCALE = FUNCTION2 + 2, 00383 ROTATE = FUNCTION2 + 3, 00384 STRETCH = FUNCTION2 + 4, 00385 TURBULENCE = FUNCTION2 + 5, 00386 WAVE = FUNCTION2 + 6, 00387 00388 IDENTITY = FUNCTION2 + 7, 00389 VERTEX = FUNCTION2 + 8, 00390 TEXTURE = FUNCTION2 + 9, 00391 LIGHTMAP = FUNCTION2 + 10, 00392 ENVIRONMENT = FUNCTION2 + 11, 00393 DOLLAR_LIGHTMAP = FUNCTION2 + 12, 00394 BULGE = FUNCTION2 + 13, 00395 AUTOSPRITE = FUNCTION2 + 14, 00396 AUTOSPRITE2 = FUNCTION2 + 15, 00397 TRANSFORM = FUNCTION2 + 16, 00398 EXACTVERTEX = FUNCTION2 + 17, 00399 CONSTANT = FUNCTION2 + 18, 00400 LIGHTINGSPECULAR = FUNCTION2 + 19, 00401 MOVE = FUNCTION2 + 20, 00402 NORMAL = FUNCTION2 + 21, 00403 IDENTITYLIGHTING = FUNCTION2 + 22, 00404 00405 WAVE_MODIFIER_FUNCTION = 0x30, 00406 SINUS = WAVE_MODIFIER_FUNCTION + 1, 00407 COSINUS = WAVE_MODIFIER_FUNCTION + 2, 00408 SQUARE = WAVE_MODIFIER_FUNCTION + 3, 00409 TRIANGLE = WAVE_MODIFIER_FUNCTION + 4, 00410 SAWTOOTH = WAVE_MODIFIER_FUNCTION + 5, 00411 SAWTOOTH_INVERSE = WAVE_MODIFIER_FUNCTION + 6, 00412 NOISE = WAVE_MODIFIER_FUNCTION + 7, 00413 00414 00415 UNKNOWN = -2 00416 00417 }; 00418 00419 struct SModifierFunction 00420 { 00421 SModifierFunction () 00422 : masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ), 00423 tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ), 00424 base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ), 00425 wave ( 1 ), 00426 x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {} 00427 00428 // "tcmod","deformvertexes","rgbgen", "tcgen" 00429 eQ3ModifierFunction masterfunc0; 00430 // depends 00431 eQ3ModifierFunction masterfunc1; 00432 // depends 00433 eQ3ModifierFunction func; 00434 00435 eQ3ModifierFunction tcgen; 00436 eQ3ModifierFunction rgbgen; 00437 eQ3ModifierFunction alphagen; 00438 00439 union 00440 { 00441 f32 base; 00442 f32 bulgewidth; 00443 }; 00444 00445 union 00446 { 00447 f32 amp; 00448 f32 bulgeheight; 00449 }; 00450 00451 f32 phase; 00452 00453 union 00454 { 00455 f32 frequency; 00456 f32 bulgespeed; 00457 }; 00458 00459 union 00460 { 00461 f32 wave; 00462 f32 div; 00463 }; 00464 00465 f32 x; 00466 f32 y; 00467 f32 z; 00468 u32 count; 00469 00470 f32 evaluate ( f32 dt ) const 00471 { 00472 // phase in 0 and 1.. 00473 f32 x = core::fract( (dt + phase ) * frequency ); 00474 f32 y = 0.f; 00475 00476 switch ( func ) 00477 { 00478 case SINUS: 00479 y = sinf ( x * core::PI * 2.f ); 00480 break; 00481 case COSINUS: 00482 y = cosf ( x * core::PI * 2.f ); 00483 break; 00484 case SQUARE: 00485 y = x < 0.5f ? 1.f : -1.f; 00486 break; 00487 case TRIANGLE: 00488 y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f; 00489 break; 00490 case SAWTOOTH: 00491 y = x; 00492 break; 00493 case SAWTOOTH_INVERSE: 00494 y = 1.f - x; 00495 break; 00496 case NOISE: 00497 y = Noiser::get(); 00498 break; 00499 default: 00500 break; 00501 } 00502 00503 return base + ( y * amp ); 00504 } 00505 00506 00507 }; 00508 00509 inline core::vector3df getMD3Normal ( u32 i, u32 j ) 00510 { 00511 const f32 lng = i * 2.0f * core::PI / 255.0f; 00512 const f32 lat = j * 2.0f * core::PI / 255.0f; 00513 return core::vector3df(cosf ( lat ) * sinf ( lng ), 00514 sinf ( lat ) * sinf ( lng ), 00515 cosf ( lng )); 00516 } 00517 00518 // 00519 inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos ) 00520 { 00521 if ( string.size() == 0 ) 00522 return; 00523 00524 static const c8 * funclist[] = 00525 { 00526 "sin","cos","square", 00527 "triangle", "sawtooth","inversesawtooth", "noise" 00528 }; 00529 00530 fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 ); 00531 fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1); 00532 00533 fill.base = getAsFloat ( string, pos ); 00534 fill.amp = getAsFloat ( string, pos ); 00535 fill.phase = getAsFloat ( string, pos ); 00536 fill.frequency = getAsFloat ( string, pos ); 00537 } 00538 00539 00540 // name = "a b c .." 00541 struct SVariable 00542 { 00543 core::stringc name; 00544 core::stringc content; 00545 00546 SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {} 00547 virtual ~SVariable () {} 00548 00549 void clear () 00550 { 00551 name = ""; 00552 content = ""; 00553 } 00554 00555 s32 isValid () const 00556 { 00557 return name.size(); 00558 } 00559 00560 bool operator == ( const SVariable &other ) const 00561 { 00562 return 0 == strcmp ( name.c_str(), other.name.c_str () ); 00563 } 00564 00565 bool operator < ( const SVariable &other ) const 00566 { 00567 return 0 > strcmp ( name.c_str(), other.name.c_str () ); 00568 } 00569 00570 }; 00571 00572 00573 // string database. "a" = "Hello", "b" = "1234.6" 00574 struct SVarGroup 00575 { 00576 SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); } 00577 virtual ~SVarGroup () {} 00578 00579 u32 isDefined ( const c8 * name, const c8 * content = 0 ) const 00580 { 00581 for ( u32 i = 0; i != Variable.size (); ++i ) 00582 { 00583 if ( 0 == strcmp ( Variable[i].name.c_str(), name ) && 00584 ( 0 == content || strstr ( Variable[i].content.c_str(), content ) ) 00585 ) 00586 { 00587 return i + 1; 00588 } 00589 } 00590 return 0; 00591 } 00592 00593 // searches for Variable name and returns is content 00594 // if Variable is not found a reference to an Empty String is returned 00595 const core::stringc &get( const c8 * name ) const 00596 { 00597 SVariable search ( name ); 00598 s32 index = Variable.linear_search ( search ); 00599 if ( index < 0 ) 00600 return irrEmptyStringc; 00601 00602 return Variable [ index ].content; 00603 } 00604 00605 // set the Variable name 00606 void set ( const c8 * name, const c8 * content = 0 ) 00607 { 00608 u32 index = isDefined ( name, 0 ); 00609 if ( 0 == index ) 00610 { 00611 Variable.push_back ( SVariable ( name, content ) ); 00612 } 00613 else 00614 { 00615 Variable [ index ].content = content; 00616 } 00617 } 00618 00619 00620 core::array < SVariable > Variable; 00621 }; 00622 00624 struct SVarGroupList: public IReferenceCounted 00625 { 00626 SVarGroupList () 00627 { 00628 VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); 00629 } 00630 virtual ~SVarGroupList () {} 00631 00632 core::array < SVarGroup > VariableGroup; 00633 }; 00634 00635 00637 struct IShader 00638 { 00639 IShader () 00640 : ID ( 0 ), VarGroup ( 0 ) {} 00641 virtual ~IShader () {} 00642 00643 void operator = (const IShader &other ) 00644 { 00645 ID = other.ID; 00646 VarGroup = other.VarGroup; 00647 name = other.name; 00648 } 00649 00650 bool operator == (const IShader &other ) const 00651 { 00652 return 0 == strcmp ( name.c_str(), other.name.c_str () ); 00653 //return name == other.name; 00654 } 00655 00656 bool operator < (const IShader &other ) const 00657 { 00658 return strcmp ( name.c_str(), other.name.c_str () ) < 0; 00659 //return name < other.name; 00660 } 00661 00662 u32 getGroupSize () const 00663 { 00664 if ( 0 == VarGroup ) 00665 return 0; 00666 return VarGroup->VariableGroup.size (); 00667 } 00668 00669 const SVarGroup * getGroup ( u32 stage ) const 00670 { 00671 if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () ) 00672 return 0; 00673 00674 return &VarGroup->VariableGroup [ stage ]; 00675 } 00676 00677 // id 00678 s32 ID; 00679 SVarGroupList *VarGroup; // reference 00680 00681 // Shader: shader name ( also first variable in first Vargroup ) 00682 // Entity: classname ( variable in Group(1) ) 00683 core::stringc name; 00684 }; 00685 00686 typedef IShader IEntity; 00687 00688 typedef core::array < IEntity > tQ3EntityList; 00689 00690 /* 00691 dump shader like original layout, regardless of internal data holding 00692 no recursive folding.. 00693 */ 00694 inline void dumpVarGroup ( core::stringc &dest, const SVarGroup * group, s32 stack ) 00695 { 00696 core::stringc buf; 00697 s32 i; 00698 00699 00700 if ( stack > 0 ) 00701 { 00702 buf = ""; 00703 for ( i = 0; i < stack - 1; ++i ) 00704 buf += '\t'; 00705 00706 buf += "{\n"; 00707 dest.append ( buf ); 00708 } 00709 00710 for ( u32 g = 0; g != group->Variable.size(); ++g ) 00711 { 00712 buf = ""; 00713 for ( i = 0; i < stack; ++i ) 00714 buf += '\t'; 00715 00716 buf += group->Variable[g].name; 00717 buf += " "; 00718 buf += group->Variable[g].content; 00719 buf += "\n"; 00720 dest.append ( buf ); 00721 } 00722 00723 if ( stack > 1 ) 00724 { 00725 buf = ""; 00726 for ( i = 0; i < stack - 1; ++i ) 00727 buf += '\t'; 00728 00729 buf += "}\n"; 00730 dest.append ( buf ); 00731 } 00732 00733 } 00734 00738 inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false ) 00739 { 00740 if ( 0 == shader ) 00741 return dest; 00742 00743 const SVarGroup * group; 00744 00745 const u32 size = shader->VarGroup->VariableGroup.size (); 00746 for ( u32 i = 0; i != size; ++i ) 00747 { 00748 group = &shader->VarGroup->VariableGroup[ i ]; 00749 dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) ); 00750 } 00751 00752 if ( !entity ) 00753 { 00754 if ( size <= 1 ) 00755 { 00756 dest.append ( "{\n" ); 00757 } 00758 dest.append ( "}\n" ); 00759 } 00760 return dest; 00761 } 00762 00763 00764 /* 00765 quake3 doesn't care much about tga & jpg 00766 load one or multiple files stored in name started at startPos to the texture array textures 00767 if texture is not loaded 0 will be added ( to find missing textures easier) 00768 */ 00769 inline void getTextures(tTexArray &textures, 00770 const core::stringc &name, u32 &startPos, 00771 io::IFileSystem *fileSystem, 00772 video::IVideoDriver* driver) 00773 { 00774 static const char* extension[] = 00775 { 00776 ".jpg", 00777 ".jpeg", 00778 ".png", 00779 ".dds", 00780 ".tga", 00781 ".bmp", 00782 ".pcx" 00783 }; 00784 00785 tStringList stringList; 00786 getAsStringList(stringList, -1, name, startPos); 00787 00788 textures.clear(); 00789 00790 io::path loadFile; 00791 for ( u32 i = 0; i!= stringList.size (); ++i ) 00792 { 00793 video::ITexture* texture = 0; 00794 for (u32 g = 0; g != 7 ; ++g) 00795 { 00796 core::cutFilenameExtension ( loadFile, stringList[i] ); 00797 00798 if ( loadFile == "$whiteimage" ) 00799 { 00800 texture = driver->getTexture( "$whiteimage" ); 00801 if ( 0 == texture ) 00802 { 00803 core::dimension2du s ( 2, 2 ); 00804 u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }; 00805 video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); 00806 texture = driver->addTexture( "$whiteimage", w ); 00807 w->drop (); 00808 } 00809 00810 } 00811 else 00812 if ( loadFile == "$redimage" ) 00813 { 00814 texture = driver->getTexture( "$redimage" ); 00815 if ( 0 == texture ) 00816 { 00817 core::dimension2du s ( 2, 2 ); 00818 u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 }; 00819 video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); 00820 texture = driver->addTexture( "$redimage", w ); 00821 w->drop (); 00822 } 00823 } 00824 else 00825 if ( loadFile == "$blueimage" ) 00826 { 00827 texture = driver->getTexture( "$blueimage" ); 00828 if ( 0 == texture ) 00829 { 00830 core::dimension2du s ( 2, 2 ); 00831 u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF }; 00832 video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); 00833 texture = driver->addTexture( "$blueimage", w ); 00834 w->drop (); 00835 } 00836 } 00837 else 00838 if ( loadFile == "$checkerimage" ) 00839 { 00840 texture = driver->getTexture( "$checkerimage" ); 00841 if ( 0 == texture ) 00842 { 00843 core::dimension2du s ( 2, 2 ); 00844 u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF }; 00845 video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); 00846 texture = driver->addTexture( "$checkerimage", w ); 00847 w->drop (); 00848 } 00849 } 00850 else 00851 if ( loadFile == "$lightmap" ) 00852 { 00853 texture = 0; 00854 } 00855 else 00856 { 00857 loadFile.append ( extension[g] ); 00858 } 00859 00860 if ( fileSystem->existFile ( loadFile ) ) 00861 { 00862 texture = driver->getTexture( loadFile ); 00863 if ( texture ) 00864 break; 00865 texture = 0; 00866 } 00867 } 00868 // take 0 Texture 00869 textures.push_back(texture); 00870 } 00871 } 00872 00873 00875 class IShaderManager : public IReferenceCounted 00876 { 00877 }; 00878 00879 } // end namespace quake3 00880 } // end namespace scene 00881 } // end namespace irr 00882 00883 #endif 00884