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