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 
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