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