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