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