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