00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://ogre.sourceforge.net/ 00006 00007 Copyright © 2000-2002 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #include "OgreStableHeaders.h" 00026 00027 #include "OgreMaterialSerializer.h" 00028 #include "OgreStringConverter.h" 00029 #include "OgreLogManager.h" 00030 #include "OgreException.h" 00031 #include "OgreTechnique.h" 00032 #include "OgrePass.h" 00033 #include "OgreTextureUnitState.h" 00034 #include "OgreMaterialManager.h" 00035 #include "OgreGpuProgramManager.h" 00036 #include "OgreHighLevelGpuProgramManager.h" 00037 #include "OgreExternalTextureSourceManager.h" 00038 00039 namespace Ogre 00040 { 00041 //----------------------------------------------------------------------- 00042 // Internal parser methods 00043 //----------------------------------------------------------------------- 00044 void logParseError(const String& error, const MaterialScriptContext& context) 00045 { 00046 // log material name only if filename not specified 00047 if (context.filename.empty() && context.material) 00048 { 00049 LogManager::getSingleton().logMessage( 00050 "Error in material " + context.material->getName() + 00051 " : " + error); 00052 } 00053 else 00054 { 00055 if (context.material) 00056 { 00057 LogManager::getSingleton().logMessage( 00058 "Error in material " + context.material->getName() + 00059 " at line " + StringConverter::toString(context.lineNo) + 00060 " of " + context.filename + ": " + error); 00061 } 00062 else 00063 { 00064 LogManager::getSingleton().logMessage( 00065 "Error at line " + StringConverter::toString(context.lineNo) + 00066 " of " + context.filename + ": " + error); 00067 } 00068 } 00069 } 00070 //----------------------------------------------------------------------- 00071 ColourValue _parseColourValue(StringVector& vecparams) 00072 { 00073 return ColourValue( 00074 StringConverter::parseReal(vecparams[0]) , 00075 StringConverter::parseReal(vecparams[1]) , 00076 StringConverter::parseReal(vecparams[2]) , 00077 (vecparams.size()==4) ? StringConverter::parseReal(vecparams[3]) : 1.0f ) ; 00078 } 00079 //----------------------------------------------------------------------- 00080 FilterOptions convertFiltering(const String& s) 00081 { 00082 if (s == "none") 00083 { 00084 return FO_NONE; 00085 } 00086 else if (s == "point") 00087 { 00088 return FO_POINT; 00089 } 00090 else if (s == "linear") 00091 { 00092 return FO_LINEAR; 00093 } 00094 else if (s == "anisotropic") 00095 { 00096 return FO_ANISOTROPIC; 00097 } 00098 00099 return FO_POINT; 00100 } 00101 //----------------------------------------------------------------------- 00102 bool parseAmbient(String& params, MaterialScriptContext& context) 00103 { 00104 StringVector vecparams = params.split(" \t"); 00105 // Must be 3 or 4 parameters 00106 if (vecparams.size() != 3 && vecparams.size() != 4) 00107 { 00108 logParseError( 00109 "Bad ambient attribute, wrong number of parameters (expected 3 or 4)", 00110 context); 00111 } 00112 else 00113 { 00114 context.pass->setAmbient( _parseColourValue(vecparams) ); 00115 } 00116 return false; 00117 } 00118 //----------------------------------------------------------------------- 00119 bool parseDiffuse(String& params, MaterialScriptContext& context) 00120 { 00121 StringVector vecparams = params.split(" \t"); 00122 // Must be 3 or 4 parameters 00123 if (vecparams.size() != 3 && vecparams.size() != 4) 00124 { 00125 logParseError( 00126 "Bad diffuse attribute, wrong number of parameters (expected 3 or 4)", 00127 context); 00128 } 00129 else 00130 { 00131 context.pass->setDiffuse( _parseColourValue(vecparams) ); 00132 } 00133 return false; 00134 } 00135 //----------------------------------------------------------------------- 00136 bool parseSpecular(String& params, MaterialScriptContext& context) 00137 { 00138 StringVector vecparams = params.split(" \t"); 00139 // Must be 4 or 5 parameters 00140 if (vecparams.size() != 4 && vecparams.size() != 5) 00141 { 00142 logParseError( 00143 "Bad specular attribute, wrong number of parameters (expected 4 or 5)", 00144 context); 00145 } 00146 else 00147 { 00148 context.pass->setSpecular( 00149 StringConverter::parseReal(vecparams[0]), 00150 StringConverter::parseReal(vecparams[1]), 00151 StringConverter::parseReal(vecparams[2])); 00152 context.pass->setShininess( 00153 StringConverter::parseReal(vecparams[vecparams.size() - 1]) ); 00154 } 00155 return false; 00156 } 00157 //----------------------------------------------------------------------- 00158 bool parseEmissive(String& params, MaterialScriptContext& context) 00159 { 00160 StringVector vecparams = params.split(" \t"); 00161 // Must be 3 or 4 parameters 00162 if (vecparams.size() != 3 && vecparams.size() != 4) 00163 { 00164 logParseError( 00165 "Bad emissive attribute, wrong number of parameters (expected 3 or 4)", 00166 context); 00167 } 00168 else 00169 { 00170 context.pass->setSelfIllumination( _parseColourValue(vecparams) ); 00171 } 00172 return false; 00173 } 00174 //----------------------------------------------------------------------- 00175 SceneBlendFactor convertBlendFactor(const String& param) 00176 { 00177 if (param == "one") 00178 return SBF_ONE; 00179 else if (param == "zero") 00180 return SBF_ZERO; 00181 else if (param == "dest_colour") 00182 return SBF_DEST_COLOUR; 00183 else if (param == "src_colour") 00184 return SBF_SOURCE_COLOUR; 00185 else if (param == "one_minus_dest_colour") 00186 return SBF_ONE_MINUS_DEST_COLOUR; 00187 else if (param == "one_minus_src_colour") 00188 return SBF_ONE_MINUS_SOURCE_COLOUR; 00189 else if (param == "dest_alpha") 00190 return SBF_DEST_ALPHA; 00191 else if (param == "src_alpha") 00192 return SBF_SOURCE_ALPHA; 00193 else if (param == "one_minus_dest_alpha") 00194 return SBF_ONE_MINUS_DEST_ALPHA; 00195 else if (param == "one_minus_src_alpha") 00196 return SBF_ONE_MINUS_SOURCE_ALPHA; 00197 else 00198 { 00199 Except(Exception::ERR_INVALIDPARAMS, "Invalid blend factor.", "convertBlendFactor"); 00200 } 00201 00202 00203 } 00204 //----------------------------------------------------------------------- 00205 bool parseSceneBlend(String& params, MaterialScriptContext& context) 00206 { 00207 params.toLowerCase(); 00208 StringVector vecparams = params.split(" \t"); 00209 // Should be 1 or 2 params 00210 if (vecparams.size() == 1) 00211 { 00212 //simple 00213 SceneBlendType stype; 00214 if (vecparams[0] == "add") 00215 stype = SBT_ADD; 00216 else if (vecparams[0] == "modulate") 00217 stype = SBT_TRANSPARENT_COLOUR; 00218 else if (vecparams[0] == "alpha_blend") 00219 stype = SBT_TRANSPARENT_ALPHA; 00220 else 00221 { 00222 logParseError( 00223 "Bad scene_blend attribute, unrecognised parameter '" + vecparams[0] + "'", 00224 context); 00225 return false; 00226 } 00227 context.pass->setSceneBlending(stype); 00228 00229 } 00230 else if (vecparams.size() == 2) 00231 { 00232 //src/dest 00233 SceneBlendFactor src, dest; 00234 00235 try { 00236 src = convertBlendFactor(vecparams[0]); 00237 dest = convertBlendFactor(vecparams[1]); 00238 context.pass->setSceneBlending(src,dest); 00239 } 00240 catch (Exception& e) 00241 { 00242 logParseError("Bad scene_blend attribute, " + e.getFullDescription(), context); 00243 } 00244 00245 } 00246 else 00247 { 00248 logParseError( 00249 "Bad scene_blend attribute, wrong number of parameters (expected 1 or 2)", 00250 context); 00251 } 00252 00253 return false; 00254 00255 } 00256 //----------------------------------------------------------------------- 00257 CompareFunction convertCompareFunction(const String& param) 00258 { 00259 if (param == "always_fail") 00260 return CMPF_ALWAYS_FAIL; 00261 else if (param == "always_pass") 00262 return CMPF_ALWAYS_PASS; 00263 else if (param == "less") 00264 return CMPF_LESS; 00265 else if (param == "less_equal") 00266 return CMPF_LESS_EQUAL; 00267 else if (param == "equal") 00268 return CMPF_EQUAL; 00269 else if (param == "not_equal") 00270 return CMPF_NOT_EQUAL; 00271 else if (param == "greater_equal") 00272 return CMPF_GREATER_EQUAL; 00273 else if (param == "greater") 00274 return CMPF_GREATER; 00275 else 00276 Except(Exception::ERR_INVALIDPARAMS, "Invalid compare function", "convertCompareFunction"); 00277 00278 } 00279 //----------------------------------------------------------------------- 00280 bool parseDepthCheck(String& params, MaterialScriptContext& context) 00281 { 00282 params.toLowerCase(); 00283 if (params == "on") 00284 context.pass->setDepthCheckEnabled(true); 00285 else if (params == "off") 00286 context.pass->setDepthCheckEnabled(false); 00287 else 00288 logParseError( 00289 "Bad depth_check attribute, valid parameters are 'on' or 'off'.", 00290 context); 00291 00292 return false; 00293 } 00294 //----------------------------------------------------------------------- 00295 bool parseDepthWrite(String& params, MaterialScriptContext& context) 00296 { 00297 params.toLowerCase(); 00298 if (params == "on") 00299 context.pass->setDepthWriteEnabled(true); 00300 else if (params == "off") 00301 context.pass->setDepthWriteEnabled(false); 00302 else 00303 logParseError( 00304 "Bad depth_write attribute, valid parameters are 'on' or 'off'.", 00305 context); 00306 return false; 00307 } 00308 00309 //----------------------------------------------------------------------- 00310 bool parseDepthFunc(String& params, MaterialScriptContext& context) 00311 { 00312 params.toLowerCase(); 00313 try { 00314 CompareFunction func = convertCompareFunction(params); 00315 context.pass->setDepthFunction(func); 00316 } 00317 catch (...) 00318 { 00319 logParseError("Bad depth_func attribute, invalid function parameter.", context); 00320 } 00321 00322 return false; 00323 } 00324 //----------------------------------------------------------------------- 00325 bool parseColourWrite(String& params, MaterialScriptContext& context) 00326 { 00327 params.toLowerCase(); 00328 if (params == "on") 00329 context.pass->setColourWriteEnabled(true); 00330 else if (params == "off") 00331 context.pass->setColourWriteEnabled(false); 00332 else 00333 logParseError( 00334 "Bad colour_write attribute, valid parameters are 'on' or 'off'.", 00335 context); 00336 return false; 00337 } 00338 00339 //----------------------------------------------------------------------- 00340 bool parseCullHardware(String& params, MaterialScriptContext& context) 00341 { 00342 params.toLowerCase(); 00343 if (params=="none") 00344 context.pass->setCullingMode(CULL_NONE); 00345 else if (params=="anticlockwise") 00346 context.pass->setCullingMode(CULL_ANTICLOCKWISE); 00347 else if (params=="clockwise") 00348 context.pass->setCullingMode(CULL_CLOCKWISE); 00349 else 00350 logParseError( 00351 "Bad cull_hardware attribute, valid parameters are " 00352 "'none', 'clockwise' or 'anticlockwise'.", context); 00353 return false; 00354 } 00355 //----------------------------------------------------------------------- 00356 bool parseCullSoftware(String& params, MaterialScriptContext& context) 00357 { 00358 params.toLowerCase(); 00359 if (params=="none") 00360 context.pass->setManualCullingMode(MANUAL_CULL_NONE); 00361 else if (params=="back") 00362 context.pass->setManualCullingMode(MANUAL_CULL_BACK); 00363 else if (params=="front") 00364 context.pass->setManualCullingMode(MANUAL_CULL_FRONT); 00365 else 00366 logParseError( 00367 "Bad cull_software attribute, valid parameters are 'none', " 00368 "'front' or 'back'.", context); 00369 return false; 00370 } 00371 //----------------------------------------------------------------------- 00372 bool parseLighting(String& params, MaterialScriptContext& context) 00373 { 00374 params.toLowerCase(); 00375 if (params=="on") 00376 context.pass->setLightingEnabled(true); 00377 else if (params=="off") 00378 context.pass->setLightingEnabled(false); 00379 else 00380 logParseError( 00381 "Bad lighting attribute, valid parameters are 'on' or 'off'.", context); 00382 return false; 00383 } 00384 //----------------------------------------------------------------------- 00385 bool parseMaxLights(String& params, MaterialScriptContext& context) 00386 { 00387 context.pass->setMaxSimultaneousLights(StringConverter::parseInt(params)); 00388 return false; 00389 } 00390 //----------------------------------------------------------------------- 00391 bool parseIteration(String& params, MaterialScriptContext& context) 00392 { 00393 params.toLowerCase(); 00394 StringVector vecparams = params.split(" \t"); 00395 if (vecparams.size() != 1 && vecparams.size() != 2) 00396 { 00397 logParseError("Bad iteration attribute, expected 1 or 2 parameters.", context); 00398 return false; 00399 } 00400 00401 if (vecparams[0]=="once") 00402 context.pass->setRunOncePerLight(false); 00403 else if (vecparams[0]=="once_per_light") 00404 { 00405 if (vecparams.size() == 2) 00406 { 00407 // Parse light type 00408 if (vecparams[1] == "directional") 00409 { 00410 context.pass->setRunOncePerLight(true, true, Light::LT_DIRECTIONAL); 00411 } 00412 else if (vecparams[1] == "point") 00413 { 00414 context.pass->setRunOncePerLight(true, true, Light::LT_POINT); 00415 } 00416 else if (vecparams[1] == "spot") 00417 { 00418 context.pass->setRunOncePerLight(true, true, Light::LT_SPOTLIGHT); 00419 } 00420 else 00421 { 00422 logParseError("Bad iteration attribute, valid values for second parameter " 00423 "are 'point' or 'directional' or 'spot'.", context); 00424 } 00425 } 00426 else 00427 { 00428 context.pass->setRunOncePerLight(true, false); 00429 } 00430 00431 } 00432 else 00433 logParseError( 00434 "Bad iteration attribute, valid parameters are 'once' or 'once_per_light'.", context); 00435 return false; 00436 } 00437 //----------------------------------------------------------------------- 00438 bool parseFogging(String& params, MaterialScriptContext& context) 00439 { 00440 params.toLowerCase(); 00441 StringVector vecparams = params.split(" \t"); 00442 if (vecparams[0]=="true") 00443 { 00444 // if true, we need to see if they supplied all arguments, or just the 1... if just the one, 00445 // Assume they want to disable the default fog from effecting this material. 00446 if( vecparams.size() == 8 ) 00447 { 00448 FogMode mFogtype; 00449 if( vecparams[1] == "none" ) 00450 mFogtype = FOG_NONE; 00451 else if( vecparams[1] == "linear" ) 00452 mFogtype = FOG_LINEAR; 00453 else if( vecparams[1] == "exp" ) 00454 mFogtype = FOG_EXP; 00455 else if( vecparams[1] == "exp2" ) 00456 mFogtype = FOG_EXP2; 00457 else 00458 { 00459 logParseError( 00460 "Bad fogging attribute, valid parameters are " 00461 "'none', 'linear', 'exp', or 'exp2'.", context); 00462 return false; 00463 } 00464 00465 context.pass->setFog( 00466 true, 00467 mFogtype, 00468 ColourValue( 00469 StringConverter::parseReal(vecparams[2]), 00470 StringConverter::parseReal(vecparams[3]), 00471 StringConverter::parseReal(vecparams[4])), 00472 StringConverter::parseReal(vecparams[5]), 00473 StringConverter::parseReal(vecparams[6]), 00474 StringConverter::parseReal(vecparams[7]) 00475 ); 00476 } 00477 else 00478 { 00479 context.pass->setFog(true); 00480 } 00481 } 00482 else if (vecparams[0]=="false") 00483 context.pass->setFog(false); 00484 else 00485 logParseError( 00486 "Bad fog_override attribute, valid parameters are 'true' or 'false'.", 00487 context); 00488 00489 return false; 00490 } 00491 //----------------------------------------------------------------------- 00492 bool parseShading(String& params, MaterialScriptContext& context) 00493 { 00494 params.toLowerCase(); 00495 if (params=="flat") 00496 context.pass->setShadingMode(SO_FLAT); 00497 else if (params=="gouraud") 00498 context.pass->setShadingMode(SO_GOURAUD); 00499 else if (params=="phong") 00500 context.pass->setShadingMode(SO_PHONG); 00501 else 00502 logParseError("Bad shading attribute, valid parameters are 'flat', " 00503 "'gouraud' or 'phong'.", context); 00504 00505 return false; 00506 } 00507 //----------------------------------------------------------------------- 00508 bool parseFiltering(String& params, MaterialScriptContext& context) 00509 { 00510 params.toLowerCase(); 00511 StringVector vecparams = params.split(" \t"); 00512 // Must be 1 or 3 parameters 00513 if (vecparams.size() == 1) 00514 { 00515 // Simple format 00516 if (vecparams[0]=="none") 00517 context.textureUnit->setTextureFiltering(TFO_NONE); 00518 else if (vecparams[0]=="bilinear") 00519 context.textureUnit->setTextureFiltering(TFO_BILINEAR); 00520 else if (vecparams[0]=="trilinear") 00521 context.textureUnit->setTextureFiltering(TFO_TRILINEAR); 00522 else if (vecparams[0]=="anisotropic") 00523 context.textureUnit->setTextureFiltering(TFO_ANISOTROPIC); 00524 else 00525 { 00526 logParseError("Bad filtering attribute, valid parameters for simple format are " 00527 "'none', 'bilinear', 'trilinear' or 'anisotropic'.", context); 00528 return false; 00529 } 00530 } 00531 else if (vecparams.size() == 3) 00532 { 00533 // Complex format 00534 context.textureUnit->setTextureFiltering( 00535 convertFiltering(vecparams[0]), 00536 convertFiltering(vecparams[1]), 00537 convertFiltering(vecparams[2])); 00538 00539 00540 } 00541 else 00542 { 00543 logParseError( 00544 "Bad filtering attribute, wrong number of parameters (expected 1 or 3)", 00545 context); 00546 } 00547 00548 return false; 00549 } 00550 //----------------------------------------------------------------------- 00551 // Texture layer attributes 00552 bool parseTexture(String& params, MaterialScriptContext& context) 00553 { 00554 StringVector vecparams = params.split(" \t"); 00555 if (vecparams.size() > 2) 00556 { 00557 logParseError("Invalid texture attribute - expected only 1 or 2 parameters.", 00558 context); 00559 } 00560 TextureType tt = TEX_TYPE_2D; 00561 if (vecparams.size() == 2) 00562 { 00563 vecparams[1].toLowerCase(); 00564 if (vecparams[1] == "1d") 00565 { 00566 tt = TEX_TYPE_1D; 00567 } 00568 else if (vecparams[1] == "2d") 00569 { 00570 tt = TEX_TYPE_2D; 00571 } 00572 else if (vecparams[1] == "3d") 00573 { 00574 tt = TEX_TYPE_3D; 00575 } 00576 else if (vecparams[1] == "cubic") 00577 { 00578 tt = TEX_TYPE_CUBE_MAP; 00579 } 00580 } 00581 context.textureUnit->setTextureName(vecparams[0], tt); 00582 return false; 00583 } 00584 //----------------------------------------------------------------------- 00585 bool parseAnimTexture(String& params, MaterialScriptContext& context) 00586 { 00587 StringVector vecparams = params.split(" \t"); 00588 size_t numParams = vecparams.size(); 00589 // Determine which form it is 00590 // Must have at least 3 params though 00591 if (numParams < 3) 00592 { 00593 logParseError("Bad anim_texture attribute, wrong number of parameters " 00594 "(expected at least 3)", context); 00595 return false; 00596 } 00597 if (numParams == 3 && StringConverter::parseInt(vecparams[1]) != 0 ) 00598 { 00599 // First form using base name & number of frames 00600 context.textureUnit->setAnimatedTextureName( 00601 vecparams[0], 00602 StringConverter::parseInt(vecparams[1]), 00603 StringConverter::parseReal(vecparams[2])); 00604 } 00605 else 00606 { 00607 // Second form using individual names 00608 context.textureUnit->setAnimatedTextureName( 00609 (String*)&vecparams[0], 00610 numParams-1, 00611 StringConverter::parseReal(vecparams[numParams-1])); 00612 } 00613 return false; 00614 00615 } 00616 //----------------------------------------------------------------------- 00617 bool parseCubicTexture(String& params, MaterialScriptContext& context) 00618 { 00619 00620 StringVector vecparams = params.split(" \t"); 00621 size_t numParams = vecparams.size(); 00622 00623 // Get final param 00624 bool useUVW; 00625 String uvOpt = vecparams[numParams-1].toLowerCase(); 00626 if (uvOpt == "combineduvw") 00627 useUVW = true; 00628 else if (uvOpt == "separateuv") 00629 useUVW = false; 00630 else 00631 { 00632 logParseError("Bad cubic_texture attribute, final parameter must be " 00633 "'combinedUVW' or 'separateUV'.", context); 00634 return false; 00635 } 00636 // Determine which form it is 00637 if (numParams == 2) 00638 { 00639 // First form using base name 00640 context.textureUnit->setCubicTextureName(vecparams[0], useUVW); 00641 } 00642 else if (numParams == 7) 00643 { 00644 // Second form using individual names 00645 // Can use vecparams[0] as array start point 00646 context.textureUnit->setCubicTextureName((String*)&vecparams[0], useUVW); 00647 } 00648 else 00649 { 00650 logParseError( 00651 "Bad cubic_texture attribute, wrong number of parameters (expected 2 or 7)", 00652 context); 00653 return false; 00654 } 00655 00656 return false; 00657 } 00658 //----------------------------------------------------------------------- 00659 bool parseTexCoord(String& params, MaterialScriptContext& context) 00660 { 00661 context.textureUnit->setTextureCoordSet( 00662 StringConverter::parseInt(params)); 00663 00664 return false; 00665 } 00666 //----------------------------------------------------------------------- 00667 bool parseTexAddressMode(String& params, MaterialScriptContext& context) 00668 { 00669 params.toLowerCase(); 00670 if (params=="wrap") 00671 context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_WRAP); 00672 else if (params=="mirror") 00673 context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_MIRROR); 00674 else if (params=="clamp") 00675 context.textureUnit->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); 00676 else 00677 logParseError("Bad tex_address_mode attribute, valid parameters are " 00678 "'wrap', 'clamp' or 'mirror'.", context); 00679 00680 return false; 00681 } 00682 //----------------------------------------------------------------------- 00683 bool parseColourOp(String& params, MaterialScriptContext& context) 00684 { 00685 params.toLowerCase(); 00686 if (params=="replace") 00687 context.textureUnit->setColourOperation(LBO_REPLACE); 00688 else if (params=="add") 00689 context.textureUnit->setColourOperation(LBO_ADD); 00690 else if (params=="modulate") 00691 context.textureUnit->setColourOperation(LBO_MODULATE); 00692 else if (params=="alpha_blend") 00693 context.textureUnit->setColourOperation(LBO_ALPHA_BLEND); 00694 else 00695 logParseError("Bad colour_op attribute, valid parameters are " 00696 "'replace', 'add', 'modulate' or 'alpha_blend'.", context); 00697 00698 return false; 00699 } 00700 //----------------------------------------------------------------------- 00701 bool parseAlphaRejection(String& params, MaterialScriptContext& context) 00702 { 00703 params.toLowerCase(); 00704 StringVector vecparams = params.split(" \t"); 00705 if (vecparams.size() != 2) 00706 { 00707 logParseError( 00708 "Bad alpha_rejection attribute, wrong number of parameters (expected 2)", 00709 context); 00710 return false; 00711 } 00712 00713 CompareFunction cmp; 00714 try { 00715 cmp = convertCompareFunction(vecparams[0]); 00716 } 00717 catch (...) 00718 { 00719 logParseError("Bad alpha_rejection attribute, invalid compare function.", context); 00720 return false; 00721 } 00722 00723 context.textureUnit->setAlphaRejectSettings(cmp, StringConverter::parseInt(vecparams[1])); 00724 00725 return false; 00726 } 00727 //----------------------------------------------------------------------- 00728 LayerBlendOperationEx convertBlendOpEx(const String& param) 00729 { 00730 if (param == "source1") 00731 return LBX_SOURCE1; 00732 else if (param == "source2") 00733 return LBX_SOURCE2; 00734 else if (param == "modulate") 00735 return LBX_MODULATE; 00736 else if (param == "modulate_x2") 00737 return LBX_MODULATE_X2; 00738 else if (param == "modulate_x4") 00739 return LBX_MODULATE_X4; 00740 else if (param == "add") 00741 return LBX_ADD; 00742 else if (param == "add_signed") 00743 return LBX_ADD_SIGNED; 00744 else if (param == "add_smooth") 00745 return LBX_ADD_SMOOTH; 00746 else if (param == "subtract") 00747 return LBX_SUBTRACT; 00748 else if (param == "blend_diffuse_alpha") 00749 return LBX_BLEND_DIFFUSE_ALPHA; 00750 else if (param == "blend_texture_alpha") 00751 return LBX_BLEND_TEXTURE_ALPHA; 00752 else if (param == "blend_current_alpha") 00753 return LBX_BLEND_CURRENT_ALPHA; 00754 else if (param == "blend_manual") 00755 return LBX_BLEND_MANUAL; 00756 else if (param == "dotproduct") 00757 return LBX_DOTPRODUCT; 00758 else 00759 Except(Exception::ERR_INVALIDPARAMS, "Invalid blend function", "convertBlendOpEx"); 00760 } 00761 //----------------------------------------------------------------------- 00762 LayerBlendSource convertBlendSource(const String& param) 00763 { 00764 if (param == "src_current") 00765 return LBS_CURRENT; 00766 else if (param == "src_texture") 00767 return LBS_TEXTURE; 00768 else if (param == "src_diffuse") 00769 return LBS_DIFFUSE; 00770 else if (param == "src_specular") 00771 return LBS_SPECULAR; 00772 else if (param == "src_manual") 00773 return LBS_MANUAL; 00774 else 00775 Except(Exception::ERR_INVALIDPARAMS, "Invalid blend source", "convertBlendSource"); 00776 } 00777 //----------------------------------------------------------------------- 00778 bool parseColourOpEx(String& params, MaterialScriptContext& context) 00779 { 00780 params.toLowerCase(); 00781 StringVector vecparams = params.split(" \t"); 00782 size_t numParams = vecparams.size(); 00783 00784 if (numParams < 3 || numParams > 10) 00785 { 00786 logParseError( 00787 "Bad colour_op_ex attribute, wrong number of parameters (expected 3 to 10)", 00788 context); 00789 return false; 00790 } 00791 LayerBlendOperationEx op; 00792 LayerBlendSource src1, src2; 00793 Real manual = 0.0; 00794 ColourValue colSrc1 = ColourValue::White; 00795 ColourValue colSrc2 = ColourValue::White; 00796 00797 try { 00798 op = convertBlendOpEx(vecparams[0]); 00799 src1 = convertBlendSource(vecparams[1]); 00800 src2 = convertBlendSource(vecparams[2]); 00801 00802 if (op == LBX_BLEND_MANUAL) 00803 { 00804 if (numParams < 4) 00805 { 00806 logParseError("Bad colour_op_ex attribute, wrong number of parameters " 00807 "(expected 4 for manual blend)", context); 00808 return false; 00809 } 00810 manual = StringConverter::parseReal(vecparams[4]); 00811 } 00812 00813 if (src1 == LBS_MANUAL) 00814 { 00815 unsigned int parIndex = 3; 00816 if (op == LBX_BLEND_MANUAL) 00817 parIndex++; 00818 00819 if (numParams < parIndex + 3) 00820 { 00821 logParseError("Bad colour_op_ex attribute, wrong number of parameters " 00822 "(expected " + StringConverter::toString(parIndex + 3) + ")", context); 00823 return false; 00824 } 00825 00826 colSrc1.r = StringConverter::parseReal(vecparams[parIndex++]); 00827 colSrc1.g = StringConverter::parseReal(vecparams[parIndex++]); 00828 colSrc1.b = StringConverter::parseReal(vecparams[parIndex]); 00829 } 00830 00831 if (src2 == LBS_MANUAL) 00832 { 00833 unsigned int parIndex = 3; 00834 if (op == LBX_BLEND_MANUAL) 00835 parIndex++; 00836 if (src1 == LBS_MANUAL) 00837 parIndex += 3; 00838 00839 if (numParams < parIndex + 3) 00840 { 00841 logParseError("Bad colour_op_ex attribute, wrong number of parameters " 00842 "(expected " + StringConverter::toString(parIndex + 3) + ")", context); 00843 return false; 00844 } 00845 00846 colSrc2.r = StringConverter::parseReal(vecparams[parIndex++]); 00847 colSrc2.g = StringConverter::parseReal(vecparams[parIndex++]); 00848 colSrc2.b = StringConverter::parseReal(vecparams[parIndex]); 00849 } 00850 } 00851 catch (Exception& e) 00852 { 00853 logParseError("Bad colour_op_ex attribute, " + e.getFullDescription(), context); 00854 return false; 00855 } 00856 00857 context.textureUnit->setColourOperationEx(op, src1, src2, colSrc1, colSrc2, manual); 00858 return false; 00859 } 00860 //----------------------------------------------------------------------- 00861 bool parseColourOpFallback(String& params, MaterialScriptContext& context) 00862 { 00863 params.toLowerCase(); 00864 StringVector vecparams = params.split(" \t"); 00865 if (vecparams.size() != 2) 00866 { 00867 logParseError("Bad colour_op_multipass_fallback attribute, wrong number " 00868 "of parameters (expected 2)", context); 00869 return false; 00870 } 00871 00872 //src/dest 00873 SceneBlendFactor src, dest; 00874 00875 try { 00876 src = convertBlendFactor(vecparams[0]); 00877 dest = convertBlendFactor(vecparams[1]); 00878 context.textureUnit->setColourOpMultipassFallback(src,dest); 00879 } 00880 catch (Exception& e) 00881 { 00882 logParseError("Bad colour_op_multipass_fallback attribute, " 00883 + e.getFullDescription(), context); 00884 } 00885 return false; 00886 } 00887 //----------------------------------------------------------------------- 00888 bool parseAlphaOpEx(String& params, MaterialScriptContext& context) 00889 { 00890 params.toLowerCase(); 00891 StringVector vecparams = params.split(" \t"); 00892 size_t numParams = vecparams.size(); 00893 if (numParams < 3 || numParams > 6) 00894 { 00895 logParseError("Bad alpha_op_ex attribute, wrong number of parameters " 00896 "(expected 3 to 6)", context); 00897 return false; 00898 } 00899 LayerBlendOperationEx op; 00900 LayerBlendSource src1, src2; 00901 Real manual = 0.0; 00902 Real arg1 = 1.0, arg2 = 1.0; 00903 00904 try { 00905 op = convertBlendOpEx(vecparams[0]); 00906 src1 = convertBlendSource(vecparams[1]); 00907 src2 = convertBlendSource(vecparams[2]); 00908 if (op == LBX_BLEND_MANUAL) 00909 { 00910 if (numParams != 4) 00911 { 00912 logParseError("Bad alpha_op_ex attribute, wrong number of parameters " 00913 "(expected 4 for manual blend)", context); 00914 return false; 00915 } 00916 manual = StringConverter::parseReal(vecparams[4]); 00917 } 00918 if (src1 == LBS_MANUAL) 00919 { 00920 unsigned int parIndex = 3; 00921 if (op == LBX_BLEND_MANUAL) 00922 parIndex++; 00923 00924 if (numParams < parIndex) 00925 { 00926 logParseError( 00927 "Bad alpha_op_ex attribute, wrong number of parameters (expected " + 00928 StringConverter::toString(parIndex - 1) + ")", context); 00929 return false; 00930 } 00931 00932 arg1 = StringConverter::parseReal(vecparams[parIndex]); 00933 } 00934 00935 if (src2 == LBS_MANUAL) 00936 { 00937 unsigned int parIndex = 3; 00938 if (op == LBX_BLEND_MANUAL) 00939 parIndex++; 00940 if (src1 == LBS_MANUAL) 00941 parIndex++; 00942 00943 if (numParams < parIndex) 00944 { 00945 logParseError( 00946 "Bad alpha_op_ex attribute, wrong number of parameters " 00947 "(expected " + StringConverter::toString(parIndex - 1) + ")", context); 00948 return false; 00949 } 00950 00951 arg2 = StringConverter::parseReal(vecparams[parIndex]); 00952 } 00953 } 00954 catch (Exception& e) 00955 { 00956 logParseError("Bad alpha_op_ex attribute, " + e.getFullDescription(), context); 00957 return false; 00958 } 00959 00960 context.textureUnit->setAlphaOperation(op, src1, src2, arg1, arg2, manual); 00961 return false; 00962 } 00963 //----------------------------------------------------------------------- 00964 bool parseEnvMap(String& params, MaterialScriptContext& context) 00965 { 00966 params.toLowerCase(); 00967 if (params=="off") 00968 context.textureUnit->setEnvironmentMap(false); 00969 else if (params=="spherical") 00970 context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_CURVED); 00971 else if (params=="planar") 00972 context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR); 00973 else if (params=="cubic_reflection") 00974 context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_REFLECTION); 00975 else if (params=="cubic_normal") 00976 context.textureUnit->setEnvironmentMap(true, TextureUnitState::ENV_NORMAL); 00977 else 00978 logParseError("Bad env_map attribute, valid parameters are 'off', " 00979 "'spherical', 'planar', 'cubic_reflection' and 'cubic_normal'.", context); 00980 00981 return false; 00982 } 00983 //----------------------------------------------------------------------- 00984 bool parseScroll(String& params, MaterialScriptContext& context) 00985 { 00986 StringVector vecparams = params.split(" \t"); 00987 if (vecparams.size() != 2) 00988 { 00989 logParseError("Bad scroll attribute, wrong number of parameters (expected 2)", context); 00990 return false; 00991 } 00992 context.textureUnit->setTextureScroll( 00993 StringConverter::parseReal(vecparams[0]), 00994 StringConverter::parseReal(vecparams[1])); 00995 00996 00997 return false; 00998 } 00999 //----------------------------------------------------------------------- 01000 bool parseScrollAnim(String& params, MaterialScriptContext& context) 01001 { 01002 StringVector vecparams = params.split(" \t"); 01003 if (vecparams.size() != 2) 01004 { 01005 logParseError("Bad scroll_anim attribute, wrong number of " 01006 "parameters (expected 2)", context); 01007 return false; 01008 } 01009 context.textureUnit->setScrollAnimation( 01010 StringConverter::parseReal(vecparams[0]), 01011 StringConverter::parseReal(vecparams[1])); 01012 01013 return false; 01014 } 01015 //----------------------------------------------------------------------- 01016 bool parseRotate(String& params, MaterialScriptContext& context) 01017 { 01018 context.textureUnit->setTextureRotate( 01019 StringConverter::parseReal(params)); 01020 01021 return false; 01022 } 01023 //----------------------------------------------------------------------- 01024 bool parseRotateAnim(String& params, MaterialScriptContext& context) 01025 { 01026 context.textureUnit->setRotateAnimation( 01027 StringConverter::parseReal(params)); 01028 01029 return false; 01030 } 01031 //----------------------------------------------------------------------- 01032 bool parseScale(String& params, MaterialScriptContext& context) 01033 { 01034 StringVector vecparams = params.split(" \t"); 01035 if (vecparams.size() != 2) 01036 { 01037 logParseError("Bad scale attribute, wrong number of parameters (expected 2)", context); 01038 return false; 01039 } 01040 context.textureUnit->setTextureScale( 01041 StringConverter::parseReal(vecparams[0]), 01042 StringConverter::parseReal(vecparams[1])); 01043 01044 return false; 01045 } 01046 //----------------------------------------------------------------------- 01047 bool parseWaveXform(String& params, MaterialScriptContext& context) 01048 { 01049 params.toLowerCase(); 01050 StringVector vecparams = params.split(" \t"); 01051 01052 if (vecparams.size() != 6) 01053 { 01054 logParseError("Bad wave_xform attribute, wrong number of parameters " 01055 "(expected 6)", context); 01056 return false; 01057 } 01058 TextureUnitState::TextureTransformType ttype; 01059 WaveformType waveType; 01060 // Check transform type 01061 if (vecparams[0]=="scroll_x") 01062 ttype = TextureUnitState::TT_TRANSLATE_U; 01063 else if (vecparams[0]=="scroll_y") 01064 ttype = TextureUnitState::TT_TRANSLATE_V; 01065 else if (vecparams[0]=="rotate") 01066 ttype = TextureUnitState::TT_ROTATE; 01067 else if (vecparams[0]=="scale_x") 01068 ttype = TextureUnitState::TT_SCALE_U; 01069 else if (vecparams[0]=="scale_y") 01070 ttype = TextureUnitState::TT_SCALE_V; 01071 else 01072 { 01073 logParseError("Bad wave_xform attribute, parameter 1 must be 'scroll_x', " 01074 "'scroll_y', 'rotate', 'scale_x' or 'scale_y'", context); 01075 return false; 01076 } 01077 // Check wave type 01078 if (vecparams[1]=="sine") 01079 waveType = WFT_SINE; 01080 else if (vecparams[1]=="triangle") 01081 waveType = WFT_TRIANGLE; 01082 else if (vecparams[1]=="square") 01083 waveType = WFT_SQUARE; 01084 else if (vecparams[1]=="sawtooth") 01085 waveType = WFT_SAWTOOTH; 01086 else if (vecparams[1]=="inverse_sawtooth") 01087 waveType = WFT_INVERSE_SAWTOOTH; 01088 else 01089 { 01090 logParseError("Bad wave_xform attribute, parameter 2 must be 'sine', " 01091 "'triangle', 'square', 'sawtooth' or 'inverse_sawtooth'", context); 01092 return false; 01093 } 01094 01095 context.textureUnit->setTransformAnimation( 01096 ttype, 01097 waveType, 01098 StringConverter::parseReal(vecparams[2]), 01099 StringConverter::parseReal(vecparams[3]), 01100 StringConverter::parseReal(vecparams[4]), 01101 StringConverter::parseReal(vecparams[5]) ); 01102 01103 return false; 01104 } 01105 //----------------------------------------------------------------------- 01106 bool parseDepthBias(String& params, MaterialScriptContext& context) 01107 { 01108 context.pass->setDepthBias( 01109 StringConverter::parseReal(params)); 01110 01111 return false; 01112 } 01113 //----------------------------------------------------------------------- 01114 bool parseAnisotropy(String& params, MaterialScriptContext& context) 01115 { 01116 context.textureUnit->setTextureAnisotropy( 01117 StringConverter::parseInt(params)); 01118 01119 return false; 01120 } 01121 //----------------------------------------------------------------------- 01122 bool parseLodDistances(String& params, MaterialScriptContext& context) 01123 { 01124 StringVector vecparams = params.split(" \t"); 01125 01126 // iterate over the parameters and parse distances out of them 01127 Material::LodDistanceList lodList; 01128 StringVector::iterator i, iend; 01129 iend = vecparams.end(); 01130 for (i = vecparams.begin(); i != iend; ++i) 01131 { 01132 lodList.push_back(StringConverter::parseReal(*i)); 01133 } 01134 01135 context.material->setLodLevels(lodList); 01136 01137 return false; 01138 } 01139 //----------------------------------------------------------------------- 01140 bool parseLodIndex(String& params, MaterialScriptContext& context) 01141 { 01142 context.technique->setLodIndex(StringConverter::parseInt(params)); 01143 return false; 01144 } 01145 //----------------------------------------------------------------------- 01146 void processManualProgramParam(size_t index, const String& commandname, 01147 StringVector& vecparams, MaterialScriptContext& context) 01148 { 01149 // NB we assume that the first element of vecparams is taken up with either 01150 // the index or the parameter name, which we ignore 01151 01152 // Determine type 01153 size_t start, dims, i; 01154 bool isReal; 01155 01156 vecparams[1].toLowerCase(); 01157 01158 if (vecparams[1] == "matrix4x4") 01159 { 01160 dims = 16; 01161 isReal = true; 01162 } 01163 else if ((start = vecparams[1].find("float")) != String::npos) 01164 { 01165 // find the dimensionality 01166 start = vecparams[1].find_first_not_of("float"); 01167 dims = StringConverter::parseInt(vecparams[1].substr(start)); 01168 isReal = true; 01169 } 01170 else if ((start = vecparams[1].find("int")) != String::npos) 01171 { 01172 // find the dimensionality 01173 start = vecparams[1].find_first_not_of("int"); 01174 dims = StringConverter::parseInt(vecparams[1].substr(start)); 01175 isReal = false; 01176 } 01177 else 01178 { 01179 logParseError("Invalid " + commandname + " attribute - unrecognised " 01180 "parameter type " + vecparams[1], context); 01181 return; 01182 } 01183 01184 if (vecparams.size() != 2 + dims) 01185 { 01186 logParseError("Invalid " + commandname + " attribute - you need " + 01187 StringConverter::toString(2 + dims) + " parameters for a parameter of " 01188 "type " + vecparams[1], context); 01189 } 01190 01191 if (dims % 4 != 0) 01192 { 01193 logParseError("Invalid " + commandname + " attribute; parameter type must " 01194 "have a cardinality which is a multiple of 4", context); 01195 } 01196 01197 // Now parse all the values 01198 if (isReal) 01199 { 01200 Real* realBuffer = new Real[dims]; 01201 for (i = 0; i < dims; ++i) 01202 { 01203 realBuffer[i] = StringConverter::parseReal(vecparams[i+2]); 01204 } 01205 // Set 01206 context.programParams->setConstant(index, realBuffer, dims * 0.25); 01207 delete [] realBuffer; 01208 } 01209 else 01210 { 01211 int* intBuffer = new int[dims]; 01212 for (i = 0; i < dims; ++i) 01213 { 01214 intBuffer[i] = StringConverter::parseInt(vecparams[i+2]); 01215 } 01216 // Set 01217 context.programParams->setConstant(index, intBuffer, dims * 0.25); 01218 delete [] intBuffer; 01219 } 01220 } 01221 //----------------------------------------------------------------------- 01222 void processAutoProgramParam(size_t index, const String& commandname, 01223 StringVector& vecparams, MaterialScriptContext& context) 01224 { 01225 // NB we assume that the first element of vecparams is taken up with either 01226 // the index or the parameter name, which we ignore 01227 01228 bool extras = false; 01229 GpuProgramParameters::AutoConstantType acType; 01230 01231 vecparams[1].toLowerCase(); 01232 01233 if (vecparams[1] == "world_matrix") 01234 { 01235 acType = GpuProgramParameters::ACT_WORLD_MATRIX; 01236 } 01237 else if (vecparams[1] == "world_matrix_array") 01238 { 01239 acType = GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY; 01240 } 01241 else if (vecparams[1] == "world_matrix_array_3x4") 01242 { 01243 acType = GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY_3x4; 01244 } 01245 else if (vecparams[1] == "view_matrix") 01246 { 01247 acType = GpuProgramParameters::ACT_VIEW_MATRIX; 01248 } 01249 else if (vecparams[1] == "viewproj_matrix") 01250 { 01251 acType = GpuProgramParameters::ACT_VIEWPROJ_MATRIX; 01252 } 01253 else if (vecparams[1] == "worldview_matrix") 01254 { 01255 acType = GpuProgramParameters::ACT_WORLDVIEW_MATRIX; 01256 } 01257 else if (vecparams[1] == "worldviewproj_matrix") 01258 { 01259 acType = GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX; 01260 } 01261 else if (vecparams[1] == "inverse_world_matrix") 01262 { 01263 acType = GpuProgramParameters::ACT_INVERSE_WORLD_MATRIX; 01264 } 01265 else if (vecparams[1] == "inverse_worldview_matrix") 01266 { 01267 acType = GpuProgramParameters::ACT_INVERSE_WORLDVIEW_MATRIX; 01268 } 01269 else if (vecparams[1] == "light_diffuse_colour") 01270 { 01271 acType = GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR; 01272 extras = true; 01273 } 01274 else if (vecparams[1] == "light_specular_colour") 01275 { 01276 acType = GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR; 01277 extras = true; 01278 } 01279 else if (vecparams[1] == "light_attenuation") 01280 { 01281 acType = GpuProgramParameters::ACT_LIGHT_ATTENUATION; 01282 extras = true; 01283 } 01284 else if (vecparams[1] == "light_position") 01285 { 01286 acType = GpuProgramParameters::ACT_LIGHT_POSITION; 01287 extras = true; 01288 } 01289 else if (vecparams[1] == "light_direction") 01290 { 01291 acType = GpuProgramParameters::ACT_LIGHT_DIRECTION; 01292 extras = true; 01293 } 01294 else if (vecparams[1] == "light_position_object_space") 01295 { 01296 acType = GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE; 01297 extras = true; 01298 } 01299 else if (vecparams[1] == "light_direction_object_space") 01300 { 01301 acType = GpuProgramParameters::ACT_LIGHT_DIRECTION_OBJECT_SPACE; 01302 extras = true; 01303 } 01304 else if (vecparams[1] == "ambient_light_colour") 01305 { 01306 acType = GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR; 01307 } 01308 else if (vecparams[1] == "camera_position_object_space") 01309 { 01310 acType = GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE; 01311 } 01312 else if (vecparams[1] == "texture_viewproj_matrix") 01313 { 01314 acType = GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX; 01315 } 01316 else if (vecparams[1] == "time") 01317 { 01318 // Special case! 01319 Real factor = 1.0f; 01320 if (vecparams.size() == 3) 01321 { 01322 factor = StringConverter::parseReal(vecparams[2]); 01323 } 01324 01325 context.programParams->setConstantFromTime(index, factor); 01326 return; 01327 } 01328 01329 // Do we need any extra parameters? 01330 size_t extraParam = 0; 01331 if (extras) 01332 { 01333 if (vecparams.size() != 3) 01334 { 01335 logParseError("Invalid " + commandname + " attribute - " 01336 "expected 3 parameters.", context); 01337 return; 01338 } 01339 extraParam = StringConverter::parseInt(vecparams[2]); 01340 } 01341 01342 context.programParams->setAutoConstant(index, acType, extraParam); 01343 } 01344 //----------------------------------------------------------------------- 01345 bool parseParamIndexed(String& params, MaterialScriptContext& context) 01346 { 01347 // NB skip this if the program is not supported or could not be found 01348 if (!context.program || !context.program->isSupported()) 01349 { 01350 return false; 01351 } 01352 01353 params.toLowerCase(); 01354 StringVector vecparams = params.split(" \t"); 01355 if (vecparams.size() < 3) 01356 { 01357 logParseError("Invalid param_indexed attribute - expected at least 3 parameters.", 01358 context); 01359 return false; 01360 } 01361 01362 // Get start index 01363 size_t index = StringConverter::parseInt(vecparams[0]); 01364 01365 processManualProgramParam(index, "param_indexed", vecparams, context); 01366 01367 return false; 01368 } 01369 //----------------------------------------------------------------------- 01370 bool parseParamIndexedAuto(String& params, MaterialScriptContext& context) 01371 { 01372 // NB skip this if the program is not supported or could not be found 01373 if (!context.program || !context.program->isSupported()) 01374 { 01375 return false; 01376 } 01377 01378 params.toLowerCase(); 01379 StringVector vecparams = params.split(" \t"); 01380 if (vecparams.size() != 2 && vecparams.size() != 3) 01381 { 01382 logParseError("Invalid param_indexed_auto attribute - expected 2 or 3 parameters.", 01383 context); 01384 return false; 01385 } 01386 01387 // Get start index 01388 size_t index = StringConverter::parseInt(vecparams[0]); 01389 01390 processAutoProgramParam(index, "param_indexed_auto", vecparams, context); 01391 01392 return false; 01393 } 01394 //----------------------------------------------------------------------- 01395 bool parseParamNamed(String& params, MaterialScriptContext& context) 01396 { 01397 // NB skip this if the program is not supported or could not be found 01398 if (!context.program || !context.program->isSupported()) 01399 { 01400 return false; 01401 } 01402 01403 StringVector vecparams = params.split(" \t"); 01404 if (vecparams.size() < 3) 01405 { 01406 logParseError("Invalid param_named attribute - expected at least 3 parameters.", 01407 context); 01408 return false; 01409 } 01410 01411 // Get start index from name 01412 size_t index; 01413 try { 01414 index = context.programParams->getParamIndex(vecparams[0]); 01415 } 01416 catch (Exception& e) 01417 { 01418 logParseError("Invalid param_named attribute - " + e.getFullDescription(), context); 01419 return false; 01420 } 01421 01422 // TEST 01423 /* 01424 LogManager::getSingleton().logMessage("SETTING PARAMETER " + vecparams[0] + " as index " + 01425 StringConverter::toString(index)); 01426 */ 01427 processManualProgramParam(index, "param_named", vecparams, context); 01428 01429 return false; 01430 } 01431 //----------------------------------------------------------------------- 01432 bool parseParamNamedAuto(String& params, MaterialScriptContext& context) 01433 { 01434 // NB skip this if the program is not supported or could not be found 01435 if (!context.program || !context.program->isSupported()) 01436 { 01437 return false; 01438 } 01439 01440 StringVector vecparams = params.split(" \t"); 01441 if (vecparams.size() != 2 && vecparams.size() != 3) 01442 { 01443 logParseError("Invalid param_indexed_auto attribute - expected 2 or 3 parameters.", 01444 context); 01445 return false; 01446 } 01447 01448 // Get start index from name 01449 size_t index; 01450 try { 01451 index = context.programParams->getParamIndex(vecparams[0]); 01452 } 01453 catch (Exception& e) 01454 { 01455 logParseError("Invalid param_named_auto attribute - " + e.getFullDescription(), context); 01456 return false; 01457 } 01458 01459 processAutoProgramParam(index, "param_named_auto", vecparams, context); 01460 01461 return false; 01462 } 01463 //----------------------------------------------------------------------- 01464 bool parseMaterial(String& params, MaterialScriptContext& context) 01465 { 01466 // Create a brand new material 01467 context.material = static_cast<Material*>( 01468 MaterialManager::getSingleton().create(params)); 01469 // Remove pre-created technique from defaults 01470 context.material->removeAllTechniques(); 01471 01472 // update section 01473 context.section = MSS_MATERIAL; 01474 01475 // Return TRUE because this must be followed by a { 01476 return true; 01477 } 01478 //----------------------------------------------------------------------- 01479 bool parseTechnique(String& params, MaterialScriptContext& context) 01480 { 01481 // Create a new technique 01482 context.technique = context.material->createTechnique(); 01483 01484 // update section 01485 context.section = MSS_TECHNIQUE; 01486 01487 //Increase technique level depth 01488 context.techLev += 1; 01489 01490 // Return TRUE because this must be followed by a { 01491 return true; 01492 } 01493 //----------------------------------------------------------------------- 01494 bool parsePass(String& params, MaterialScriptContext& context) 01495 { 01496 // Create a new pass 01497 context.pass = context.technique->createPass(); 01498 01499 // update section 01500 context.section = MSS_PASS; 01501 01502 //Increase pass level depth 01503 context.passLev += 1; 01504 01505 // Return TRUE because this must be followed by a { 01506 return true; 01507 } 01508 //----------------------------------------------------------------------- 01509 bool parseTextureUnit(String& params, MaterialScriptContext& context) 01510 { 01511 // Create a new texture unit 01512 context.textureUnit = context.pass->createTextureUnitState(); 01513 01514 // update section 01515 context.section = MSS_TEXTUREUNIT; 01516 01517 // Increase texture unit depth 01518 context.stateLev += 1; 01519 01520 // Return TRUE because this must be followed by a { 01521 return true; 01522 } 01523 //----------------------------------------------------------------------- 01524 bool parseVertexProgramRef(String& params, MaterialScriptContext& context) 01525 { 01526 // update section 01527 context.section = MSS_PROGRAM_REF; 01528 01529 context.program = static_cast<GpuProgram*>( 01530 GpuProgramManager::getSingleton().getByName(params)); 01531 if (context.program == 0) 01532 { 01533 // Unknown program 01534 logParseError("Invalid vertex_program_ref entry - vertex program " 01535 + params + " has not been defined.", context); 01536 return true; 01537 } 01538 01539 context.isProgramShadowCaster = false; 01540 context.isProgramShadowReceiver = false; 01541 01542 // Set the vertex program for this pass 01543 context.pass->setVertexProgram(params); 01544 01545 // Create params? Skip this if program is not supported 01546 if (context.program->isSupported()) 01547 { 01548 context.programParams = context.pass->getVertexProgramParameters(); 01549 } 01550 01551 // Return TRUE because this must be followed by a { 01552 return true; 01553 } 01554 //----------------------------------------------------------------------- 01555 bool parseShadowCasterVertexProgramRef(String& params, MaterialScriptContext& context) 01556 { 01557 // update section 01558 context.section = MSS_PROGRAM_REF; 01559 01560 context.program = static_cast<GpuProgram*>( 01561 GpuProgramManager::getSingleton().getByName(params)); 01562 if (context.program == 0) 01563 { 01564 // Unknown program 01565 logParseError("Invalid vertex_program_ref entry - vertex program " 01566 + params + " has not been defined.", context); 01567 return true; 01568 } 01569 01570 context.isProgramShadowCaster = true; 01571 context.isProgramShadowReceiver = false; 01572 01573 // Set the vertex program for this pass 01574 context.pass->setShadowCasterVertexProgram(params); 01575 01576 // Create params? Skip this if program is not supported 01577 if (context.program->isSupported()) 01578 { 01579 context.programParams = context.pass->getShadowCasterVertexProgramParameters(); 01580 } 01581 01582 // Return TRUE because this must be followed by a { 01583 return true; 01584 } 01585 //----------------------------------------------------------------------- 01586 bool parseShadowReceiverVertexProgramRef(String& params, MaterialScriptContext& context) 01587 { 01588 // update section 01589 context.section = MSS_PROGRAM_REF; 01590 01591 context.program = static_cast<GpuProgram*>( 01592 GpuProgramManager::getSingleton().getByName(params)); 01593 if (context.program == 0) 01594 { 01595 // Unknown program 01596 logParseError("Invalid vertex_program_ref entry - vertex program " 01597 + params + " has not been defined.", context); 01598 return true; 01599 } 01600 01601 context.isProgramShadowCaster = false; 01602 context.isProgramShadowReceiver = true; 01603 01604 // Set the vertex program for this pass 01605 context.pass->setShadowReceiverVertexProgram(params); 01606 01607 // Create params? Skip this if program is not supported 01608 if (context.program->isSupported()) 01609 { 01610 context.programParams = context.pass->getShadowReceiverVertexProgramParameters(); 01611 } 01612 01613 // Return TRUE because this must be followed by a { 01614 return true; 01615 } 01616 //----------------------------------------------------------------------- 01617 bool parseFragmentProgramRef(String& params, MaterialScriptContext& context) 01618 { 01619 // update section 01620 context.section = MSS_PROGRAM_REF; 01621 01622 context.program = static_cast<GpuProgram*>( 01623 GpuProgramManager::getSingleton().getByName(params)); 01624 if (context.program == 0) 01625 { 01626 // Unknown program 01627 logParseError("Invalid fragment_program_ref entry - fragment program " 01628 + params + " has not been defined.", context); 01629 return true; 01630 } 01631 01632 // Set the vertex program for this pass 01633 context.pass->setFragmentProgram(params); 01634 01635 // Create params? Skip this if program is not supported 01636 if (context.program->isSupported()) 01637 { 01638 context.programParams = context.pass->getFragmentProgramParameters(); 01639 } 01640 01641 // Return TRUE because this must be followed by a { 01642 return true; 01643 } 01644 //----------------------------------------------------------------------- 01645 bool parseVertexProgram(String& params, MaterialScriptContext& context) 01646 { 01647 // update section 01648 context.section = MSS_PROGRAM; 01649 01650 // Create new program definition-in-progress 01651 context.programDef = new MaterialScriptProgramDefinition(); 01652 context.programDef->progType = GPT_VERTEX_PROGRAM; 01653 context.programDef->supportsSkeletalAnimation = false; 01654 01655 // Get name and language code 01656 StringVector vecparams = params.split(" \t"); 01657 if (vecparams.size() != 2) 01658 { 01659 logParseError("Invalid vertex_program entry - expected " 01660 "2 parameters.", context); 01661 return true; 01662 } 01663 // Name, preserve case 01664 context.programDef->name = vecparams[0]; 01665 // language code, make lower case 01666 context.programDef->language = vecparams[1].toLowerCase(); 01667 01668 // Return TRUE because this must be followed by a { 01669 return true; 01670 } 01671 //----------------------------------------------------------------------- 01672 bool parseFragmentProgram(String& params, MaterialScriptContext& context) 01673 { 01674 // update section 01675 context.section = MSS_PROGRAM; 01676 01677 // Create new program definition-in-progress 01678 context.programDef = new MaterialScriptProgramDefinition(); 01679 context.programDef->progType = GPT_FRAGMENT_PROGRAM; 01680 context.programDef->supportsSkeletalAnimation = false; 01681 01682 // Get name and language code 01683 StringVector vecparams = params.split(" \t"); 01684 if (vecparams.size() != 2) 01685 { 01686 logParseError("Invalid fragment_program entry - expected " 01687 "2 parameters.", context); 01688 return true; 01689 } 01690 // Name, preserve case 01691 context.programDef->name = vecparams[0]; 01692 // language code, make lower case 01693 context.programDef->language = vecparams[1].toLowerCase(); 01694 01695 // Return TRUE because this must be followed by a { 01696 return true; 01697 01698 } 01699 //----------------------------------------------------------------------- 01700 bool parseProgramSource(String& params, MaterialScriptContext& context) 01701 { 01702 // Source filename, preserve case 01703 context.programDef->source = params; 01704 01705 return false; 01706 } 01707 //----------------------------------------------------------------------- 01708 bool parseProgramSkeletalAnimation(String& params, MaterialScriptContext& context) 01709 { 01710 // Source filename, preserve case 01711 context.programDef->supportsSkeletalAnimation 01712 = StringConverter::parseBool(params); 01713 01714 return false; 01715 } 01716 //----------------------------------------------------------------------- 01717 bool parseProgramSyntax(String& params, MaterialScriptContext& context) 01718 { 01719 // Syntax code, make lower case 01720 context.programDef->syntax = params; 01721 01722 return false; 01723 } 01724 //----------------------------------------------------------------------- 01725 bool parseProgramCustomParameter(String& params, MaterialScriptContext& context) 01726 { 01727 // This params object does not have the command stripped 01728 // Lower case the command, but not the value incase it's relevant 01729 // Split only up to first delimiter, program deals with the rest 01730 StringVector vecparams = params.split(" \t", 1); 01731 if (vecparams.size() != 2) 01732 { 01733 logParseError("Invalid custom program parameter entry; " 01734 "there must be a parameter name and at least one value.", 01735 context); 01736 return false; 01737 } 01738 01739 context.programDef->customParameters[vecparams[0]] = vecparams[1]; 01740 01741 return false; 01742 } 01743 01744 //----------------------------------------------------------------------- 01745 bool parseTextureSource(String& params, MaterialScriptContext& context) 01746 { 01747 params.toLowerCase(); 01748 StringVector vecparams = params.split(" \t"); 01749 if (vecparams.size() != 1) 01750 logParseError("Invalid texture source attribute - expected 1 parameter.", context); 01751 //The only param should identify which ExternalTextureSource is needed 01752 ExternalTextureSourceManager::getSingleton().SetCurrentPlugIn( vecparams[0] ); 01753 01754 if( ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0 ) 01755 { 01756 String tps; 01757 tps = StringConverter::toString( context.techLev ) + " " 01758 + StringConverter::toString( context.passLev ) + " " 01759 + StringConverter::toString( context.stateLev); 01760 01761 ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( "set_T_P_S", tps ); 01762 } 01763 01764 // update section 01765 context.section = MSS_TEXTURESOURCE; 01766 // Return TRUE because this must be followed by a { 01767 return true; 01768 } 01769 01770 //----------------------------------------------------------------------- 01771 bool parseTextureCustomParameter(String& params, MaterialScriptContext& context) 01772 { 01773 // This params object does not have the command stripped 01774 // Split only up to first delimiter, program deals with the rest 01775 StringVector vecparams = params.split(" \t", 1); 01776 if (vecparams.size() != 2) 01777 { 01778 logParseError("Invalid texture parameter entry; " 01779 "there must be a parameter name and at least one value.", 01780 context); 01781 return false; 01782 } 01783 01784 if( ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0 ) 01786 ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( vecparams[0], vecparams[1] ); 01787 01788 return false; 01789 } 01790 //----------------------------------------------------------------------- 01791 bool parseReceiveShadows(String& params, MaterialScriptContext& context) 01792 { 01793 params.toLowerCase(); 01794 if (params == "on") 01795 context.material->setReceiveShadows(true); 01796 else if (params == "off") 01797 context.material->setReceiveShadows(false); 01798 else 01799 logParseError( 01800 "Bad receive_shadows attribute, valid parameters are 'on' or 'off'.", 01801 context); 01802 01803 return false; 01804 01805 } 01806 01807 //----------------------------------------------------------------------- 01808 //----------------------------------------------------------------------- 01809 MaterialSerializer::MaterialSerializer() 01810 { 01811 // Set up root attribute parsers 01812 mRootAttribParsers.insert(AttribParserList::value_type("material", (ATTRIBUTE_PARSER)parseMaterial)); 01813 mRootAttribParsers.insert(AttribParserList::value_type("vertex_program", (ATTRIBUTE_PARSER)parseVertexProgram)); 01814 mRootAttribParsers.insert(AttribParserList::value_type("fragment_program", (ATTRIBUTE_PARSER)parseFragmentProgram)); 01815 // Set up material attribute parsers 01816 mMaterialAttribParsers.insert(AttribParserList::value_type("lod_distances", (ATTRIBUTE_PARSER)parseLodDistances)); 01817 mMaterialAttribParsers.insert(AttribParserList::value_type("receive_shadows", (ATTRIBUTE_PARSER)parseReceiveShadows)); 01818 mMaterialAttribParsers.insert(AttribParserList::value_type("technique", (ATTRIBUTE_PARSER)parseTechnique)); 01819 // Set up technique attribute parsers 01820 mTechniqueAttribParsers.insert(AttribParserList::value_type("lod_index", (ATTRIBUTE_PARSER)parseLodIndex)); 01821 mTechniqueAttribParsers.insert(AttribParserList::value_type("pass", (ATTRIBUTE_PARSER)parsePass)); 01822 // Set up pass attribute parsers 01823 mPassAttribParsers.insert(AttribParserList::value_type("ambient", (ATTRIBUTE_PARSER)parseAmbient)); 01824 mPassAttribParsers.insert(AttribParserList::value_type("diffuse", (ATTRIBUTE_PARSER)parseDiffuse)); 01825 mPassAttribParsers.insert(AttribParserList::value_type("specular", (ATTRIBUTE_PARSER)parseSpecular)); 01826 mPassAttribParsers.insert(AttribParserList::value_type("emissive", (ATTRIBUTE_PARSER)parseEmissive)); 01827 mPassAttribParsers.insert(AttribParserList::value_type("scene_blend", (ATTRIBUTE_PARSER)parseSceneBlend)); 01828 mPassAttribParsers.insert(AttribParserList::value_type("depth_check", (ATTRIBUTE_PARSER)parseDepthCheck)); 01829 mPassAttribParsers.insert(AttribParserList::value_type("depth_write", (ATTRIBUTE_PARSER)parseDepthWrite)); 01830 mPassAttribParsers.insert(AttribParserList::value_type("depth_func", (ATTRIBUTE_PARSER)parseDepthFunc)); 01831 mPassAttribParsers.insert(AttribParserList::value_type("colour_write", (ATTRIBUTE_PARSER)parseColourWrite)); 01832 mPassAttribParsers.insert(AttribParserList::value_type("cull_hardware", (ATTRIBUTE_PARSER)parseCullHardware)); 01833 mPassAttribParsers.insert(AttribParserList::value_type("cull_software", (ATTRIBUTE_PARSER)parseCullSoftware)); 01834 mPassAttribParsers.insert(AttribParserList::value_type("lighting", (ATTRIBUTE_PARSER)parseLighting)); 01835 mPassAttribParsers.insert(AttribParserList::value_type("fog_override", (ATTRIBUTE_PARSER)parseFogging)); 01836 mPassAttribParsers.insert(AttribParserList::value_type("shading", (ATTRIBUTE_PARSER)parseShading)); 01837 mPassAttribParsers.insert(AttribParserList::value_type("depth_bias", (ATTRIBUTE_PARSER)parseDepthBias)); 01838 mPassAttribParsers.insert(AttribParserList::value_type("texture_unit", (ATTRIBUTE_PARSER)parseTextureUnit)); 01839 mPassAttribParsers.insert(AttribParserList::value_type("vertex_program_ref", (ATTRIBUTE_PARSER)parseVertexProgramRef)); 01840 mPassAttribParsers.insert(AttribParserList::value_type("shadow_caster_vertex_program_ref", (ATTRIBUTE_PARSER)parseShadowCasterVertexProgramRef)); 01841 mPassAttribParsers.insert(AttribParserList::value_type("shadow_receiver_vertex_program_ref", (ATTRIBUTE_PARSER)parseShadowReceiverVertexProgramRef)); 01842 mPassAttribParsers.insert(AttribParserList::value_type("fragment_program_ref", (ATTRIBUTE_PARSER)parseFragmentProgramRef)); 01843 mPassAttribParsers.insert(AttribParserList::value_type("max_lights", (ATTRIBUTE_PARSER)parseMaxLights)); 01844 mPassAttribParsers.insert(AttribParserList::value_type("iteration", (ATTRIBUTE_PARSER)parseIteration)); 01845 mTextureUnitAttribParsers.insert(AttribParserList::value_type("texture_source", (ATTRIBUTE_PARSER)parseTextureSource)); 01846 01847 // Set up texture unit attribute parsers 01848 mTextureUnitAttribParsers.insert(AttribParserList::value_type("texture", (ATTRIBUTE_PARSER)parseTexture)); 01849 mTextureUnitAttribParsers.insert(AttribParserList::value_type("anim_texture", (ATTRIBUTE_PARSER)parseAnimTexture)); 01850 mTextureUnitAttribParsers.insert(AttribParserList::value_type("cubic_texture", (ATTRIBUTE_PARSER)parseCubicTexture)); 01851 mTextureUnitAttribParsers.insert(AttribParserList::value_type("tex_coord_set", (ATTRIBUTE_PARSER)parseTexCoord)); 01852 mTextureUnitAttribParsers.insert(AttribParserList::value_type("tex_address_mode", (ATTRIBUTE_PARSER)parseTexAddressMode)); 01853 mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op", (ATTRIBUTE_PARSER)parseColourOp)); 01854 mTextureUnitAttribParsers.insert(AttribParserList::value_type("alpha_rejection", (ATTRIBUTE_PARSER)parseAlphaRejection)); 01855 mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op_ex", (ATTRIBUTE_PARSER)parseColourOpEx)); 01856 mTextureUnitAttribParsers.insert(AttribParserList::value_type("colour_op_multipass_fallback", (ATTRIBUTE_PARSER)parseColourOpFallback)); 01857 mTextureUnitAttribParsers.insert(AttribParserList::value_type("alpha_op_ex", (ATTRIBUTE_PARSER)parseAlphaOpEx)); 01858 mTextureUnitAttribParsers.insert(AttribParserList::value_type("env_map", (ATTRIBUTE_PARSER)parseEnvMap)); 01859 mTextureUnitAttribParsers.insert(AttribParserList::value_type("scroll", (ATTRIBUTE_PARSER)parseScroll)); 01860 mTextureUnitAttribParsers.insert(AttribParserList::value_type("scroll_anim", (ATTRIBUTE_PARSER)parseScrollAnim)); 01861 mTextureUnitAttribParsers.insert(AttribParserList::value_type("rotate", (ATTRIBUTE_PARSER)parseRotate)); 01862 mTextureUnitAttribParsers.insert(AttribParserList::value_type("rotate_anim", (ATTRIBUTE_PARSER)parseRotateAnim)); 01863 mTextureUnitAttribParsers.insert(AttribParserList::value_type("scale", (ATTRIBUTE_PARSER)parseScale)); 01864 mTextureUnitAttribParsers.insert(AttribParserList::value_type("wave_xform", (ATTRIBUTE_PARSER)parseWaveXform)); 01865 mTextureUnitAttribParsers.insert(AttribParserList::value_type("filtering", (ATTRIBUTE_PARSER)parseFiltering)); 01866 mTextureUnitAttribParsers.insert(AttribParserList::value_type("max_anisotropy", (ATTRIBUTE_PARSER)parseAnisotropy)); 01867 01868 // Set up program reference attribute parsers 01869 mProgramRefAttribParsers.insert(AttribParserList::value_type("param_indexed", (ATTRIBUTE_PARSER)parseParamIndexed)); 01870 mProgramRefAttribParsers.insert(AttribParserList::value_type("param_indexed_auto", (ATTRIBUTE_PARSER)parseParamIndexedAuto)); 01871 mProgramRefAttribParsers.insert(AttribParserList::value_type("param_named", (ATTRIBUTE_PARSER)parseParamNamed)); 01872 mProgramRefAttribParsers.insert(AttribParserList::value_type("param_named_auto", (ATTRIBUTE_PARSER)parseParamNamedAuto)); 01873 mProgramRefAttribParsers.insert(AttribParserList::value_type("param_named", (ATTRIBUTE_PARSER)parseParamNamedAuto)); 01874 01875 // Set up program definition attribute parsers 01876 mProgramAttribParsers.insert(AttribParserList::value_type("source", (ATTRIBUTE_PARSER)parseProgramSource)); 01877 mProgramAttribParsers.insert(AttribParserList::value_type("syntax", (ATTRIBUTE_PARSER)parseProgramSyntax)); 01878 mProgramAttribParsers.insert(AttribParserList::value_type("includes_skeletal_animation", (ATTRIBUTE_PARSER)parseProgramSkeletalAnimation)); 01879 01880 01881 mScriptContext.section = MSS_NONE; 01882 mScriptContext.material = 0; 01883 mScriptContext.technique = 0; 01884 mScriptContext.pass = 0; 01885 mScriptContext.textureUnit = 0; 01886 mScriptContext.program = 0; 01887 mScriptContext.lineNo = 0; 01888 mScriptContext.filename = ""; 01889 mScriptContext.techLev = -1; 01890 mScriptContext.passLev = -1; 01891 mScriptContext.stateLev = -1; 01892 01893 mBuffer = ""; 01894 } 01895 01896 //----------------------------------------------------------------------- 01897 void MaterialSerializer::parseScript(DataChunk& chunk, const String& filename) 01898 { 01899 String line; 01900 bool nextIsOpenBrace = false; 01901 01902 mScriptContext.section = MSS_NONE; 01903 mScriptContext.material = 0; 01904 mScriptContext.technique = 0; 01905 mScriptContext.pass = 0; 01906 mScriptContext.textureUnit = 0; 01907 mScriptContext.program = 0; 01908 mScriptContext.lineNo = 0; 01909 mScriptContext.techLev = -1; 01910 mScriptContext.passLev = -1; 01911 mScriptContext.stateLev = -1; 01912 mScriptContext.filename = filename; 01913 while(!chunk.isEOF()) 01914 { 01915 line = chunk.getLine(); 01916 mScriptContext.lineNo++; 01917 01918 // DEBUG LINE 01919 //LogManager::getSingleton().logMessage("About to attempt line: " + 01920 // StringConverter::toString(mScriptContext.lineNo)); 01921 01922 // Ignore comments & blanks 01923 if (!(line.length() == 0 || line.substr(0,2) == "//")) 01924 { 01925 if (nextIsOpenBrace) 01926 { 01927 // NB, parser will have changed context already 01928 if (line != "{") 01929 { 01930 logParseError("Expecting '{' but got " + 01931 line + " instead.", mScriptContext); 01932 } 01933 nextIsOpenBrace = false; 01934 } 01935 else 01936 { 01937 nextIsOpenBrace = parseScriptLine(line); 01938 } 01939 01940 } 01941 } 01942 01943 // Check all braces were closed 01944 if (mScriptContext.section != MSS_NONE) 01945 { 01946 logParseError("Unexpected end of file.", mScriptContext); 01947 } 01948 01949 } 01950 //----------------------------------------------------------------------- 01951 bool MaterialSerializer::parseScriptLine(String& line) 01952 { 01953 switch(mScriptContext.section) 01954 { 01955 case MSS_NONE: 01956 if (line == "}") 01957 { 01958 logParseError("Unexpected terminating brace.", mScriptContext); 01959 return false; 01960 } 01961 else 01962 { 01963 // find & invoke a parser 01964 return invokeParser(line, mRootAttribParsers); 01965 } 01966 break; 01967 case MSS_MATERIAL: 01968 if (line == "}") 01969 { 01970 // End of material 01971 mScriptContext.section = MSS_NONE; 01972 mScriptContext.material = NULL; 01973 //Reset all levels for next material 01974 mScriptContext.passLev = -1; 01975 mScriptContext.stateLev= -1; 01976 mScriptContext.techLev = -1; 01977 } 01978 else 01979 { 01980 // find & invoke a parser 01981 return invokeParser(line, mMaterialAttribParsers); 01982 } 01983 break; 01984 case MSS_TECHNIQUE: 01985 if (line == "}") 01986 { 01987 // End of technique 01988 mScriptContext.section = MSS_MATERIAL; 01989 mScriptContext.technique = NULL; 01990 mScriptContext.passLev = -1; //Reset pass level (yes, the pass level) 01991 } 01992 else 01993 { 01994 // find & invoke a parser 01995 return invokeParser(line, mTechniqueAttribParsers); 01996 } 01997 break; 01998 case MSS_PASS: 01999 if (line == "}") 02000 { 02001 // End of pass 02002 mScriptContext.section = MSS_TECHNIQUE; 02003 mScriptContext.pass = NULL; 02004 mScriptContext.stateLev = -1; //Reset state level (yes, the state level) 02005 } 02006 else 02007 { 02008 // find & invoke a parser 02009 return invokeParser(line, mPassAttribParsers); 02010 } 02011 break; 02012 case MSS_TEXTUREUNIT: 02013 if (line == "}") 02014 { 02015 // End of texture unit 02016 mScriptContext.section = MSS_PASS; 02017 mScriptContext.textureUnit = NULL; 02018 } 02019 else 02020 { 02021 // find & invoke a parser 02022 return invokeParser(line, mTextureUnitAttribParsers); 02023 } 02024 break; 02025 case MSS_TEXTURESOURCE: 02026 if( line == "}" ) 02027 { 02028 //End texture source section 02029 //Finish creating texture here 02030 String sMaterialName = mScriptContext.material->getName(); 02031 if( ExternalTextureSourceManager::getSingleton().getCurrentPlugIn() != 0) 02032 ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->createDefinedTexture( sMaterialName ); 02033 //Revert back to texture unit 02034 mScriptContext.section = MSS_TEXTUREUNIT; 02035 } 02036 else 02037 { 02038 // custom texture parameter, use original line 02039 parseTextureCustomParameter(line, mScriptContext); 02040 } 02041 break; 02042 case MSS_PROGRAM_REF: 02043 if (line == "}") 02044 { 02045 // End of program 02046 mScriptContext.section = MSS_PASS; 02047 mScriptContext.program = NULL; 02048 } 02049 else 02050 { 02051 // find & invoke a parser 02052 return invokeParser(line, mProgramRefAttribParsers); 02053 } 02054 break; 02055 case MSS_PROGRAM: 02056 // Program definitions are slightly different, they are deferred 02057 // until all the information required is known 02058 if (line == "}") 02059 { 02060 // End of program 02061 finishProgramDefinition(); 02062 mScriptContext.section = MSS_NONE; 02063 delete mScriptContext.programDef; 02064 mScriptContext.programDef = NULL; 02065 } 02066 else 02067 { 02068 // find & invoke a parser 02069 // do this manually because we want to call a custom 02070 // routine when the parser is not found 02071 // First, split line on first divisor only 02072 StringVector splitCmd = line.split(" \t", 1); 02073 // Find attribute parser 02074 AttribParserList::iterator iparser = mProgramAttribParsers.find(splitCmd[0]); 02075 if (iparser == mProgramAttribParsers.end()) 02076 { 02077 // custom parameter, use original line 02078 parseProgramCustomParameter(line, mScriptContext); 02079 } 02080 else 02081 { 02082 String cmd = splitCmd.size() >= 2? splitCmd[1]:String::BLANK; 02083 // Use parser with remainder 02084 iparser->second(cmd, mScriptContext ); 02085 } 02086 02087 } 02088 break; 02089 }; 02090 02091 return false; 02092 } 02093 //----------------------------------------------------------------------- 02094 void MaterialSerializer::finishProgramDefinition(void) 02095 { 02096 // Now it is time to create the program and propagate the parameters 02097 MaterialScriptProgramDefinition* def = mScriptContext.programDef; 02098 if (def->language == "asm") 02099 { 02100 // Native assembler 02101 // Validate 02102 if (def->source.empty()) 02103 { 02104 logParseError("Invalid program definition for " + def->name + 02105 ", you must specify a source file.", mScriptContext); 02106 } 02107 if (def->syntax.empty()) 02108 { 02109 logParseError("Invalid program definition for " + def->name + 02110 ", you must specify a syntax code.", mScriptContext); 02111 } 02112 // Create 02113 GpuProgram* gp = GpuProgramManager::getSingleton(). 02114 createProgram(def->name, def->source, def->progType, def->syntax); 02115 gp->setSkeletalAnimationIncluded(def->supportsSkeletalAnimation); 02116 } 02117 else 02118 { 02119 // High-level program 02120 // Validate 02121 if (def->source.empty()) 02122 { 02123 logParseError("Invalid program definition for " + def->name + 02124 ", you must specify a source file.", mScriptContext); 02125 } 02126 // Create 02127 try 02128 { 02129 HighLevelGpuProgram* gp = HighLevelGpuProgramManager::getSingleton(). 02130 createProgram(def->name, def->language, def->progType); 02131 // Set source file 02132 gp->setSourceFile(def->source); 02133 // Skel animation supported 02134 gp->setSkeletalAnimationIncluded(def->supportsSkeletalAnimation); 02135 02136 // Set custom parameters 02137 std::map<String, String>::const_iterator i, iend; 02138 iend = def->customParameters.end(); 02139 for (i = def->customParameters.begin(); i != iend; ++i) 02140 { 02141 if (!gp->setParameter(i->first, i->second)) 02142 { 02143 logParseError("Error in program " + def->name + 02144 " parameter " + i->first + " is not valid.", mScriptContext); 02145 } 02146 } 02147 } 02148 catch (Exception& e) 02149 { 02150 LogManager::getSingleton().logMessage("Could not create GPU program '" 02151 + def->name + "', error reported was: " + e.getFullDescription()); 02152 } 02153 } 02154 } 02155 //----------------------------------------------------------------------- 02156 bool MaterialSerializer::invokeParser(String& line, AttribParserList& parsers) 02157 { 02158 // First, split line on first divisor only 02159 StringVector splitCmd = line.split(" \t", 1); 02160 // Find attribute parser 02161 AttribParserList::iterator iparser = parsers.find(splitCmd[0]); 02162 if (iparser == parsers.end()) 02163 { 02164 // BAD command. BAD! 02165 logParseError("Unrecognised command: " + splitCmd[0], mScriptContext); 02166 return false; 02167 } 02168 else 02169 { 02170 String cmd = splitCmd.size() >= 2 ? splitCmd[1] : String::BLANK; 02171 // Use parser, make sure we have 2 params before using splitCmd[1] 02172 return iparser->second( cmd, mScriptContext ); 02173 } 02174 } 02175 //----------------------------------------------------------------------- 02176 void MaterialSerializer::exportMaterial(const Material *pMat, const String &fileName, bool exportDefaults) 02177 { 02178 clearQueue(); 02179 mDefaults = exportDefaults; 02180 writeMaterial(pMat); 02181 exportQueued(fileName); 02182 } 02183 //----------------------------------------------------------------------- 02184 void MaterialSerializer::exportQueued(const String &fileName) 02185 { 02186 if (mBuffer == "") 02187 Except(Exception::ERR_INVALIDPARAMS, "Queue is empty !", "MaterialSerializer::exportQueued"); 02188 02189 LogManager::getSingleton().logMessage("MaterialSerializer : writing material(s) to material script : " + fileName, LML_CRITICAL); 02190 FILE *fp; 02191 fp = fopen(fileName.c_str(), "w"); 02192 if (!fp) 02193 Except(Exception::ERR_CANNOT_WRITE_TO_FILE, "Cannot create material file.", 02194 "MaterialSerializer::export"); 02195 02196 fputs(mBuffer.c_str(), fp); 02197 fclose(fp); 02198 LogManager::getSingleton().logMessage("MaterialSerializer : done.", LML_CRITICAL); 02199 clearQueue(); 02200 } 02201 //----------------------------------------------------------------------- 02202 void MaterialSerializer::queueForExport(const Material *pMat, bool clearQueued, bool exportDefaults) 02203 { 02204 if (clearQueued) 02205 clearQueue(); 02206 02207 mDefaults = exportDefaults; 02208 writeMaterial(pMat); 02209 } 02210 //----------------------------------------------------------------------- 02211 void MaterialSerializer::clearQueue() 02212 { 02213 mBuffer = ""; 02214 } 02215 //----------------------------------------------------------------------- 02216 const String &MaterialSerializer::getQueuedAsString() const 02217 { 02218 return mBuffer; 02219 } 02220 //----------------------------------------------------------------------- 02221 void MaterialSerializer::writeMaterial(const Material *pMat) 02222 { 02223 LogManager::getSingleton().logMessage("MaterialSerializer : writing material " + pMat->getName() + " to queue.", LML_CRITICAL); 02224 // Material name 02225 writeAttribute(0, "material " + pMat->getName()); 02226 beginSection(0); 02227 { 02228 // Write LOD information 02229 Material::LodDistanceIterator distIt = pMat->getLodDistanceIterator(); 02230 // Skip zero value 02231 if (distIt.hasMoreElements()) 02232 distIt.getNext(); 02233 String attributeVal; 02234 while (distIt.hasMoreElements()) 02235 { 02236 Real sqdist = distIt.getNext(); 02237 attributeVal.append(StringConverter::toString(Math::Sqrt(sqdist))); 02238 if (distIt.hasMoreElements()) 02239 attributeVal.append(" "); 02240 } 02241 if (!attributeVal.empty()) 02242 { 02243 writeAttribute(1, "lod_distances"); 02244 writeValue(attributeVal); 02245 } 02246 02247 02248 // Shadow receive 02249 if (mDefaults || 02250 pMat->getReceiveShadows() != true) 02251 { 02252 writeAttribute(1, "receive_shadows"); 02253 writeValue(pMat->getReceiveShadows() ? "on" : "off"); 02254 } 02255 // Iterate over techniques 02256 Material::TechniqueIterator it = 02257 const_cast<Material*>(pMat)->getTechniqueIterator(); 02258 while (it.hasMoreElements()) 02259 { 02260 writeTechnique(it.getNext()); 02261 } 02262 } 02263 endSection(0); 02264 } 02265 //----------------------------------------------------------------------- 02266 void MaterialSerializer::writeTechnique(const Technique* pTech) 02267 { 02268 // Technique header 02269 writeAttribute(1, "technique"); 02270 beginSection(1); 02271 { 02272 // Iterate over passes 02273 Technique::PassIterator it = const_cast<Technique*>(pTech)->getPassIterator(); 02274 while (it.hasMoreElements()) 02275 { 02276 writePass(it.getNext()); 02277 } 02278 } 02279 endSection(1); 02280 02281 } 02282 //----------------------------------------------------------------------- 02283 void MaterialSerializer::writePass(const Pass* pPass) 02284 { 02285 writeAttribute(2, "pass"); 02286 beginSection(2); 02287 { 02288 //lighting 02289 if (mDefaults || 02290 pPass->getLightingEnabled() != true) 02291 { 02292 writeAttribute(3, "lighting"); 02293 writeValue(pPass->getLightingEnabled() ? "on" : "off"); 02294 } 02295 // max_lights 02296 if (mDefaults || 02297 pPass->getMaxSimultaneousLights() != OGRE_MAX_SIMULTANEOUS_LIGHTS) 02298 { 02299 writeAttribute(3, "max_lights"); 02300 writeValue(StringConverter::toString(pPass->getMaxSimultaneousLights())); 02301 } 02302 // iteration 02303 if (mDefaults || 02304 pPass->getRunOncePerLight()) 02305 { 02306 writeAttribute(3, "iteration"); 02307 writeValue(pPass->getRunOncePerLight() ? "once_per_light" : "once"); 02308 if (pPass->getRunOncePerLight() && pPass->getRunOnlyForOneLightType()) 02309 { 02310 switch (pPass->getOnlyLightType()) 02311 { 02312 case Light::LT_DIRECTIONAL: 02313 writeValue("directional"); 02314 break; 02315 case Light::LT_POINT: 02316 writeValue("point"); 02317 break; 02318 case Light::LT_SPOTLIGHT: 02319 writeValue("spot"); 02320 break; 02321 }; 02322 } 02323 } 02324 02325 02326 if (pPass->getLightingEnabled()) 02327 { 02328 // Ambient 02329 if (mDefaults || 02330 pPass->getAmbient().r != 1 || 02331 pPass->getAmbient().g != 1 || 02332 pPass->getAmbient().b != 1 || 02333 pPass->getAmbient().a != 1) 02334 { 02335 writeAttribute(3, "ambient"); 02336 writeColourValue(pPass->getAmbient(), true); 02337 } 02338 02339 // Diffuse 02340 if (mDefaults || 02341 pPass->getDiffuse().r != 1 || 02342 pPass->getDiffuse().g != 1 || 02343 pPass->getDiffuse().b != 1 || 02344 pPass->getDiffuse().a != 1) 02345 { 02346 writeAttribute(3, "diffuse"); 02347 writeColourValue(pPass->getDiffuse(), true); 02348 } 02349 02350 // Specular 02351 if (mDefaults || 02352 pPass->getSpecular().r != 0 || 02353 pPass->getSpecular().g != 0 || 02354 pPass->getSpecular().b != 0 || 02355 pPass->getSpecular().a != 1 || 02356 pPass->getShininess() != 0) 02357 { 02358 writeAttribute(3, "specular"); 02359 writeColourValue(pPass->getSpecular(), true); 02360 writeValue(StringConverter::toString(pPass->getShininess())); 02361 } 02362 02363 // Emissive 02364 if (mDefaults || 02365 pPass->getSelfIllumination().r != 0 || 02366 pPass->getSelfIllumination().g != 0 || 02367 pPass->getSelfIllumination().b != 0 || 02368 pPass->getSelfIllumination().a != 1) 02369 { 02370 writeAttribute(3, "emissive"); 02371 writeColourValue(pPass->getSelfIllumination(), true); 02372 } 02373 } 02374 02375 // scene blend factor 02376 if (mDefaults || 02377 pPass->getSourceBlendFactor() != SBF_ONE || 02378 pPass->getDestBlendFactor() != SBF_ZERO) 02379 { 02380 writeAttribute(3, "scene_blend"); 02381 writeSceneBlendFactor(pPass->getSourceBlendFactor(), pPass->getDestBlendFactor()); 02382 } 02383 02384 02385 //depth check 02386 if (mDefaults || 02387 pPass->getDepthCheckEnabled() != true) 02388 { 02389 writeAttribute(3, "depth_check"); 02390 writeValue(pPass->getDepthCheckEnabled() ? "on" : "off"); 02391 } 02392 02393 //depth write 02394 if (mDefaults || 02395 pPass->getDepthWriteEnabled() != true) 02396 { 02397 writeAttribute(3, "depth_write"); 02398 writeValue(pPass->getDepthWriteEnabled() ? "on" : "off"); 02399 } 02400 02401 //depth function 02402 if (mDefaults || 02403 pPass->getDepthFunction() != CMPF_LESS_EQUAL) 02404 { 02405 writeAttribute(3, "depth_func"); 02406 writeCompareFunction(pPass->getDepthFunction()); 02407 } 02408 02409 //depth bias 02410 if (mDefaults || 02411 pPass->getDepthBias() != 0) 02412 { 02413 writeAttribute(3, "depth_bias"); 02414 writeValue(StringConverter::toString(pPass->getDepthBias())); 02415 } 02416 02417 // hardware culling mode 02418 if (mDefaults || 02419 pPass->getCullingMode() != CULL_CLOCKWISE) 02420 { 02421 CullingMode hcm = pPass->getCullingMode(); 02422 writeAttribute(3, "cull_hardware"); 02423 switch (hcm) 02424 { 02425 case CULL_NONE : 02426 writeValue("none"); 02427 break; 02428 case CULL_CLOCKWISE : 02429 writeValue("clockwise"); 02430 break; 02431 case CULL_ANTICLOCKWISE : 02432 writeValue("anticlockwise"); 02433 break; 02434 } 02435 } 02436 02437 // software culling mode 02438 if (mDefaults || 02439 pPass->getManualCullingMode() != MANUAL_CULL_BACK) 02440 { 02441 ManualCullingMode scm = pPass->getManualCullingMode(); 02442 writeAttribute(3, "cull_software"); 02443 switch (scm) 02444 { 02445 case MANUAL_CULL_NONE : 02446 writeValue("none"); 02447 break; 02448 case MANUAL_CULL_BACK : 02449 writeValue("back"); 02450 break; 02451 case MANUAL_CULL_FRONT : 02452 writeValue("front"); 02453 break; 02454 } 02455 } 02456 02457 //shading 02458 if (mDefaults || 02459 pPass->getShadingMode() != SO_GOURAUD) 02460 { 02461 writeAttribute(3, "shading"); 02462 switch (pPass->getShadingMode()) 02463 { 02464 case SO_FLAT: 02465 writeValue("flat"); 02466 break; 02467 case SO_GOURAUD: 02468 writeValue("gouraud"); 02469 break; 02470 case SO_PHONG: 02471 writeValue("phong"); 02472 break; 02473 } 02474 } 02475 02476 02477 //fog override 02478 if (mDefaults || 02479 pPass->getFogOverride() != false) 02480 { 02481 writeAttribute(3, "fog_override"); 02482 writeValue(pPass->getFogOverride() ? "true" : "false"); 02483 if (pPass->getFogOverride()) 02484 { 02485 switch (pPass->getFogMode()) 02486 { 02487 case FOG_NONE: 02488 writeValue("none"); 02489 break; 02490 case FOG_LINEAR: 02491 writeValue("linear"); 02492 break; 02493 case FOG_EXP2: 02494 writeValue("exp2"); 02495 break; 02496 case FOG_EXP: 02497 writeValue("exp"); 02498 break; 02499 } 02500 02501 if (pPass->getFogMode() != FOG_NONE) 02502 { 02503 writeColourValue(pPass->getFogColour()); 02504 writeValue(StringConverter::toString(pPass->getFogDensity())); 02505 writeValue(StringConverter::toString(pPass->getFogStart())); 02506 writeValue(StringConverter::toString(pPass->getFogEnd())); 02507 } 02508 } 02509 } 02510 02511 // Nested texture layers 02512 Pass::TextureUnitStateIterator it = const_cast<Pass*>(pPass)->getTextureUnitStateIterator(); 02513 while(it.hasMoreElements()) 02514 { 02515 writeTextureUnit(it.getNext()); 02516 } 02517 } 02518 endSection(2); 02519 LogManager::getSingleton().logMessage("MaterialSerializer : done.", LML_CRITICAL); 02520 } 02521 //----------------------------------------------------------------------- 02522 String MaterialSerializer::convertFiltering(FilterOptions fo) 02523 { 02524 switch (fo) 02525 { 02526 case FO_NONE: 02527 return "none"; 02528 case FO_POINT: 02529 return "point"; 02530 case FO_LINEAR: 02531 return "linear"; 02532 case FO_ANISOTROPIC: 02533 return "anisotropic"; 02534 } 02535 02536 return "point"; 02537 } 02538 //----------------------------------------------------------------------- 02539 void MaterialSerializer::writeTextureUnit(const TextureUnitState *pTex) 02540 { 02541 LogManager::getSingleton().logMessage("MaterialSerializer : parsing texture layer.", LML_CRITICAL); 02542 mBuffer += "\n"; 02543 writeAttribute(3, "texture_unit"); 02544 beginSection(3); 02545 { 02546 //texture name 02547 if (pTex->getNumFrames() == 1 && pTex->getTextureName() != "" && !pTex->isCubic()) 02548 { 02549 writeAttribute(4, "texture"); 02550 writeValue(pTex->getTextureName()); 02551 switch (pTex->getTextureType()) 02552 { 02553 case TEX_TYPE_1D: 02554 writeValue("1d"); 02555 break; 02556 case TEX_TYPE_2D: 02557 // nothing, this is the default 02558 break; 02559 case TEX_TYPE_3D: 02560 writeValue("3d"); 02561 break; 02562 case TEX_TYPE_CUBE_MAP: 02563 // nothing, deal with this as cubic_texture since it copes with all variants 02564 break; 02565 default: 02566 break; 02567 }; 02568 } 02569 02570 //anim. texture 02571 if (pTex->getNumFrames() > 1 && !pTex->isCubic()) 02572 { 02573 writeAttribute(4, "anim_texture"); 02574 for (unsigned int n = 0; n < pTex->getNumFrames(); n++) 02575 writeValue(pTex->getFrameTextureName(n)); 02576 writeValue(StringConverter::toString(pTex->getAnimationDuration())); 02577 } 02578 02579 //cubic texture 02580 if (pTex->isCubic()) 02581 { 02582 writeAttribute(4, "cubic_texture"); 02583 for (unsigned int n = 0; n < pTex->getNumFrames(); n++) 02584 writeValue(pTex->getFrameTextureName(n)); 02585 02586 //combinedUVW/separateUW 02587 if (pTex->getTextureType() == TEX_TYPE_CUBE_MAP) 02588 writeValue("combinedUVW"); 02589 else 02590 writeValue("separateUV"); 02591 } 02592 02593 //anisotropy level 02594 if (mDefaults || 02595 pTex->getTextureAnisotropy() != 1) 02596 { 02597 writeAttribute(4, "max_anisotropy"); 02598 writeValue(StringConverter::toString(pTex->getTextureAnisotropy())); 02599 } 02600 02601 //texture coordinate set 02602 if (mDefaults || 02603 pTex->getTextureCoordSet() != 0) 02604 { 02605 writeAttribute(4, "tex_coord_set"); 02606 writeValue(StringConverter::toString(pTex->getTextureCoordSet())); 02607 } 02608 02609 //addressing mode 02610 if (mDefaults || 02611 pTex->getTextureAddressingMode() != Ogre::TextureUnitState::TAM_WRAP) 02612 { 02613 writeAttribute(4, "tex_address_mode"); 02614 switch (pTex->getTextureAddressingMode()) 02615 { 02616 case Ogre::TextureUnitState::TAM_CLAMP: 02617 writeValue("clamp"); 02618 break; 02619 case Ogre::TextureUnitState::TAM_MIRROR: 02620 writeValue("mirror"); 02621 break; 02622 case Ogre::TextureUnitState::TAM_WRAP: 02623 writeValue("wrap"); 02624 break; 02625 } 02626 } 02627 02628 //filtering 02629 if (mDefaults || 02630 pTex->getTextureFiltering(FT_MIN) != FO_LINEAR || 02631 pTex->getTextureFiltering(FT_MAG) != FO_LINEAR || 02632 pTex->getTextureFiltering(FT_MIP) != FO_POINT) 02633 { 02634 writeAttribute(4, "filtering"); 02635 writeValue( 02636 convertFiltering(pTex->getTextureFiltering(FT_MIN)) 02637 + " " 02638 + convertFiltering(pTex->getTextureFiltering(FT_MAG)) 02639 + " " 02640 + convertFiltering(pTex->getTextureFiltering(FT_MIP))); 02641 } 02642 02643 // alpha_rejection 02644 if (mDefaults || 02645 pTex->getAlphaRejectFunction() != CMPF_ALWAYS_PASS || 02646 pTex->getAlphaRejectValue() != 0) 02647 { 02648 writeAttribute(4, "alpha_rejection"); 02649 writeCompareFunction(pTex->getAlphaRejectFunction()); 02650 writeValue(StringConverter::toString(pTex->getAlphaRejectValue())); 02651 } 02652 02653 // colour_op_ex 02654 if (mDefaults || 02655 pTex->getColourBlendMode().operation != LBX_MODULATE || 02656 pTex->getColourBlendMode().source1 != LBS_TEXTURE || 02657 pTex->getColourBlendMode().source2 != LBS_CURRENT) 02658 { 02659 writeAttribute(4, "colour_op_ex"); 02660 writeLayerBlendOperationEx(pTex->getColourBlendMode().operation); 02661 writeLayerBlendSource(pTex->getColourBlendMode().source1); 02662 writeLayerBlendSource(pTex->getColourBlendMode().source2); 02663 if (pTex->getColourBlendMode().operation == LBX_BLEND_MANUAL) 02664 writeValue(StringConverter::toString(pTex->getColourBlendMode().factor)); 02665 if (pTex->getColourBlendMode().source1 == LBS_MANUAL) 02666 writeColourValue(pTex->getColourBlendMode().colourArg1, false); 02667 if (pTex->getColourBlendMode().source2 == LBS_MANUAL) 02668 writeColourValue(pTex->getColourBlendMode().colourArg2, false); 02669 02670 //colour_op_multipass_fallback 02671 writeAttribute(4, "colour_op_multipass_fallback"); 02672 writeSceneBlendFactor(pTex->getColourBlendFallbackSrc()); 02673 writeSceneBlendFactor(pTex->getColourBlendFallbackDest()); 02674 } 02675 02676 // alpha_op_ex 02677 if (mDefaults || 02678 pTex->getAlphaBlendMode().operation != LBX_MODULATE || 02679 pTex->getAlphaBlendMode().source1 != LBS_TEXTURE || 02680 pTex->getAlphaBlendMode().source2 != LBS_CURRENT) 02681 { 02682 writeAttribute(4, "alpha_op_ex"); 02683 writeLayerBlendOperationEx(pTex->getAlphaBlendMode().operation); 02684 writeLayerBlendSource(pTex->getAlphaBlendMode().source1); 02685 writeLayerBlendSource(pTex->getAlphaBlendMode().source2); 02686 if (pTex->getAlphaBlendMode().operation == LBX_BLEND_MANUAL) 02687 writeValue(StringConverter::toString(pTex->getAlphaBlendMode().factor)); 02688 else if (pTex->getAlphaBlendMode().source1 == LBS_MANUAL) 02689 writeValue(StringConverter::toString(pTex->getAlphaBlendMode().alphaArg1)); 02690 else if (pTex->getAlphaBlendMode().source2 == LBS_MANUAL) 02691 writeValue(StringConverter::toString(pTex->getAlphaBlendMode().alphaArg2)); 02692 } 02693 02694 // rotate 02695 if (mDefaults || 02696 pTex->getTextureRotate() != 0) 02697 { 02698 writeAttribute(4, "rotate"); 02699 writeValue(StringConverter::toString(pTex->getTextureRotate())); 02700 } 02701 02702 // scroll 02703 if (mDefaults || 02704 pTex->getTextureUScroll() != 0 || 02705 pTex->getTextureVScroll() != 0 ) 02706 { 02707 writeAttribute(4, "scroll"); 02708 writeValue(StringConverter::toString(pTex->getTextureUScroll())); 02709 writeValue(StringConverter::toString(pTex->getTextureVScroll())); 02710 } 02711 // scale 02712 if (mDefaults || 02713 pTex->getTextureUScale() != 1.0 || 02714 pTex->getTextureVScale() != 1.0 ) 02715 { 02716 writeAttribute(4, "scale"); 02717 writeValue(StringConverter::toString(pTex->getTextureUScale())); 02718 writeValue(StringConverter::toString(pTex->getTextureVScale())); 02719 } 02720 02721 EffectMap m_ef = pTex->getEffects(); 02722 if (!m_ef.empty()) 02723 { 02724 EffectMap::const_iterator it; 02725 for (it = m_ef.begin(); it != m_ef.end(); ++it) 02726 { 02727 const TextureUnitState::TextureEffect& ef = it->second; 02728 switch (ef.type) 02729 { 02730 case TextureUnitState::ET_ENVIRONMENT_MAP : 02731 writeEnvironmentMapEffect(ef, pTex); 02732 break; 02733 case TextureUnitState::ET_ROTATE : 02734 writeRotationEffect(ef, pTex); 02735 break; 02736 case TextureUnitState::ET_SCROLL : 02737 writeScrollEffect(ef, pTex); 02738 break; 02739 case TextureUnitState::ET_TRANSFORM : 02740 writeTransformEffect(ef, pTex); 02741 break; 02742 default: 02743 break; 02744 } 02745 } 02746 } 02747 } 02748 endSection(3); 02749 02750 } 02751 //----------------------------------------------------------------------- 02752 void MaterialSerializer::writeEnvironmentMapEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex) 02753 { 02754 writeAttribute(4, "env_map"); 02755 switch (effect.subtype) 02756 { 02757 case TextureUnitState::ENV_PLANAR: 02758 writeValue("planar"); 02759 break; 02760 case TextureUnitState::ENV_CURVED: 02761 writeValue("spherical"); 02762 break; 02763 case TextureUnitState::ENV_NORMAL: 02764 writeValue("cubic_normal"); 02765 break; 02766 case TextureUnitState::ENV_REFLECTION: 02767 writeValue("cubic_reflection"); 02768 break; 02769 } 02770 } 02771 //----------------------------------------------------------------------- 02772 void MaterialSerializer::writeRotationEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex) 02773 { 02774 if (effect.arg1) 02775 { 02776 writeAttribute(4, "rotate_anim"); 02777 writeValue(StringConverter::toString(effect.arg1)); 02778 } 02779 } 02780 //----------------------------------------------------------------------- 02781 void MaterialSerializer::writeTransformEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex) 02782 { 02783 writeAttribute(4, "wave_xform"); 02784 02785 switch (effect.subtype) 02786 { 02787 case TextureUnitState::TT_ROTATE: 02788 writeValue("rotate"); 02789 break; 02790 case TextureUnitState::TT_SCALE_U: 02791 writeValue("scale_x"); 02792 break; 02793 case TextureUnitState::TT_SCALE_V: 02794 writeValue("scale_y"); 02795 break; 02796 case TextureUnitState::TT_TRANSLATE_U: 02797 writeValue("scroll_x"); 02798 break; 02799 case TextureUnitState::TT_TRANSLATE_V: 02800 writeValue("scroll_y"); 02801 break; 02802 } 02803 02804 switch (effect.waveType) 02805 { 02806 case WFT_INVERSE_SAWTOOTH: 02807 writeValue("inverse_sawtooth"); 02808 break; 02809 case WFT_SAWTOOTH: 02810 writeValue("sawtooth"); 02811 break; 02812 case WFT_SINE: 02813 writeValue("sine"); 02814 break; 02815 case WFT_SQUARE: 02816 writeValue("square"); 02817 break; 02818 case WFT_TRIANGLE: 02819 writeValue("triangle"); 02820 break; 02821 } 02822 02823 writeValue(StringConverter::toString(effect.base)); 02824 writeValue(StringConverter::toString(effect.frequency)); 02825 writeValue(StringConverter::toString(effect.phase)); 02826 writeValue(StringConverter::toString(effect.amplitude)); 02827 } 02828 //----------------------------------------------------------------------- 02829 void MaterialSerializer::writeScrollEffect(const TextureUnitState::TextureEffect& effect, const TextureUnitState *pTex) 02830 { 02831 if (effect.arg1 || effect.arg2) 02832 { 02833 writeAttribute(4, "scroll_anim"); 02834 writeValue(StringConverter::toString(effect.arg1)); 02835 writeValue(StringConverter::toString(effect.arg2)); 02836 } 02837 } 02838 //----------------------------------------------------------------------- 02839 void MaterialSerializer::writeSceneBlendFactor(const SceneBlendFactor sbf) 02840 { 02841 switch (sbf) 02842 { 02843 case SBF_DEST_ALPHA: 02844 writeValue("dest_alpha"); 02845 break; 02846 case SBF_DEST_COLOUR: 02847 writeValue("dest_colour"); 02848 break; 02849 case SBF_ONE: 02850 writeValue("one"); 02851 break; 02852 case SBF_ONE_MINUS_DEST_ALPHA: 02853 writeValue("one_minus_dest_alpha"); 02854 break; 02855 case SBF_ONE_MINUS_DEST_COLOUR: 02856 writeValue("one_minus_dest_colour"); 02857 break; 02858 case SBF_ONE_MINUS_SOURCE_ALPHA: 02859 writeValue("one_minus_src_alpha"); 02860 break; 02861 case SBF_ONE_MINUS_SOURCE_COLOUR: 02862 writeValue("one_minus_src_colour"); 02863 break; 02864 case SBF_SOURCE_ALPHA: 02865 writeValue("src_alpha"); 02866 break; 02867 case SBF_SOURCE_COLOUR: 02868 writeValue("src_colour"); 02869 break; 02870 case SBF_ZERO: 02871 writeValue("zero"); 02872 break; 02873 } 02874 } 02875 //----------------------------------------------------------------------- 02876 void MaterialSerializer::writeSceneBlendFactor(const SceneBlendFactor sbf_src, const SceneBlendFactor sbf_dst) 02877 { 02878 if (sbf_src == SBF_ONE && sbf_dst == SBF_ONE ) 02879 writeValue("add"); 02880 else if (sbf_src == SBF_SOURCE_COLOUR && sbf_dst == SBF_ONE_MINUS_SOURCE_COLOUR) 02881 writeValue("modulate"); 02882 else if (sbf_src == SBF_SOURCE_ALPHA && sbf_dst == SBF_ONE_MINUS_SOURCE_ALPHA) 02883 writeValue("alpha_blend"); 02884 else 02885 { 02886 writeSceneBlendFactor(sbf_src); 02887 writeSceneBlendFactor(sbf_dst); 02888 } 02889 } 02890 //----------------------------------------------------------------------- 02891 void MaterialSerializer::writeCompareFunction(const CompareFunction cf) 02892 { 02893 switch (cf) 02894 { 02895 case CMPF_ALWAYS_FAIL: 02896 writeValue("always_fail"); 02897 break; 02898 case CMPF_ALWAYS_PASS: 02899 writeValue("always_pass"); 02900 break; 02901 case CMPF_EQUAL: 02902 writeValue("equal"); 02903 break; 02904 case CMPF_GREATER: 02905 writeValue("greater"); 02906 break; 02907 case CMPF_GREATER_EQUAL: 02908 writeValue("greater_equal"); 02909 break; 02910 case CMPF_LESS: 02911 writeValue("less"); 02912 break; 02913 case CMPF_LESS_EQUAL: 02914 writeValue("less_equal"); 02915 break; 02916 case CMPF_NOT_EQUAL: 02917 writeValue("not_equal"); 02918 break; 02919 } 02920 } 02921 //----------------------------------------------------------------------- 02922 void MaterialSerializer::writeColourValue(const ColourValue &colour, bool writeAlpha) 02923 { 02924 writeValue(StringConverter::toString(colour.r)); 02925 writeValue(StringConverter::toString(colour.g)); 02926 writeValue(StringConverter::toString(colour.b)); 02927 if (writeAlpha) 02928 writeValue(StringConverter::toString(colour.a)); 02929 } 02930 //----------------------------------------------------------------------- 02931 void MaterialSerializer::writeLayerBlendOperationEx(const LayerBlendOperationEx op) 02932 { 02933 switch (op) 02934 { 02935 case LBX_ADD: 02936 writeValue("add"); 02937 break; 02938 case LBX_ADD_SIGNED: 02939 writeValue("add_signed"); 02940 break; 02941 case LBX_ADD_SMOOTH: 02942 writeValue("add_smooth"); 02943 break; 02944 case LBX_BLEND_CURRENT_ALPHA: 02945 writeValue("blend_current_alpha"); 02946 break; 02947 case LBX_BLEND_DIFFUSE_ALPHA: 02948 writeValue("blend_diffuse_alpha"); 02949 break; 02950 case LBX_BLEND_MANUAL: 02951 writeValue("blend_manual"); 02952 break; 02953 case LBX_BLEND_TEXTURE_ALPHA: 02954 writeValue("blend_texture_alpha"); 02955 break; 02956 case LBX_MODULATE: 02957 writeValue("modulate"); 02958 break; 02959 case LBX_MODULATE_X2: 02960 writeValue("modulate_x2"); 02961 break; 02962 case LBX_MODULATE_X4: 02963 writeValue("modulate_x4"); 02964 break; 02965 case LBX_SOURCE1: 02966 writeValue("source1"); 02967 break; 02968 case LBX_SOURCE2: 02969 writeValue("source2"); 02970 break; 02971 case LBX_SUBTRACT: 02972 writeValue("subtract"); 02973 break; 02974 case LBX_DOTPRODUCT: 02975 writeValue("dotproduct"); 02976 break; 02977 } 02978 } 02979 //----------------------------------------------------------------------- 02980 void MaterialSerializer::writeLayerBlendSource(const LayerBlendSource lbs) 02981 { 02982 switch (lbs) 02983 { 02984 case LBS_CURRENT: 02985 writeValue("src_current"); 02986 break; 02987 case LBS_DIFFUSE: 02988 writeValue("src_diffuse"); 02989 break; 02990 case LBS_MANUAL: 02991 writeValue("src_manual"); 02992 break; 02993 case LBS_SPECULAR: 02994 writeValue("src_specular"); 02995 break; 02996 case LBS_TEXTURE: 02997 writeValue("src_texture"); 02998 break; 02999 } 03000 } 03001 }
Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:22 2004