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