source: OGRE/trunk/ogrenew/OgreMain/src/OgreMaterial.cpp @ 692

Revision 692, 25.1 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26
27#include "OgreMaterial.h"
28
29#include "OgreSceneManagerEnumerator.h"
30#include "OgreMaterialManager.h"
31#include "OgreIteratorWrappers.h"
32#include "OgreTechnique.h"
33#include "OgreLogManager.h"
34#include "OgreException.h"
35#include "OgreStringConverter.h"
36
37namespace Ogre {
38
39    //-----------------------------------------------------------------------
40        Material::Material(ResourceManager* creator, const String& name, ResourceHandle handle,
41                const String& group, bool isManual, ManualResourceLoader* loader)
42                :Resource(creator, name, handle, group, isManual, loader),
43         mReceiveShadows(true),
44         mTransparencyCastsShadows(false),
45         mCompilationRequired(true)
46    {
47                // Override isManual, not applicable for Material (we always want to call loadImpl)
48                if(isManual)
49                {
50                        mIsManual = false;
51                        LogManager::getSingleton().logMessage("Material " + name +
52                                " was requested with isManual=true, but this is not applicable "
53                                "for materials; the flag has been reset to false");
54                }
55
56                mLodDistances.push_back(0.0f);
57
58                applyDefaults();
59
60                /* For consistency with StringInterface, but we don't add any parameters here
61                That's because the Resource implementation of StringInterface is to
62                list all the options that need to be set before loading, of which
63                we have none as such. Full details can be set through scripts.
64                */
65                createParamDictionary("Material");
66    }
67    //-----------------------------------------------------------------------
68    Material::~Material()
69    {
70        removeAllTechniques();
71        // have to call this here reather than in Resource destructor
72        // since calling virtual methods in base destructors causes crash
73        unload();
74    }
75    //-----------------------------------------------------------------------
76    Material& Material::operator=(const Material& rhs)
77    {
78            mName = rhs.mName;
79                mGroup = rhs.mGroup;
80                mCreator = rhs.mCreator;
81                mIsManual = rhs.mIsManual;
82                mLoader = rhs.mLoader;
83            mHandle = rhs.mHandle;
84        mSize = rhs.mSize;
85        mReceiveShadows = rhs.mReceiveShadows;
86        mTransparencyCastsShadows = rhs.mTransparencyCastsShadows;
87
88        mIsLoaded = rhs.mIsLoaded;
89
90        // Copy Techniques
91        this->removeAllTechniques();
92        Techniques::const_iterator i, iend;
93        iend = rhs.mTechniques.end();
94        for(i = rhs.mTechniques.begin(); i != iend; ++i)
95        {
96            Technique* t = this->createTechnique();
97            *t = *(*i);
98            if ((*i)->isSupported())
99            {
100                                insertSupportedTechnique(t);
101            }
102        }
103
104                // Also copy LOD information
105                mLodDistances = rhs.mLodDistances;
106        mCompilationRequired = rhs.mCompilationRequired;
107        // illumination passes are not compiled right away so
108        // mIsLoaded state should still be the same as the original material
109        assert(mIsLoaded == rhs.mIsLoaded);
110
111            return *this;
112    }
113
114
115    //-----------------------------------------------------------------------
116    void Material::loadImpl(void)
117    {
118                // compile if required
119        if (mCompilationRequired)
120            compile();
121
122        // Load all supported techniques
123        Techniques::iterator i, iend;
124        iend = mSupportedTechniques.end();
125        for (i = mSupportedTechniques.begin(); i != iend; ++i)
126        {
127            (*i)->_load();
128        }
129
130    }
131    //-----------------------------------------------------------------------
132    void Material::unloadImpl(void)
133    {
134        // Unload all supported techniques
135        Techniques::iterator i, iend;
136        iend = mSupportedTechniques.end();
137        for (i = mSupportedTechniques.begin(); i != iend; ++i)
138        {
139            (*i)->_unload();
140        }
141    }
142    //-----------------------------------------------------------------------
143    MaterialPtr Material::clone(const String& newName, bool changeGroup,
144                const String& newGroup) const
145    {
146                MaterialPtr newMat;
147                if (changeGroup)
148                {
149                        newMat = MaterialManager::getSingleton().create(newName, newGroup);
150                }
151                else
152                {
153                        newMat = MaterialManager::getSingleton().create(newName, mGroup);
154                }
155       
156
157        // Keep handle (see below, copy overrides everything)
158        ResourceHandle newHandle = newMat->getHandle();
159        // Assign values from this
160        *newMat = *this;
161                // Restore new group if required, will have been overridden by operator
162                if (changeGroup)
163                {
164                        newMat->mGroup = newGroup;
165                }
166               
167        // Correct the name & handle, they get copied too
168        newMat->mName = newName;
169        newMat->mHandle = newHandle;
170
171        return newMat;
172
173
174
175    }
176    //-----------------------------------------------------------------------
177    void Material::copyDetailsTo(MaterialPtr& mat) const
178    {
179        // Keep handle (see below, copy overrides everything)
180        ResourceHandle savedHandle = mat->mHandle;
181        String savedName = mat->mName;
182        String savedGroup = mat->mGroup;
183                ManualResourceLoader* savedLoader = mat->mLoader;
184                bool savedManual = mat->mIsManual;
185        // Assign values from this
186        *mat = *this;
187        // Correct the name & handle, they get copied too
188        mat->mName = savedName;
189        mat->mHandle = savedHandle;
190        mat->mGroup = savedGroup;
191                mat->mIsManual = savedManual;
192                mat->mLoader = savedLoader;
193
194    }
195    //-----------------------------------------------------------------------
196    void Material::applyDefaults(void)
197    {
198                MaterialPtr defaults = MaterialManager::getSingleton().getDefaultSettings();
199
200                if (!defaults.isNull())
201                {
202            // save name & handle
203            String savedName = mName;
204            String savedGroup = mGroup;
205            ResourceHandle savedHandle = mHandle;
206                        ManualResourceLoader *savedLoader = mLoader;
207                        bool savedManual = mIsManual;
208                        *this = *defaults;
209            // restore name & handle
210            mName = savedName;
211            mHandle = savedHandle;
212            mGroup = savedGroup;
213                        mLoader = savedLoader;
214                        mIsManual = savedManual;
215                }
216        mCompilationRequired = true;
217
218    }
219    //-----------------------------------------------------------------------
220    Technique* Material::createTechnique(void)
221    {
222        Technique *t = new Technique(this);
223        mTechniques.push_back(t);
224        mCompilationRequired = true;
225        return t;
226    }
227    //-----------------------------------------------------------------------
228    Technique* Material::getTechnique(unsigned short index)
229    {
230        assert (index < mTechniques.size() && "Index out of bounds.");
231        return mTechniques[index];
232    }
233    //-----------------------------------------------------------------------
234    Technique* Material::getTechnique(const String& name)
235    {
236        Techniques::iterator i    = mTechniques.begin();
237        Techniques::iterator iend = mTechniques.end();
238        Technique* foundTechnique = 0;
239
240        // iterate through techniques to find a match
241        while (i != iend)
242        {
243            if ( (*i)->getName() == name )
244            {
245                foundTechnique = (*i);
246                break;
247            }
248            ++i;
249        }
250
251        return foundTechnique;
252    }
253    //-----------------------------------------------------------------------   
254    unsigned short Material::getNumTechniques(void) const
255    {
256                return static_cast<unsigned short>(mTechniques.size());
257    }
258        //-----------------------------------------------------------------------
259    Technique* Material::getSupportedTechnique(unsigned short index)
260    {
261        assert (index < mSupportedTechniques.size() && "Index out of bounds.");
262        return mSupportedTechniques[index];
263    }
264    //-----------------------------------------------------------------------   
265    unsigned short Material::getNumSupportedTechniques(void) const
266    {
267                return static_cast<unsigned short>(mSupportedTechniques.size());
268    }
269        //-----------------------------------------------------------------------
270        unsigned short Material::getNumLodLevels(unsigned short schemeIndex) const
271        {
272                BestTechniquesBySchemeList::const_iterator i =
273                        mBestTechniquesBySchemeList.find(schemeIndex);
274                if (i != mBestTechniquesBySchemeList.end())
275                {
276                        return static_cast<unsigned short>(i->second->size());
277                }
278                else
279                {
280                        return 0;
281                }
282        }
283        //-----------------------------------------------------------------------
284        unsigned short Material::getNumLodLevels(const String& schemeName) const
285        {
286                return getNumLodLevels(
287                        MaterialManager::getSingleton()._getSchemeIndex(schemeName));
288        }
289        //-----------------------------------------------------------------------
290        void Material::insertSupportedTechnique(Technique* t)
291        {
292                mSupportedTechniques.push_back(t);
293                // get scheme
294                unsigned short schemeIndex = t->_getSchemeIndex();
295                BestTechniquesBySchemeList::iterator i =
296                        mBestTechniquesBySchemeList.find(schemeIndex);
297                LodTechniques* lodtechs = 0;
298                if (i == mBestTechniquesBySchemeList.end())
299                {
300                        lodtechs = new LodTechniques();
301                        mBestTechniquesBySchemeList[schemeIndex] = lodtechs;
302                }
303                else
304                {
305                        lodtechs = i->second;
306                }
307
308                // Insert won't replace if supported technique for this scheme/lod is
309                // already there, which is what we want
310                lodtechs->insert(LodTechniques::value_type(t->getLodIndex(), t));
311
312        }
313        //-----------------------------------------------------------------------------
314    Technique* Material::getBestTechnique(unsigned short lodIndex)
315    {
316        if (mSupportedTechniques.empty())
317        {
318            return NULL;
319        }
320        else
321        {
322                        Technique* ret = 0;
323                        // get scheme
324                        BestTechniquesBySchemeList::iterator si =
325                                mBestTechniquesBySchemeList.find(
326                                MaterialManager::getSingleton()._getActiveSchemeIndex());
327                        // scheme not found?
328                        if (si == mBestTechniquesBySchemeList.end())
329                        {
330                                // get the first item, will be 0 (the default) if default
331                                // scheme techniques exist, otherwise the earliest defined
332                                si = mBestTechniquesBySchemeList.begin();
333                        }
334
335                        // get LOD
336                        LodTechniques* lodtechs = si->second;
337                        LodTechniques::iterator li = si->second->find(lodIndex);
338                        // LOD not found?
339                        if (li == si->second->end())
340                        {
341                                // Use the next LOD level up
342                                for (LodTechniques::reverse_iterator rli = si->second->rbegin();
343                                        rli != si->second->rend(); ++rli)
344                                {
345                                        if (rli->second->getLodIndex() < lodIndex)
346                                        {
347                                                ret = rli->second;
348                                                break;
349                                        }
350
351                                }
352                                if (!ret)
353                                {
354                                        // shouldn't ever hit this really, unless user defines no LOD 0
355                                        // pick the first LOD we have (must be at least one to have a scheme entry)
356                                        ret = si->second->begin()->second;
357                                }
358
359                        }
360                        else
361                        {
362                                // LOD found
363                                ret = li->second;
364                        }
365
366                        return ret;
367
368        }
369    }
370    //-----------------------------------------------------------------------
371    void Material::removeTechnique(unsigned short index)
372    {
373        assert (index < mTechniques.size() && "Index out of bounds.");
374        Techniques::iterator i = mTechniques.begin() + index;
375        delete(*i);
376        mTechniques.erase(i);
377        mSupportedTechniques.clear();
378                clearBestTechniqueList();
379        mCompilationRequired = true;
380    }
381    //-----------------------------------------------------------------------
382    void Material::removeAllTechniques(void)
383    {
384        Techniques::iterator i, iend;
385        iend = mTechniques.end();
386        for (i = mTechniques.begin(); i != iend; ++i)
387        {
388            delete(*i);
389        }
390        mTechniques.clear();
391        mSupportedTechniques.clear();
392        clearBestTechniqueList();
393        mCompilationRequired = true;
394    }
395    //-----------------------------------------------------------------------
396    Material::TechniqueIterator Material::getTechniqueIterator(void)
397    {
398        return TechniqueIterator(mTechniques.begin(), mTechniques.end());
399    }
400    //-----------------------------------------------------------------------
401    Material::TechniqueIterator Material::getSupportedTechniqueIterator(void)
402    {
403        return TechniqueIterator(mSupportedTechniques.begin(), mSupportedTechniques.end());
404    }
405    //-----------------------------------------------------------------------
406    bool Material::isTransparent(void) const
407        {
408                // Check each technique
409                Techniques::const_iterator i, iend;
410                iend = mTechniques.end();
411                for (i = mTechniques.begin(); i != iend; ++i)
412                {
413                        if ( (*i)->isTransparent() )
414                                return true;
415                }
416                return false;
417        }
418    //-----------------------------------------------------------------------
419    void Material::compile(bool autoManageTextureUnits)
420    {
421        // Compile each technique, then add it to the list of supported techniques
422        mSupportedTechniques.clear();
423                clearBestTechniqueList();
424
425
426        Techniques::iterator i, iend;
427        iend = mTechniques.end();
428        for (i = mTechniques.begin(); i != iend; ++i)
429        {
430            (*i)->_compile(autoManageTextureUnits);
431            if ( (*i)->isSupported() )
432            {
433                mSupportedTechniques.push_back(*i);
434                                insertSupportedTechnique(*i);
435            }
436        }
437
438        mCompilationRequired = false;
439
440        // Did we find any?
441        if (mSupportedTechniques.empty())
442        {
443            LogManager::getSingleton().logMessage(
444                "Warning: material " + mName + " has no supportable Techniques on this "
445                "hardware, it will be rendered blank.");
446        }
447    }
448        //-----------------------------------------------------------------------
449        void Material::clearBestTechniqueList(void)
450        {
451                for (BestTechniquesBySchemeList::iterator i = mBestTechniquesBySchemeList.begin();
452                        i != mBestTechniquesBySchemeList.end(); ++i)
453                {
454                        delete i->second;
455                }
456                mBestTechniquesBySchemeList.clear();
457        }
458    //-----------------------------------------------------------------------
459    void Material::setPointSize(Real ps)
460    {
461        Techniques::iterator i, iend;
462        iend = mTechniques.end();
463        for (i = mTechniques.begin(); i != iend; ++i)
464        {
465            (*i)->setPointSize(ps);
466        }
467
468    }
469    //-----------------------------------------------------------------------
470    void Material::setAmbient(Real red, Real green, Real blue)
471    {
472        Techniques::iterator i, iend;
473        iend = mTechniques.end();
474        for (i = mTechniques.begin(); i != iend; ++i)
475        {
476            (*i)->setAmbient(red, green, blue);
477        }
478
479    }
480    //-----------------------------------------------------------------------
481    void Material::setAmbient(const ColourValue& ambient)
482    {
483        setAmbient(ambient.r, ambient.g, ambient.b);
484    }
485    //-----------------------------------------------------------------------
486    void Material::setDiffuse(Real red, Real green, Real blue, Real alpha)
487    {
488        Techniques::iterator i, iend;
489        iend = mTechniques.end();
490        for (i = mTechniques.begin(); i != iend; ++i)
491        {
492            (*i)->setDiffuse(red, green, blue, alpha);
493        }
494    }
495    //-----------------------------------------------------------------------
496    void Material::setDiffuse(const ColourValue& diffuse)
497    {
498        setDiffuse(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
499    }
500    //-----------------------------------------------------------------------
501    void Material::setSpecular(Real red, Real green, Real blue, Real alpha)
502    {
503        Techniques::iterator i, iend;
504        iend = mTechniques.end();
505        for (i = mTechniques.begin(); i != iend; ++i)
506        {
507            (*i)->setSpecular(red, green, blue, alpha);
508        }
509    }
510    //-----------------------------------------------------------------------
511    void Material::setSpecular(const ColourValue& specular)
512    {
513        setSpecular(specular.r, specular.g, specular.b, specular.a);
514    }
515    //-----------------------------------------------------------------------
516    void Material::setShininess(Real val)
517    {
518        Techniques::iterator i, iend;
519        iend = mTechniques.end();
520        for (i = mTechniques.begin(); i != iend; ++i)
521        {
522            (*i)->setShininess(val);
523        }
524    }
525    //-----------------------------------------------------------------------
526    void Material::setSelfIllumination(Real red, Real green, Real blue)
527    {
528        Techniques::iterator i, iend;
529        iend = mTechniques.end();
530        for (i = mTechniques.begin(); i != iend; ++i)
531        {
532            (*i)->setSelfIllumination(red, green, blue);
533        }
534    }
535    //-----------------------------------------------------------------------
536    void Material::setSelfIllumination(const ColourValue& selfIllum)
537    {
538        setSelfIllumination(selfIllum.r, selfIllum.g, selfIllum.b);
539    }
540    //-----------------------------------------------------------------------
541    void Material::setDepthCheckEnabled(bool enabled)
542    {
543        Techniques::iterator i, iend;
544        iend = mTechniques.end();
545        for (i = mTechniques.begin(); i != iend; ++i)
546        {
547            (*i)->setDepthCheckEnabled(enabled);
548        }
549    }
550    //-----------------------------------------------------------------------
551    void Material::setDepthWriteEnabled(bool enabled)
552    {
553        Techniques::iterator i, iend;
554        iend = mTechniques.end();
555        for (i = mTechniques.begin(); i != iend; ++i)
556        {
557            (*i)->setDepthWriteEnabled(enabled);
558        }
559    }
560    //-----------------------------------------------------------------------
561    void Material::setDepthFunction( CompareFunction func )
562    {
563        Techniques::iterator i, iend;
564        iend = mTechniques.end();
565        for (i = mTechniques.begin(); i != iend; ++i)
566        {
567            (*i)->setDepthFunction(func);
568        }
569    }
570    //-----------------------------------------------------------------------
571        void Material::setColourWriteEnabled(bool enabled)
572    {
573        Techniques::iterator i, iend;
574        iend = mTechniques.end();
575        for (i = mTechniques.begin(); i != iend; ++i)
576        {
577            (*i)->setColourWriteEnabled(enabled);
578        }
579    }
580    //-----------------------------------------------------------------------
581    void Material::setCullingMode( CullingMode mode )
582    {
583        Techniques::iterator i, iend;
584        iend = mTechniques.end();
585        for (i = mTechniques.begin(); i != iend; ++i)
586        {
587            (*i)->setCullingMode(mode);
588        }
589    }
590    //-----------------------------------------------------------------------
591    void Material::setManualCullingMode( ManualCullingMode mode )
592    {
593        Techniques::iterator i, iend;
594        iend = mTechniques.end();
595        for (i = mTechniques.begin(); i != iend; ++i)
596        {
597            (*i)->setManualCullingMode(mode);
598        }
599    }
600    //-----------------------------------------------------------------------
601    void Material::setLightingEnabled(bool enabled)
602    {
603        Techniques::iterator i, iend;
604        iend = mTechniques.end();
605        for (i = mTechniques.begin(); i != iend; ++i)
606        {
607            (*i)->setLightingEnabled(enabled);
608        }
609    }
610    //-----------------------------------------------------------------------
611    void Material::setShadingMode( ShadeOptions mode )
612    {
613        Techniques::iterator i, iend;
614        iend = mTechniques.end();
615        for (i = mTechniques.begin(); i != iend; ++i)
616        {
617            (*i)->setShadingMode(mode);
618        }
619    }
620    //-----------------------------------------------------------------------
621    void Material::setFog(bool overrideScene, FogMode mode, const ColourValue& colour,
622        Real expDensity, Real linearStart, Real linearEnd)
623    {
624        Techniques::iterator i, iend;
625        iend = mTechniques.end();
626        for (i = mTechniques.begin(); i != iend; ++i)
627        {
628            (*i)->setFog(overrideScene, mode, colour, expDensity, linearStart, linearEnd);
629        }
630    }
631    //-----------------------------------------------------------------------
632    void Material::setDepthBias(ushort bias)
633    {
634        Techniques::iterator i, iend;
635        iend = mTechniques.end();
636        for (i = mTechniques.begin(); i != iend; ++i)
637        {
638            (*i)->setDepthBias(bias);
639        }
640    }
641    //-----------------------------------------------------------------------
642    void Material::setTextureFiltering(TextureFilterOptions filterType)
643    {
644        Techniques::iterator i, iend;
645        iend = mTechniques.end();
646        for (i = mTechniques.begin(); i != iend; ++i)
647        {
648            (*i)->setTextureFiltering(filterType);
649        }
650    }
651    // --------------------------------------------------------------------
652    void Material::setTextureAnisotropy(int maxAniso)
653    {
654        Techniques::iterator i, iend;
655        iend = mTechniques.end();
656        for (i = mTechniques.begin(); i != iend; ++i)
657        {
658            (*i)->setTextureAnisotropy(maxAniso);
659        }
660    }
661    // --------------------------------------------------------------------
662    void Material::setSceneBlending( const SceneBlendType sbt )
663    {
664        Techniques::iterator i, iend;
665        iend = mTechniques.end();
666        for (i = mTechniques.begin(); i != iend; ++i)
667        {
668            (*i)->setSceneBlending(sbt);
669        }
670    }
671    // --------------------------------------------------------------------
672    void Material::setSceneBlending( const SceneBlendFactor sourceFactor,
673        const SceneBlendFactor destFactor)
674    {
675        Techniques::iterator i, iend;
676        iend = mTechniques.end();
677        for (i = mTechniques.begin(); i != iend; ++i)
678        {
679            (*i)->setSceneBlending(sourceFactor, destFactor);
680        }
681    }
682    // --------------------------------------------------------------------
683    void Material::_notifyNeedsRecompile(void)
684    {
685        mCompilationRequired = true;
686        // Also need to unload to ensure we loaded any new items
687        unload();
688    }
689    // --------------------------------------------------------------------
690    void Material::setLodLevels(const LodDistanceList& lodDistances)
691    {
692        // Square the distances for the internal list
693                LodDistanceList::const_iterator i, iend;
694                iend = lodDistances.end();
695                // First, clear and add single zero entry
696                mLodDistances.clear();
697                mLodDistances.push_back(0.0f);
698                for (i = lodDistances.begin(); i != iend; ++i)
699                {
700                        mLodDistances.push_back((*i) * (*i));
701                }
702               
703    }
704    // --------------------------------------------------------------------
705    unsigned short Material::getLodIndex(Real d) const
706    {
707        return getLodIndexSquaredDepth(d * d);
708    }
709    // --------------------------------------------------------------------
710    unsigned short Material::getLodIndexSquaredDepth(Real squaredDistance) const
711    {
712                LodDistanceList::const_iterator i, iend;
713                iend = mLodDistances.end();
714                unsigned short index = 0;
715                for (i = mLodDistances.begin(); i != iend; ++i, ++index)
716                {
717                        if (*i > squaredDistance)
718                        {
719                                return index - 1;
720                        }
721                }
722
723                // If we fall all the way through, use the highest value
724                return static_cast<ushort>(mLodDistances.size() - 1);
725    }
726    // --------------------------------------------------------------------
727    Material::LodDistanceIterator Material::getLodDistanceIterator(void) const
728    {
729        return LodDistanceIterator(mLodDistances.begin(), mLodDistances.end());
730    }
731
732    //-----------------------------------------------------------------------
733    bool Material::applyTextureAliases(const AliasTextureNamePairList& aliasList, const bool apply) const
734    {
735        // iterate through all techniques and apply texture aliases
736                Techniques::const_iterator i, iend;
737                iend = mTechniques.end();
738        bool testResult = false;
739
740                for (i = mTechniques.begin(); i != iend; ++i)
741                {
742            if ((*i)->applyTextureAliases(aliasList, apply))
743                testResult = true;
744                }
745
746        return testResult;
747    }
748}
Note: See TracBrowser for help on using the repository browser.