Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreMaterial.cpp

Go to the documentation of this file.
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