00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 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 "OgreMaterial.h" 00028 00029 #include "OgreSceneManagerEnumerator.h" 00030 #include "OgreMaterialManager.h" 00031 #include "OgreIteratorWrappers.h" 00032 #include "OgreTechnique.h" 00033 #include "OgreLogManager.h" 00034 00035 namespace Ogre { 00036 00037 Material* Material::mDefaultSettings = 0; 00038 00039 //----------------------------------------------------------------------- 00040 Material::Material() 00041 { 00042 static unsigned short num = 1; 00043 char name[14]; 00044 00045 sprintf(name, "Undefined%d", num++); 00046 mName = name; 00047 mCompilationRequired = true; 00048 mIsLoaded = false; 00049 mLodDistances.push_back(0.0f); 00050 00051 } 00052 //----------------------------------------------------------------------- 00053 Material::Material( const String& name ) 00054 { 00055 applyDefaults(); 00056 00057 // Assign name 00058 mName = name; 00059 mCompilationRequired = true; 00060 mIsLoaded = false; 00061 00062 } 00063 //----------------------------------------------------------------------- 00064 Material::~Material() 00065 { 00066 removeAllTechniques(); 00067 // parent Resource will call unload 00068 } 00069 //----------------------------------------------------------------------- 00070 Material& Material::operator=(const Material& rhs) 00071 { 00072 mName = rhs.mName; 00073 mHandle = rhs.mHandle; 00074 mSize = rhs.mSize; 00075 mLastAccess = rhs.mLastAccess; 00076 00077 00078 00079 // Copy Techniques 00080 this->removeAllTechniques(); 00081 Techniques::const_iterator i, iend; 00082 iend = rhs.mTechniques.end(); 00083 for(i = rhs.mTechniques.begin(); i != iend; ++i) 00084 { 00085 Technique* t = this->createTechnique(); 00086 *t = *(*i); 00087 if ((*i)->isSupported()) 00088 { 00089 mSupportedTechniques.push_back(t); 00090 // NB this won't insert if the index is already there, which is what we want 00091 mBestTechniqueList.insert( 00092 BestTechniqueList::value_type(t->getLodIndex(), t)); 00093 } 00094 } 00095 00096 // Also copy LOD information 00097 mLodDistances.clear(); 00098 LodDistanceList::const_iterator lodi, lodiend; 00099 lodiend = rhs.mLodDistances.end(); 00100 for (lodi = rhs.mLodDistances.begin(); lodi != lodiend; ++lodi) 00101 { 00102 mLodDistances.push_back(*lodi); 00103 } 00104 mCompilationRequired = rhs.mCompilationRequired; 00105 mIsLoaded = rhs.mIsLoaded; 00106 00107 return *this; 00108 } 00109 00110 00111 //----------------------------------------------------------------------- 00112 const String& Material::getName(void) const 00113 { 00114 return mName; 00115 } 00116 //----------------------------------------------------------------------- 00117 void Material::load(void) 00118 { 00119 if (!mIsLoaded) 00120 { 00121 // compile if required 00122 if (mCompilationRequired) 00123 compile(); 00124 00125 // Load all supported techniques 00126 Techniques::iterator i, iend; 00127 iend = mSupportedTechniques.end(); 00128 for (i = mSupportedTechniques.begin(); i != iend; ++i) 00129 { 00130 (*i)->_load(); 00131 } 00132 00133 mIsLoaded = true; 00134 00135 } 00136 } 00137 //----------------------------------------------------------------------- 00138 void Material::unload(void) 00139 { 00140 if (mIsLoaded) 00141 { 00142 // Unload all supported techniques 00143 Techniques::iterator i, iend; 00144 iend = mSupportedTechniques.end(); 00145 for (i = mSupportedTechniques.begin(); i != iend; ++i) 00146 { 00147 (*i)->_unload(); 00148 } 00149 mIsLoaded = false; 00150 } 00151 } 00152 //----------------------------------------------------------------------- 00153 Material* Material::clone(const String& newName) const 00154 { 00155 Material* newMat = (Material*)MaterialManager::getSingleton().create(newName); 00156 00157 // Keep handle (see below, copy overrides everything) 00158 ResourceHandle newHandle = newMat->getHandle(); 00159 // Assign values from this 00160 *newMat = *this; 00161 newMat->mIsLoaded = this->mIsLoaded; 00162 // Correct the name & handle, they get copied too 00163 newMat->mName = newName; 00164 newMat->mHandle = newHandle; 00165 00166 return newMat; 00167 00168 00169 00170 } 00171 //----------------------------------------------------------------------- 00172 void Material::copyDetailsTo(Material* mat) const 00173 { 00174 // Keep handle (see below, copy overrides everything) 00175 ResourceHandle savedHandle = mat->mHandle; 00176 String savedName = mat->mName; 00177 // Assign values from this 00178 *mat = *this; 00179 // Correct the name & handle, they get copied too 00180 mat->mName = savedName; 00181 mat->mHandle = savedHandle; 00182 00183 } 00184 //----------------------------------------------------------------------- 00185 void Material::applyDefaults(void) 00186 { 00187 *this = *mDefaultSettings; 00188 mCompilationRequired = true; 00189 00190 } 00191 //----------------------------------------------------------------------- 00192 Technique* Material::createTechnique(void) 00193 { 00194 Technique *t = new Technique(this); 00195 mTechniques.push_back(t); 00196 mCompilationRequired = true; 00197 return t; 00198 } 00199 //----------------------------------------------------------------------- 00200 Technique* Material::getTechnique(unsigned short index) 00201 { 00202 assert (index < mTechniques.size() && "Index out of bounds."); 00203 return mTechniques[index]; 00204 } 00205 //----------------------------------------------------------------------- 00206 Technique* Material::getBestTechnique(unsigned short lodIndex) 00207 { 00208 if (mSupportedTechniques.empty()) 00209 { 00210 return NULL; 00211 } 00212 else 00213 { 00214 BestTechniqueList::iterator i = mBestTechniqueList.find(lodIndex); 00215 00216 if (i == mBestTechniqueList.end()) 00217 { 00218 Except(Exception::ERR_ITEM_NOT_FOUND, 00219 "Lod index " + StringConverter::toString(lodIndex) + 00220 " not found for material " + mName, 00221 "Material::getBestTechnique"); 00222 } 00223 return i->second; 00224 } 00225 } 00226 //----------------------------------------------------------------------- 00227 void Material::removeTechnique(unsigned short index) 00228 { 00229 assert (index < mTechniques.size() && "Index out of bounds."); 00230 Techniques::iterator i = mTechniques.begin() + index; 00231 delete(*i); 00232 mTechniques.erase(i); 00233 mSupportedTechniques.clear(); 00234 mBestTechniqueList.clear(); 00235 mCompilationRequired = true; 00236 } 00237 //----------------------------------------------------------------------- 00238 void Material::removeAllTechniques(void) 00239 { 00240 Techniques::iterator i, iend; 00241 iend = mTechniques.end(); 00242 for (i = mTechniques.begin(); i != iend; ++i) 00243 { 00244 delete(*i); 00245 } 00246 mTechniques.clear(); 00247 mSupportedTechniques.clear(); 00248 mBestTechniqueList.clear(); 00249 mCompilationRequired = true; 00250 } 00251 //----------------------------------------------------------------------- 00252 Material::TechniqueIterator Material::getTechniqueIterator(void) 00253 { 00254 return TechniqueIterator(mTechniques.begin(), mTechniques.end()); 00255 } 00256 //----------------------------------------------------------------------- 00257 Material::TechniqueIterator Material::getSupportedTechniqueIterator(void) 00258 { 00259 return TechniqueIterator(mSupportedTechniques.begin(), mSupportedTechniques.end()); 00260 } 00261 //----------------------------------------------------------------------- 00262 bool Material::isTransparent(void) const 00263 { 00264 // Check each technique 00265 Techniques::const_iterator i, iend; 00266 iend = mTechniques.end(); 00267 for (i = mTechniques.begin(); i != iend; ++i) 00268 { 00269 if ( (*i)->isTransparent() ) 00270 return true; 00271 } 00272 return false; 00273 } 00274 //----------------------------------------------------------------------- 00275 void Material::compile(bool autoManageTextureUnits) 00276 { 00277 // Compile each technique, then add it to the list of supported techniques 00278 mSupportedTechniques.clear(); 00279 mBestTechniqueList.clear(); 00280 00281 Techniques::iterator i, iend; 00282 iend = mTechniques.end(); 00283 for (i = mTechniques.begin(); i != iend; ++i) 00284 { 00285 (*i)->_compile(autoManageTextureUnits); 00286 if ( (*i)->isSupported() ) 00287 { 00288 mSupportedTechniques.push_back(*i); 00289 // NB this won't insert if the index is already there, which is what we want 00290 mBestTechniqueList.insert( 00291 BestTechniqueList::value_type((*i)->getLodIndex(), *i)); 00292 } 00293 } 00294 // Now iterate over the best technique list, looking for gaps and filling them in 00295 // guarantees we've got a sequential list with entries in all indexes 00296 BestTechniqueList::iterator bi, biend; 00297 biend = mBestTechniqueList.end(); 00298 unsigned short lastIndex = 0; 00299 Technique* lastTechnique = NULL; 00300 for (bi = mBestTechniqueList.begin(); bi != biend; ++bi) 00301 { 00302 while (bi->first > lastIndex + 1) 00303 { 00304 if (!lastTechnique) // hmm, index 0 is missing, use the first one we have 00305 lastTechnique = bi->second; 00306 mBestTechniqueList[++lastIndex] = lastTechnique; 00307 } 00308 00309 lastIndex = bi->first; 00310 lastTechnique = bi->second; 00311 00312 } 00313 mCompilationRequired = false; 00314 00315 // Did we find any? 00316 if (mSupportedTechniques.empty()) 00317 { 00318 LogManager::getSingleton().logMessage( 00319 "Warning: material " + mName + " has no supportable Techniques on this " 00320 "hardware, it will be rendered blank."); 00321 } 00322 } 00323 //----------------------------------------------------------------------- 00324 void Material::setAmbient(Real red, Real green, Real blue) 00325 { 00326 Techniques::iterator i, iend; 00327 iend = mTechniques.end(); 00328 for (i = mTechniques.begin(); i != iend; ++i) 00329 { 00330 (*i)->setAmbient(red, green, blue); 00331 } 00332 00333 } 00334 //----------------------------------------------------------------------- 00335 void Material::setAmbient(const ColourValue& ambient) 00336 { 00337 setAmbient(ambient.r, ambient.g, ambient.b); 00338 } 00339 //----------------------------------------------------------------------- 00340 void Material::setDiffuse(Real red, Real green, Real blue) 00341 { 00342 Techniques::iterator i, iend; 00343 iend = mTechniques.end(); 00344 for (i = mTechniques.begin(); i != iend; ++i) 00345 { 00346 (*i)->setDiffuse(red, green, blue); 00347 } 00348 } 00349 //----------------------------------------------------------------------- 00350 void Material::setDiffuse(const ColourValue& diffuse) 00351 { 00352 setDiffuse(diffuse.r, diffuse.g, diffuse.b); 00353 } 00354 //----------------------------------------------------------------------- 00355 void Material::setSpecular(Real red, Real green, Real blue) 00356 { 00357 Techniques::iterator i, iend; 00358 iend = mTechniques.end(); 00359 for (i = mTechniques.begin(); i != iend; ++i) 00360 { 00361 (*i)->setSpecular(red, green, blue); 00362 } 00363 } 00364 //----------------------------------------------------------------------- 00365 void Material::setSpecular(const ColourValue& specular) 00366 { 00367 setSpecular(specular.r, specular.g, specular.b); 00368 } 00369 //----------------------------------------------------------------------- 00370 void Material::setShininess(Real val) 00371 { 00372 Techniques::iterator i, iend; 00373 iend = mTechniques.end(); 00374 for (i = mTechniques.begin(); i != iend; ++i) 00375 { 00376 (*i)->setShininess(val); 00377 } 00378 } 00379 //----------------------------------------------------------------------- 00380 void Material::setSelfIllumination(Real red, Real green, Real blue) 00381 { 00382 Techniques::iterator i, iend; 00383 iend = mTechniques.end(); 00384 for (i = mTechniques.begin(); i != iend; ++i) 00385 { 00386 (*i)->setSelfIllumination(red, green, blue); 00387 } 00388 } 00389 //----------------------------------------------------------------------- 00390 void Material::setSelfIllumination(const ColourValue& selfIllum) 00391 { 00392 setSelfIllumination(selfIllum.r, selfIllum.g, selfIllum.b); 00393 } 00394 //----------------------------------------------------------------------- 00395 void Material::setDepthCheckEnabled(bool enabled) 00396 { 00397 Techniques::iterator i, iend; 00398 iend = mTechniques.end(); 00399 for (i = mTechniques.begin(); i != iend; ++i) 00400 { 00401 (*i)->setDepthCheckEnabled(enabled); 00402 } 00403 } 00404 //----------------------------------------------------------------------- 00405 void Material::setDepthWriteEnabled(bool enabled) 00406 { 00407 Techniques::iterator i, iend; 00408 iend = mTechniques.end(); 00409 for (i = mTechniques.begin(); i != iend; ++i) 00410 { 00411 (*i)->setDepthWriteEnabled(enabled); 00412 } 00413 } 00414 //----------------------------------------------------------------------- 00415 void Material::setDepthFunction( CompareFunction func ) 00416 { 00417 Techniques::iterator i, iend; 00418 iend = mTechniques.end(); 00419 for (i = mTechniques.begin(); i != iend; ++i) 00420 { 00421 (*i)->setDepthFunction(func); 00422 } 00423 } 00424 //----------------------------------------------------------------------- 00425 void Material::setColourWriteEnabled(bool enabled) 00426 { 00427 Techniques::iterator i, iend; 00428 iend = mTechniques.end(); 00429 for (i = mTechniques.begin(); i != iend; ++i) 00430 { 00431 (*i)->setColourWriteEnabled(enabled); 00432 } 00433 } 00434 //----------------------------------------------------------------------- 00435 void Material::setCullingMode( CullingMode mode ) 00436 { 00437 Techniques::iterator i, iend; 00438 iend = mTechniques.end(); 00439 for (i = mTechniques.begin(); i != iend; ++i) 00440 { 00441 (*i)->setCullingMode(mode); 00442 } 00443 } 00444 //----------------------------------------------------------------------- 00445 void Material::setManualCullingMode( ManualCullingMode mode ) 00446 { 00447 Techniques::iterator i, iend; 00448 iend = mTechniques.end(); 00449 for (i = mTechniques.begin(); i != iend; ++i) 00450 { 00451 (*i)->setManualCullingMode(mode); 00452 } 00453 } 00454 //----------------------------------------------------------------------- 00455 void Material::setLightingEnabled(bool enabled) 00456 { 00457 Techniques::iterator i, iend; 00458 iend = mTechniques.end(); 00459 for (i = mTechniques.begin(); i != iend; ++i) 00460 { 00461 (*i)->setLightingEnabled(enabled); 00462 } 00463 } 00464 //----------------------------------------------------------------------- 00465 void Material::setShadingMode( ShadeOptions mode ) 00466 { 00467 Techniques::iterator i, iend; 00468 iend = mTechniques.end(); 00469 for (i = mTechniques.begin(); i != iend; ++i) 00470 { 00471 (*i)->setShadingMode(mode); 00472 } 00473 } 00474 //----------------------------------------------------------------------- 00475 void Material::setFog(bool overrideScene, FogMode mode, const ColourValue& colour, 00476 Real expDensity, Real linearStart, Real linearEnd) 00477 { 00478 Techniques::iterator i, iend; 00479 iend = mTechniques.end(); 00480 for (i = mTechniques.begin(); i != iend; ++i) 00481 { 00482 (*i)->setFog(overrideScene, mode, colour, expDensity, linearStart, linearEnd); 00483 } 00484 } 00485 //----------------------------------------------------------------------- 00486 void Material::setDepthBias(ushort bias) 00487 { 00488 Techniques::iterator i, iend; 00489 iend = mTechniques.end(); 00490 for (i = mTechniques.begin(); i != iend; ++i) 00491 { 00492 (*i)->setDepthBias(bias); 00493 } 00494 } 00495 //----------------------------------------------------------------------- 00496 void Material::setTextureFiltering(TextureFilterOptions filterType) 00497 { 00498 Techniques::iterator i, iend; 00499 iend = mTechniques.end(); 00500 for (i = mTechniques.begin(); i != iend; ++i) 00501 { 00502 (*i)->setTextureFiltering(filterType); 00503 } 00504 } 00505 // -------------------------------------------------------------------- 00506 void Material::setTextureAnisotropy(int maxAniso) 00507 { 00508 Techniques::iterator i, iend; 00509 iend = mTechniques.end(); 00510 for (i = mTechniques.begin(); i != iend; ++i) 00511 { 00512 (*i)->setTextureAnisotropy(maxAniso); 00513 } 00514 } 00515 // -------------------------------------------------------------------- 00516 void Material::setSceneBlending( const SceneBlendType sbt ) 00517 { 00518 Techniques::iterator i, iend; 00519 iend = mTechniques.end(); 00520 for (i = mTechniques.begin(); i != iend; ++i) 00521 { 00522 (*i)->setSceneBlending(sbt); 00523 } 00524 } 00525 // -------------------------------------------------------------------- 00526 void Material::setSceneBlending( const SceneBlendFactor sourceFactor, 00527 const SceneBlendFactor destFactor) 00528 { 00529 Techniques::iterator i, iend; 00530 iend = mTechniques.end(); 00531 for (i = mTechniques.begin(); i != iend; ++i) 00532 { 00533 (*i)->setSceneBlending(sourceFactor, destFactor); 00534 } 00535 } 00536 // -------------------------------------------------------------------- 00537 void Material::_notifyNeedsRecompile(void) 00538 { 00539 mCompilationRequired = true; 00540 // Also need to flag as unloaded to ensure we loaded any new items 00541 mIsLoaded = false; 00542 } 00543 // -------------------------------------------------------------------- 00544 void Material::setLodLevels(const LodDistanceList& lodDistances) 00545 { 00546 // Square the distances for the internal list 00547 LodDistanceList::const_iterator i, iend; 00548 iend = lodDistances.end(); 00549 // First, clear and add single zero entry 00550 mLodDistances.clear(); 00551 mLodDistances.push_back(0.0f); 00552 for (i = lodDistances.begin(); i != iend; ++i) 00553 { 00554 mLodDistances.push_back((*i) * (*i)); 00555 } 00556 00557 } 00558 // -------------------------------------------------------------------- 00559 unsigned short Material::getLodIndex(Real d) const 00560 { 00561 return getLodIndexSquaredDepth(d * d); 00562 } 00563 // -------------------------------------------------------------------- 00564 unsigned short Material::getLodIndexSquaredDepth(Real squaredDistance) const 00565 { 00566 LodDistanceList::const_iterator i, iend; 00567 iend = mLodDistances.end(); 00568 unsigned short index = 0; 00569 for (i = mLodDistances.begin(); i != iend; ++i, ++index) 00570 { 00571 if (*i > squaredDistance) 00572 { 00573 return index - 1; 00574 } 00575 } 00576 00577 // If we fall all the way through, use the highest value 00578 return static_cast<ushort>(mLodDistances.size() - 1); 00579 } 00580 00581 00582 } 00583
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:15 2004