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

Revision 657, 22.3 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

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                mSupportedTechniques.push_back(t);
101                                // NB this won't insert if the index is already there, which is what we want
102                                mBestTechniqueList.insert(
103                                        BestTechniqueList::value_type(t->getLodIndex(), t));
104            }
105        }
106
107        // Fixup the best technique list guarantees no gaps inside
108        fixupBestTechniqueList();
109
110                // Also copy LOD information
111                mLodDistances = rhs.mLodDistances;
112        mCompilationRequired = rhs.mCompilationRequired;
113        // illumination passes are not compiled right away so
114        // mIsLoaded state should still be the same as the original material
115        assert(mIsLoaded == rhs.mIsLoaded);
116
117            return *this;
118    }
119
120
121    //-----------------------------------------------------------------------
122    void Material::loadImpl(void)
123    {
124                // compile if required
125        if (mCompilationRequired)
126            compile();
127
128        // Load all supported techniques
129        Techniques::iterator i, iend;
130        iend = mSupportedTechniques.end();
131        for (i = mSupportedTechniques.begin(); i != iend; ++i)
132        {
133            (*i)->_load();
134        }
135
136    }
137    //-----------------------------------------------------------------------
138    void Material::unloadImpl(void)
139    {
140        // Unload all supported techniques
141        Techniques::iterator i, iend;
142        iend = mSupportedTechniques.end();
143        for (i = mSupportedTechniques.begin(); i != iend; ++i)
144        {
145            (*i)->_unload();
146        }
147    }
148    //-----------------------------------------------------------------------
149    MaterialPtr Material::clone(const String& newName, bool changeGroup,
150                const String& newGroup) const
151    {
152                MaterialPtr newMat;
153                if (changeGroup)
154                {
155                        newMat = MaterialManager::getSingleton().create(newName, newGroup);
156                }
157                else
158                {
159                        newMat = MaterialManager::getSingleton().create(newName, mGroup);
160                }
161       
162
163        // Keep handle (see below, copy overrides everything)
164        ResourceHandle newHandle = newMat->getHandle();
165        // Assign values from this
166        *newMat = *this;
167                // Restore new group if required, will have been overridden by operator
168                if (changeGroup)
169                {
170                        newMat->mGroup = newGroup;
171                }
172               
173        // Correct the name & handle, they get copied too
174        newMat->mName = newName;
175        newMat->mHandle = newHandle;
176
177        return newMat;
178
179
180
181    }
182    //-----------------------------------------------------------------------
183    void Material::copyDetailsTo(MaterialPtr& mat) const
184    {
185        // Keep handle (see below, copy overrides everything)
186        ResourceHandle savedHandle = mat->mHandle;
187        String savedName = mat->mName;
188        String savedGroup = mat->mGroup;
189                ManualResourceLoader* savedLoader = mat->mLoader;
190                bool savedManual = mat->mIsManual;
191        // Assign values from this
192        *mat = *this;
193        // Correct the name & handle, they get copied too
194        mat->mName = savedName;
195        mat->mHandle = savedHandle;
196        mat->mGroup = savedGroup;
197                mat->mIsManual = savedManual;
198                mat->mLoader = savedLoader;
199
200    }
201    //-----------------------------------------------------------------------
202    void Material::applyDefaults(void)
203    {
204                MaterialPtr defaults = MaterialManager::getSingleton().getDefaultSettings();
205
206                if (!defaults.isNull())
207                {
208            // save name & handle
209            String savedName = mName;
210            String savedGroup = mGroup;
211            ResourceHandle savedHandle = mHandle;
212                        ManualResourceLoader *savedLoader = mLoader;
213                        bool savedManual = mIsManual;
214                        *this = *defaults;
215            // restore name & handle
216            mName = savedName;
217            mHandle = savedHandle;
218            mGroup = savedGroup;
219                        mLoader = savedLoader;
220                        mIsManual = savedManual;
221                }
222        mCompilationRequired = true;
223
224    }
225    //-----------------------------------------------------------------------
226    Technique* Material::createTechnique(void)
227    {
228        Technique *t = new Technique(this);
229        mTechniques.push_back(t);
230        mCompilationRequired = true;
231        return t;
232    }
233    //-----------------------------------------------------------------------
234    Technique* Material::getTechnique(unsigned short index)
235    {
236        assert (index < mTechniques.size() && "Index out of bounds.");
237        return mTechniques[index];
238    }
239    //-----------------------------------------------------------------------   
240    unsigned short Material::getNumTechniques(void) const
241    {
242                return static_cast<unsigned short>(mTechniques.size());
243    }
244        //-----------------------------------------------------------------------
245    Technique* Material::getSupportedTechnique(unsigned short index)
246    {
247        assert (index < mSupportedTechniques.size() && "Index out of bounds.");
248        return mSupportedTechniques[index];
249    }
250    //-----------------------------------------------------------------------   
251    unsigned short Material::getNumSupportedTechniques(void) const
252    {
253                return static_cast<unsigned short>(mSupportedTechniques.size());
254    }
255        //-----------------------------------------------------------------------------
256    Technique* Material::getBestTechnique(unsigned short lodIndex)
257    {
258        if (mSupportedTechniques.empty())
259        {
260            return NULL;
261        }
262        else
263        {
264                        BestTechniqueList::iterator i = mBestTechniqueList.find(lodIndex);
265
266                        if (i == mBestTechniqueList.end())
267                        {
268                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
269                                        "Lod index " + StringConverter::toString(lodIndex) +
270                                        " not found for material " + mName,
271                                        "Material::getBestTechnique");
272                        }
273            return i->second;
274        }
275    }
276    //-----------------------------------------------------------------------
277    void Material::removeTechnique(unsigned short index)
278    {
279        assert (index < mTechniques.size() && "Index out of bounds.");
280        Techniques::iterator i = mTechniques.begin() + index;
281        delete(*i);
282        mTechniques.erase(i);
283        mSupportedTechniques.clear();
284        mBestTechniqueList.clear();
285        mCompilationRequired = true;
286    }
287    //-----------------------------------------------------------------------
288    void Material::removeAllTechniques(void)
289    {
290        Techniques::iterator i, iend;
291        iend = mTechniques.end();
292        for (i = mTechniques.begin(); i != iend; ++i)
293        {
294            delete(*i);
295        }
296        mTechniques.clear();
297        mSupportedTechniques.clear();
298        mBestTechniqueList.clear();
299        mCompilationRequired = true;
300    }
301    //-----------------------------------------------------------------------
302    Material::TechniqueIterator Material::getTechniqueIterator(void)
303    {
304        return TechniqueIterator(mTechniques.begin(), mTechniques.end());
305    }
306    //-----------------------------------------------------------------------
307    Material::TechniqueIterator Material::getSupportedTechniqueIterator(void)
308    {
309        return TechniqueIterator(mSupportedTechniques.begin(), mSupportedTechniques.end());
310    }
311    //-----------------------------------------------------------------------
312    bool Material::isTransparent(void) const
313        {
314                // Check each technique
315                Techniques::const_iterator i, iend;
316                iend = mTechniques.end();
317                for (i = mTechniques.begin(); i != iend; ++i)
318                {
319                        if ( (*i)->isTransparent() )
320                                return true;
321                }
322                return false;
323        }
324    //-----------------------------------------------------------------------
325    void Material::compile(bool autoManageTextureUnits)
326    {
327        // Compile each technique, then add it to the list of supported techniques
328        mSupportedTechniques.clear();
329                mBestTechniqueList.clear();
330
331        Techniques::iterator i, iend;
332        iend = mTechniques.end();
333        for (i = mTechniques.begin(); i != iend; ++i)
334        {
335            (*i)->_compile(autoManageTextureUnits);
336            if ( (*i)->isSupported() )
337            {
338                mSupportedTechniques.push_back(*i);
339                                // NB this won't insert if the index is already there, which is what we want
340                                mBestTechniqueList.insert(
341                                        BestTechniqueList::value_type((*i)->getLodIndex(), *i));
342            }
343        }
344
345        // Fixup the best technique list guarantees no gaps inside
346        fixupBestTechniqueList();
347
348        mCompilationRequired = false;
349
350        // Did we find any?
351        if (mSupportedTechniques.empty())
352        {
353            LogManager::getSingleton().logMessage(
354                "Warning: material " + mName + " has no supportable Techniques on this "
355                "hardware, it will be rendered blank.");
356        }
357    }
358    //-----------------------------------------------------------------------
359    void Material::fixupBestTechniqueList(void)
360    {
361                BestTechniqueList::iterator bi, biend;
362                biend = mBestTechniqueList.end();
363
364                unsigned short lastIndex = 0;
365                Technique* lastTechnique = 0;
366
367                for (bi = mBestTechniqueList.begin(); bi != biend; ++bi)
368                {
369                        if (lastIndex < bi->first)
370                        {
371                                if (!lastTechnique) // hmm, index 0 is missing, use the first one we have
372                                        lastTechnique = bi->second;
373
374                                do
375                {
376                                        mBestTechniqueList.insert(BestTechniqueList::value_type(lastIndex, lastTechnique));
377                                } while (++lastIndex < bi->first);
378                        }
379
380                        ++lastIndex;
381                        lastTechnique = bi->second;
382                }
383    }
384    //-----------------------------------------------------------------------
385    void Material::setAmbient(Real red, Real green, Real blue)
386    {
387        Techniques::iterator i, iend;
388        iend = mTechniques.end();
389        for (i = mTechniques.begin(); i != iend; ++i)
390        {
391            (*i)->setAmbient(red, green, blue);
392        }
393
394    }
395    //-----------------------------------------------------------------------
396    void Material::setAmbient(const ColourValue& ambient)
397    {
398        setAmbient(ambient.r, ambient.g, ambient.b);
399    }
400    //-----------------------------------------------------------------------
401    void Material::setDiffuse(Real red, Real green, Real blue, Real alpha)
402    {
403        Techniques::iterator i, iend;
404        iend = mTechniques.end();
405        for (i = mTechniques.begin(); i != iend; ++i)
406        {
407            (*i)->setDiffuse(red, green, blue, alpha);
408        }
409    }
410    //-----------------------------------------------------------------------
411    void Material::setDiffuse(const ColourValue& diffuse)
412    {
413        setDiffuse(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
414    }
415    //-----------------------------------------------------------------------
416    void Material::setSpecular(Real red, Real green, Real blue, Real alpha)
417    {
418        Techniques::iterator i, iend;
419        iend = mTechniques.end();
420        for (i = mTechniques.begin(); i != iend; ++i)
421        {
422            (*i)->setSpecular(red, green, blue, alpha);
423        }
424    }
425    //-----------------------------------------------------------------------
426    void Material::setSpecular(const ColourValue& specular)
427    {
428        setSpecular(specular.r, specular.g, specular.b, specular.a);
429    }
430    //-----------------------------------------------------------------------
431    void Material::setShininess(Real val)
432    {
433        Techniques::iterator i, iend;
434        iend = mTechniques.end();
435        for (i = mTechniques.begin(); i != iend; ++i)
436        {
437            (*i)->setShininess(val);
438        }
439    }
440    //-----------------------------------------------------------------------
441    void Material::setSelfIllumination(Real red, Real green, Real blue)
442    {
443        Techniques::iterator i, iend;
444        iend = mTechniques.end();
445        for (i = mTechniques.begin(); i != iend; ++i)
446        {
447            (*i)->setSelfIllumination(red, green, blue);
448        }
449    }
450    //-----------------------------------------------------------------------
451    void Material::setSelfIllumination(const ColourValue& selfIllum)
452    {
453        setSelfIllumination(selfIllum.r, selfIllum.g, selfIllum.b);
454    }
455    //-----------------------------------------------------------------------
456    void Material::setDepthCheckEnabled(bool enabled)
457    {
458        Techniques::iterator i, iend;
459        iend = mTechniques.end();
460        for (i = mTechniques.begin(); i != iend; ++i)
461        {
462            (*i)->setDepthCheckEnabled(enabled);
463        }
464    }
465    //-----------------------------------------------------------------------
466    void Material::setDepthWriteEnabled(bool enabled)
467    {
468        Techniques::iterator i, iend;
469        iend = mTechniques.end();
470        for (i = mTechniques.begin(); i != iend; ++i)
471        {
472            (*i)->setDepthWriteEnabled(enabled);
473        }
474    }
475    //-----------------------------------------------------------------------
476    void Material::setDepthFunction( CompareFunction func )
477    {
478        Techniques::iterator i, iend;
479        iend = mTechniques.end();
480        for (i = mTechniques.begin(); i != iend; ++i)
481        {
482            (*i)->setDepthFunction(func);
483        }
484    }
485    //-----------------------------------------------------------------------
486        void Material::setColourWriteEnabled(bool enabled)
487    {
488        Techniques::iterator i, iend;
489        iend = mTechniques.end();
490        for (i = mTechniques.begin(); i != iend; ++i)
491        {
492            (*i)->setColourWriteEnabled(enabled);
493        }
494    }
495    //-----------------------------------------------------------------------
496    void Material::setCullingMode( CullingMode mode )
497    {
498        Techniques::iterator i, iend;
499        iend = mTechniques.end();
500        for (i = mTechniques.begin(); i != iend; ++i)
501        {
502            (*i)->setCullingMode(mode);
503        }
504    }
505    //-----------------------------------------------------------------------
506    void Material::setManualCullingMode( ManualCullingMode mode )
507    {
508        Techniques::iterator i, iend;
509        iend = mTechniques.end();
510        for (i = mTechniques.begin(); i != iend; ++i)
511        {
512            (*i)->setManualCullingMode(mode);
513        }
514    }
515    //-----------------------------------------------------------------------
516    void Material::setLightingEnabled(bool enabled)
517    {
518        Techniques::iterator i, iend;
519        iend = mTechniques.end();
520        for (i = mTechniques.begin(); i != iend; ++i)
521        {
522            (*i)->setLightingEnabled(enabled);
523        }
524    }
525    //-----------------------------------------------------------------------
526    void Material::setShadingMode( ShadeOptions mode )
527    {
528        Techniques::iterator i, iend;
529        iend = mTechniques.end();
530        for (i = mTechniques.begin(); i != iend; ++i)
531        {
532            (*i)->setShadingMode(mode);
533        }
534    }
535    //-----------------------------------------------------------------------
536    void Material::setFog(bool overrideScene, FogMode mode, const ColourValue& colour,
537        Real expDensity, Real linearStart, Real linearEnd)
538    {
539        Techniques::iterator i, iend;
540        iend = mTechniques.end();
541        for (i = mTechniques.begin(); i != iend; ++i)
542        {
543            (*i)->setFog(overrideScene, mode, colour, expDensity, linearStart, linearEnd);
544        }
545    }
546    //-----------------------------------------------------------------------
547    void Material::setDepthBias(ushort bias)
548    {
549        Techniques::iterator i, iend;
550        iend = mTechniques.end();
551        for (i = mTechniques.begin(); i != iend; ++i)
552        {
553            (*i)->setDepthBias(bias);
554        }
555    }
556    //-----------------------------------------------------------------------
557    void Material::setTextureFiltering(TextureFilterOptions filterType)
558    {
559        Techniques::iterator i, iend;
560        iend = mTechniques.end();
561        for (i = mTechniques.begin(); i != iend; ++i)
562        {
563            (*i)->setTextureFiltering(filterType);
564        }
565    }
566    // --------------------------------------------------------------------
567    void Material::setTextureAnisotropy(int maxAniso)
568    {
569        Techniques::iterator i, iend;
570        iend = mTechniques.end();
571        for (i = mTechniques.begin(); i != iend; ++i)
572        {
573            (*i)->setTextureAnisotropy(maxAniso);
574        }
575    }
576    // --------------------------------------------------------------------
577    void Material::setSceneBlending( const SceneBlendType sbt )
578    {
579        Techniques::iterator i, iend;
580        iend = mTechniques.end();
581        for (i = mTechniques.begin(); i != iend; ++i)
582        {
583            (*i)->setSceneBlending(sbt);
584        }
585    }
586    // --------------------------------------------------------------------
587    void Material::setSceneBlending( const SceneBlendFactor sourceFactor,
588        const SceneBlendFactor destFactor)
589    {
590        Techniques::iterator i, iend;
591        iend = mTechniques.end();
592        for (i = mTechniques.begin(); i != iend; ++i)
593        {
594            (*i)->setSceneBlending(sourceFactor, destFactor);
595        }
596    }
597    // --------------------------------------------------------------------
598    void Material::_notifyNeedsRecompile(void)
599    {
600        mCompilationRequired = true;
601        // Also need to unload to ensure we loaded any new items
602        unload();
603    }
604    // --------------------------------------------------------------------
605    void Material::setLodLevels(const LodDistanceList& lodDistances)
606    {
607        // Square the distances for the internal list
608                LodDistanceList::const_iterator i, iend;
609                iend = lodDistances.end();
610                // First, clear and add single zero entry
611                mLodDistances.clear();
612                mLodDistances.push_back(0.0f);
613                for (i = lodDistances.begin(); i != iend; ++i)
614                {
615                        mLodDistances.push_back((*i) * (*i));
616                }
617               
618    }
619    // --------------------------------------------------------------------
620    unsigned short Material::getLodIndex(Real d) const
621    {
622        return getLodIndexSquaredDepth(d * d);
623    }
624    // --------------------------------------------------------------------
625    unsigned short Material::getLodIndexSquaredDepth(Real squaredDistance) const
626    {
627                LodDistanceList::const_iterator i, iend;
628                iend = mLodDistances.end();
629                unsigned short index = 0;
630                for (i = mLodDistances.begin(); i != iend; ++i, ++index)
631                {
632                        if (*i > squaredDistance)
633                        {
634                                return index - 1;
635                        }
636                }
637
638                // If we fall all the way through, use the highest value
639                return static_cast<ushort>(mLodDistances.size() - 1);
640    }
641    // --------------------------------------------------------------------
642    Material::LodDistanceIterator Material::getLodDistanceIterator(void) const
643    {
644        return LodDistanceIterator(mLodDistances.begin(), mLodDistances.end());
645    }
646
647}
Note: See TracBrowser for help on using the repository browser.