source: OGRE/trunk/ogre_changes/Ogre1.2/OgreMain/src/OgreSceneManager.cpp @ 768

Revision 768, 167.2 KB checked in by szirmay, 18 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://ogre.sourceforge.net/
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 "OgreSceneManager.h"
28
29#include "OgreCamera.h"
30#include "OgreRenderSystem.h"
31#include "OgreMeshManager.h"
32#include "OgreMesh.h"
33#include "OgreSubMesh.h"
34#include "OgreEntity.h"
35#include "OgreSubEntity.h"
36#include "OgreLight.h"
37#include "OgreMath.h"
38#include "OgreControllerManager.h"
39#include "OgreMaterialManager.h"
40#include "OgreAnimation.h"
41#include "OgreAnimationTrack.h"
42#include "OgreRenderQueueSortingGrouping.h"
43#include "OgreOverlay.h"
44#include "OgreOverlayManager.h"
45#include "OgreStringConverter.h"
46#include "OgreRenderQueueListener.h"
47#include "OgreBillboardSet.h"
48#include "OgrePass.h"
49#include "OgreTechnique.h"
50#include "OgreTextureUnitState.h"
51#include "OgreException.h"
52#include "OgreLogManager.h"
53#include "OgreHardwareBufferManager.h"
54#include "OgreRoot.h"
55#include "OgreSpotShadowFadePng.h"
56#include "OgreGpuProgramManager.h"
57#include "OgreGpuProgram.h"
58#include "OgreShadowVolumeExtrudeProgram.h"
59#include "OgreDataStream.h"
60#include "OgreStaticGeometry.h"
61#include "OgreHardwarePixelBuffer.h"
62#include "OgreManualObject.h"
63#include "OgreRenderQueueInvocation.h"
64#include "OgreBillboardChain.h"
65#include "OgreRibbonTrail.h"
66#include "OgreParticleSystemManager.h"
67// This class implements the most basic scene manager
68
69#include <cstdio>
70
71namespace Ogre {
72
73//-----------------------------------------------------------------------
74uint32 SceneManager::WORLD_GEOMETRY_TYPE_MASK   = 0x80000000;
75uint32 SceneManager::ENTITY_TYPE_MASK                   = 0x40000000;
76uint32 SceneManager::FX_TYPE_MASK                               = 0x20000000;
77uint32 SceneManager::STATICGEOMETRY_TYPE_MASK   = 0x10000000;
78uint32 SceneManager::LIGHT_TYPE_MASK                    = 0x08000000;
79uint32 SceneManager::USER_TYPE_MASK_LIMIT         = SceneManager::LIGHT_TYPE_MASK;
80//-----------------------------------------------------------------------
81SceneManager::SceneManager(const String& name) :
82mName(name),
83mRenderQueue(0),
84mSkyPlaneEntity(0),
85mSkyPlaneNode(0),
86mSkyDomeNode(0),
87mSkyBoxNode(0),
88mSkyPlaneEnabled(false),
89mSkyBoxEnabled(false),
90mSkyDomeEnabled(false),
91mFogMode(FOG_NONE),
92mSpecialCaseQueueMode(SCRQM_EXCLUDE),
93mWorldGeometryRenderQueue(RENDER_QUEUE_WORLD_GEOMETRY_1),
94mLastFrameNumber(0),
95mShadowCasterPlainBlackPass(0),
96mShadowReceiverPass(0),
97mDisplayNodes(false),
98mShowBoundingBoxes(false),
99mShadowTechnique(SHADOWTYPE_NONE),
100mDebugShadows(false),
101mShadowColour(ColourValue(0.25, 0.25, 0.25)),
102mShadowDebugPass(0),
103mShadowStencilPass(0),
104mShadowModulativePass(0),
105mShadowMaterialInitDone(false),
106mShadowIndexBufferSize(51200),
107mFullScreenQuad(0),
108mShadowDirLightExtrudeDist(10000),
109mIlluminationStage(IRS_NONE),
110mShadowTextureSize(512),
111mShadowTextureCount(1),
112mShadowTextureFormat(PF_X8R8G8B8),
113mShadowUseInfiniteFarPlane(true),
114mShadowCasterSphereQuery(0),
115mShadowCasterAABBQuery(0),
116mShadowFarDist(0),
117mShadowFarDistSquared(0),
118mShadowTextureOffset(0.6),
119mShadowTextureFadeStart(0.7),
120mShadowTextureFadeEnd(0.9),
121mShadowTextureSelfShadow(false),
122mShadowTextureCustomCasterPass(0),
123mShadowTextureCustomReceiverPass(0),
124mShadowTextureCasterVPDirty(false),
125mShadowTextureReceiverVPDirty(false),
126mVisibilityMask(0xFFFFFFFF),
127mFindVisibleObjects(true),
128mSuppressRenderStateChanges(false),
129mSuppressShadows(false)
130{
131    // Root scene node
132    mSceneRoot = new SceneNode(this, "root node");
133        mSceneRoot->_notifyRootNode();
134
135    // init sky
136    size_t i;
137    for (i = 0; i < 6; ++i)
138    {
139        mSkyBoxEntity[i] = 0;
140    }
141    for (i = 0; i < 5; ++i)
142    {
143        mSkyDomeEntity[i] = 0;
144    }
145
146        mShadowCasterQueryListener = new ShadowCasterSceneQueryListener(this);
147
148    Root *root = Root::getSingletonPtr();
149    if (root)
150        _setDestinationRenderSystem(root->getRenderSystem());
151
152        // Setup default queued renderable visitor
153        mActiveQueuedRenderableVisitor = &mDefaultQueuedRenderableVisitor;
154}
155//-----------------------------------------------------------------------
156SceneManager::~SceneManager()
157{
158    clearScene();
159    destroyAllCameras();
160
161        // clear down movable object collection map
162        for (MovableObjectCollectionMap::iterator i = mMovableObjectCollectionMap.begin();
163                i != mMovableObjectCollectionMap.end(); ++i)
164        {
165                delete i->second;
166        }
167        mMovableObjectCollectionMap.clear();
168
169        delete mShadowCasterQueryListener;
170    delete mSceneRoot;
171    delete mFullScreenQuad;
172    delete mShadowCasterSphereQuery;
173    delete mShadowCasterAABBQuery;
174    delete mRenderQueue;
175}
176//-----------------------------------------------------------------------
177RenderQueue* SceneManager::getRenderQueue(void)
178{
179    if (!mRenderQueue)
180    {
181        initRenderQueue();
182    }
183    return mRenderQueue;
184}
185//-----------------------------------------------------------------------
186void SceneManager::initRenderQueue(void)
187{
188    mRenderQueue = new RenderQueue();
189    // init render queues that do not need shadows
190    mRenderQueue->getQueueGroup(RENDER_QUEUE_BACKGROUND)->setShadowsEnabled(false);
191    mRenderQueue->getQueueGroup(RENDER_QUEUE_OVERLAY)->setShadowsEnabled(false);
192    mRenderQueue->getQueueGroup(RENDER_QUEUE_SKIES_EARLY)->setShadowsEnabled(false);
193    mRenderQueue->getQueueGroup(RENDER_QUEUE_SKIES_LATE)->setShadowsEnabled(false);
194}
195//-----------------------------------------------------------------------
196void SceneManager::addSpecialCaseRenderQueue(uint8 qid)
197{
198        mSpecialCaseQueueList.insert(qid);
199}
200//-----------------------------------------------------------------------
201void SceneManager::removeSpecialCaseRenderQueue(uint8 qid)
202{
203        mSpecialCaseQueueList.erase(qid);
204}
205//-----------------------------------------------------------------------
206void SceneManager::clearSpecialCaseRenderQueues(void)
207{
208        mSpecialCaseQueueList.clear();
209}
210//-----------------------------------------------------------------------
211void SceneManager::setSpecialCaseRenderQueueMode(SceneManager::SpecialCaseRenderQueueMode mode)
212{
213        mSpecialCaseQueueMode = mode;
214}
215//-----------------------------------------------------------------------
216SceneManager::SpecialCaseRenderQueueMode SceneManager::getSpecialCaseRenderQueueMode(void)
217{
218        return mSpecialCaseQueueMode;
219}
220//-----------------------------------------------------------------------
221bool SceneManager::isRenderQueueToBeProcessed(uint8 qid)
222{
223        bool inList = mSpecialCaseQueueList.find(qid) != mSpecialCaseQueueList.end();
224        return (inList && mSpecialCaseQueueMode == SCRQM_INCLUDE)
225                || (!inList && mSpecialCaseQueueMode == SCRQM_EXCLUDE);
226}
227//-----------------------------------------------------------------------
228void SceneManager::setWorldGeometryRenderQueue(uint8 qid)
229{
230        mWorldGeometryRenderQueue = qid;
231}
232//-----------------------------------------------------------------------
233uint8 SceneManager::getWorldGeometryRenderQueue(void)
234{
235        return mWorldGeometryRenderQueue;
236}
237//-----------------------------------------------------------------------
238Camera* SceneManager::createCamera(const String& name)
239{
240    // Check name not used
241    if (mCameras.find(name) != mCameras.end())
242    {
243        OGRE_EXCEPT(
244            Exception::ERR_DUPLICATE_ITEM,
245            "A camera with the name " + name + " already exists",
246            "SceneManager::createCamera" );
247    }
248
249    Camera *c = new Camera(name, this);
250    mCameras.insert(CameraList::value_type(name, c));
251
252
253    return c;
254}
255
256//-----------------------------------------------------------------------
257Camera* SceneManager::getCamera(const String& name)
258{
259    CameraList::iterator i = mCameras.find(name);
260    if (i == mCameras.end())
261    {
262        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND,
263            "Cannot find Camera with name " + name,
264            "SceneManager::getCamera");
265    }
266    else
267    {
268        return i->second;
269    }
270}
271
272//-----------------------------------------------------------------------
273void SceneManager::destroyCamera(Camera *cam)
274{
275    // Find in list
276    CameraList::iterator i = mCameras.begin();
277    for (; i != mCameras.end(); ++i)
278    {
279        if (i->second == cam)
280        {
281            mCameras.erase(i);
282            // notify render targets
283            mDestRenderSystem->_notifyCameraRemoved(cam);
284            delete cam;
285            break;
286        }
287    }
288
289}
290
291//-----------------------------------------------------------------------
292void SceneManager::destroyCamera(const String& name)
293{
294    // Find in list
295    CameraList::iterator i = mCameras.find(name);
296    if (i != mCameras.end())
297    {
298        // Notify render system
299        mDestRenderSystem->_notifyCameraRemoved(i->second);
300        delete i->second;
301        mCameras.erase(i);
302    }
303
304}
305
306//-----------------------------------------------------------------------
307void SceneManager::destroyAllCameras(void)
308{
309
310    CameraList::iterator i = mCameras.begin();
311    for (; i != mCameras.end(); ++i)
312    {
313        // Notify render system
314        mDestRenderSystem->_notifyCameraRemoved(i->second);
315        delete i->second;
316    }
317    mCameras.clear();
318}
319//-----------------------------------------------------------------------
320Light* SceneManager::createLight(const String& name)
321{
322        return static_cast<Light*>(
323                createMovableObject(name, LightFactory::FACTORY_TYPE_NAME));
324}
325//-----------------------------------------------------------------------
326Light* SceneManager::getLight(const String& name)
327{
328        return static_cast<Light*>(
329                getMovableObject(name, LightFactory::FACTORY_TYPE_NAME));
330}
331//-----------------------------------------------------------------------
332void SceneManager::destroyLight(Light *l)
333{
334        destroyMovableObject(l);
335}
336//-----------------------------------------------------------------------
337void SceneManager::destroyLight(const String& name)
338{
339        destroyMovableObject(name, LightFactory::FACTORY_TYPE_NAME);
340}
341//-----------------------------------------------------------------------
342void SceneManager::destroyAllLights(void)
343{
344        destroyAllMovableObjectsByType(LightFactory::FACTORY_TYPE_NAME);
345}
346//-----------------------------------------------------------------------
347bool SceneManager::lightLess::operator()(const Light* a, const Light* b) const
348{
349    return a->tempSquareDist < b->tempSquareDist;
350}
351//-----------------------------------------------------------------------
352void SceneManager::_populateLightList(const Vector3& position, Real radius,
353                                                                          LightList& destList)
354{
355    // Really basic trawl of the lights, then sort
356    // Subclasses could do something smarter
357    destList.clear();
358
359        MovableObjectIterator it =
360                getMovableObjectIterator(LightFactory::FACTORY_TYPE_NAME);
361
362    while(it.hasMoreElements())
363    {
364        Light* lt = static_cast<Light*>(it.getNext());
365        if (lt->isVisible())
366        {
367            if (lt->getType() == Light::LT_DIRECTIONAL)
368            {
369                // No distance
370                lt->tempSquareDist = 0.0f;
371                destList.push_back(lt);
372            }
373            else
374            {
375                // Calc squared distance
376                lt->tempSquareDist = (lt->getDerivedPosition() - position).squaredLength();
377                // only add in-range lights
378                Real range = lt->getAttenuationRange();
379                Real maxDist = range + radius;
380                if (lt->tempSquareDist <= Math::Sqr(maxDist))
381                {
382                    destList.push_back(lt);
383                }
384            }
385        }
386    }
387
388    // Sort (stable to guarantee ordering on directional lights)
389    std::stable_sort(destList.begin(), destList.end(), lightLess());
390
391
392}
393//-----------------------------------------------------------------------
394Entity* SceneManager::createEntity(const String& entityName, PrefabType ptype)
395{
396    switch (ptype)
397    {
398    case PT_PLANE:
399        return createEntity(entityName, "Prefab_Plane");
400
401        break;
402    }
403
404    OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND,
405        "Unknown prefab type for entity " + entityName,
406        "SceneManager::createEntity");
407}
408
409//-----------------------------------------------------------------------
410Entity* SceneManager::createEntity(
411                                   const String& entityName,
412                                   const String& meshName )
413{
414        // delegate to factory implementation
415        NameValuePairList params;
416        params["mesh"] = meshName;
417        return static_cast<Entity*>(
418                createMovableObject(entityName, EntityFactory::FACTORY_TYPE_NAME,
419                        &params));
420
421}
422
423//-----------------------------------------------------------------------
424Entity* SceneManager::getEntity(const String& name)
425{
426        return static_cast<Entity*>(
427                getMovableObject(name, EntityFactory::FACTORY_TYPE_NAME));
428}
429
430//-----------------------------------------------------------------------
431void SceneManager::destroyEntity(Entity *e)
432{
433        destroyMovableObject(e);
434}
435
436//-----------------------------------------------------------------------
437void SceneManager::destroyEntity(const String& name)
438{
439        destroyMovableObject(name, EntityFactory::FACTORY_TYPE_NAME);
440
441}
442
443//-----------------------------------------------------------------------
444void SceneManager::destroyAllEntities(void)
445{
446
447        destroyAllMovableObjectsByType(EntityFactory::FACTORY_TYPE_NAME);
448}
449
450//-----------------------------------------------------------------------
451void SceneManager::destroyAllBillboardSets(void)
452{
453        destroyAllMovableObjectsByType(BillboardSetFactory::FACTORY_TYPE_NAME);
454}
455//-----------------------------------------------------------------------
456ManualObject* SceneManager::createManualObject(const String& name)
457{
458        return static_cast<ManualObject*>(
459                createMovableObject(name, ManualObjectFactory::FACTORY_TYPE_NAME));
460}
461//-----------------------------------------------------------------------
462ManualObject* SceneManager::getManualObject(const String& name)
463{
464        return static_cast<ManualObject*>(
465                getMovableObject(name, ManualObjectFactory::FACTORY_TYPE_NAME));
466
467}
468//-----------------------------------------------------------------------
469void SceneManager::destroyManualObject(ManualObject* obj)
470{
471        destroyMovableObject(obj);
472}
473//-----------------------------------------------------------------------
474void SceneManager::destroyManualObject(const String& name)
475{
476        destroyMovableObject(name, ManualObjectFactory::FACTORY_TYPE_NAME);
477}
478//-----------------------------------------------------------------------
479void SceneManager::destroyAllManualObjects(void)
480{
481        destroyAllMovableObjectsByType(ManualObjectFactory::FACTORY_TYPE_NAME);
482}
483//-----------------------------------------------------------------------
484BillboardChain* SceneManager::createBillboardChain(const String& name)
485{
486        return static_cast<BillboardChain*>(
487                createMovableObject(name, BillboardChainFactory::FACTORY_TYPE_NAME));
488}
489//-----------------------------------------------------------------------
490BillboardChain* SceneManager::getBillboardChain(const String& name)
491{
492        return static_cast<BillboardChain*>(
493                getMovableObject(name, BillboardChainFactory::FACTORY_TYPE_NAME));
494
495}
496//-----------------------------------------------------------------------
497void SceneManager::destroyBillboardChain(BillboardChain* obj)
498{
499        destroyMovableObject(obj);
500}
501//-----------------------------------------------------------------------
502void SceneManager::destroyBillboardChain(const String& name)
503{
504        destroyMovableObject(name, BillboardChainFactory::FACTORY_TYPE_NAME);
505}
506//-----------------------------------------------------------------------
507void SceneManager::destroyAllBillboardChains(void)
508{
509        destroyAllMovableObjectsByType(BillboardChainFactory::FACTORY_TYPE_NAME);
510}
511//-----------------------------------------------------------------------
512RibbonTrail* SceneManager::createRibbonTrail(const String& name)
513{
514        return static_cast<RibbonTrail*>(
515                createMovableObject(name, RibbonTrailFactory::FACTORY_TYPE_NAME));
516}
517//-----------------------------------------------------------------------
518RibbonTrail* SceneManager::getRibbonTrail(const String& name)
519{
520        return static_cast<RibbonTrail*>(
521                getMovableObject(name, RibbonTrailFactory::FACTORY_TYPE_NAME));
522
523}
524//-----------------------------------------------------------------------
525void SceneManager::destroyRibbonTrail(RibbonTrail* obj)
526{
527        destroyMovableObject(obj);
528}
529//-----------------------------------------------------------------------
530void SceneManager::destroyRibbonTrail(const String& name)
531{
532        destroyMovableObject(name, RibbonTrailFactory::FACTORY_TYPE_NAME);
533}
534//-----------------------------------------------------------------------
535void SceneManager::destroyAllRibbonTrails(void)
536{
537        destroyAllMovableObjectsByType(RibbonTrailFactory::FACTORY_TYPE_NAME);
538}
539//-----------------------------------------------------------------------
540ParticleSystem* SceneManager::createParticleSystem(const String& name,
541        const String& templateName)
542{
543        NameValuePairList params;
544        params["templateName"] = templateName;
545       
546        return static_cast<ParticleSystem*>(
547                createMovableObject(name, ParticleSystemFactory::FACTORY_TYPE_NAME,
548                        &params));
549}
550//-----------------------------------------------------------------------
551ParticleSystem* SceneManager::createParticleSystem(const String& name,
552        size_t quota, const String& group)
553{
554        NameValuePairList params;
555        params["quota"] = StringConverter::toString(quota);
556        params["resourceGroup"] = group;
557       
558        return static_cast<ParticleSystem*>(
559                createMovableObject(name, ParticleSystemFactory::FACTORY_TYPE_NAME,
560                        &params));
561}
562//-----------------------------------------------------------------------
563ParticleSystem* SceneManager::getParticleSystem(const String& name)
564{
565        return static_cast<ParticleSystem*>(
566                getMovableObject(name, ParticleSystemFactory::FACTORY_TYPE_NAME));
567
568}
569//-----------------------------------------------------------------------
570void SceneManager::destroyParticleSystem(ParticleSystem* obj)
571{
572        destroyMovableObject(obj);
573}
574//-----------------------------------------------------------------------
575void SceneManager::destroyParticleSystem(const String& name)
576{
577        destroyMovableObject(name, ParticleSystemFactory::FACTORY_TYPE_NAME);
578}
579//-----------------------------------------------------------------------
580void SceneManager::destroyAllParticleSystems(void)
581{
582        destroyAllMovableObjectsByType(ParticleSystemFactory::FACTORY_TYPE_NAME);
583}
584//-----------------------------------------------------------------------
585void SceneManager::clearScene(void)
586{
587        destroyAllStaticGeometry();
588        destroyAllMovableObjects();
589
590        // Clear root node of all children
591        mSceneRoot->removeAllChildren();
592        mSceneRoot->detachAllObjects();
593
594        // Delete all SceneNodes, except root that is
595        for (SceneNodeList::iterator i = mSceneNodes.begin();
596                i != mSceneNodes.end(); ++i)
597        {
598                delete i->second;
599        }
600        mSceneNodes.clear();
601        mAutoTrackingSceneNodes.clear();
602
603
604       
605        // Clear animations
606    destroyAllAnimations();
607
608    // Remove sky nodes since they've been deleted
609    mSkyBoxNode = mSkyPlaneNode = mSkyDomeNode = 0;
610    mSkyBoxEnabled = mSkyPlaneEnabled = mSkyDomeEnabled = false;
611
612        // Clear render queue, empty completely
613        if (mRenderQueue)
614                mRenderQueue->clear(true);
615
616}
617//-----------------------------------------------------------------------
618SceneNode* SceneManager::createSceneNode(void)
619{
620    SceneNode* sn = new SceneNode(this);
621    assert(mSceneNodes.find(sn->getName()) == mSceneNodes.end());
622    mSceneNodes[sn->getName()] = sn;
623    return sn;
624}
625//-----------------------------------------------------------------------
626SceneNode* SceneManager::createSceneNode(const String& name)
627{
628    // Check name not used
629    if (mSceneNodes.find(name) != mSceneNodes.end())
630    {
631        OGRE_EXCEPT(
632            Exception::ERR_DUPLICATE_ITEM,
633            "A scene node with the name " + name + " already exists",
634            "SceneManager::createSceneNode" );
635    }
636
637    SceneNode* sn = new SceneNode(this, name);
638    mSceneNodes[sn->getName()] = sn;
639    return sn;
640}
641//-----------------------------------------------------------------------
642void SceneManager::destroySceneNode(const String& name)
643{
644    SceneNodeList::iterator i = mSceneNodes.find(name);
645
646    if (i == mSceneNodes.end())
647    {
648        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
649            "SceneManager::destroySceneNode");
650    }
651
652    // Find any scene nodes which are tracking this node, and turn them off
653    AutoTrackingSceneNodes::iterator ai, aiend;
654    aiend = mAutoTrackingSceneNodes.end();
655    for (ai = mAutoTrackingSceneNodes.begin(); ai != aiend; )
656    {
657                // Pre-increment incase we delete
658                AutoTrackingSceneNodes::iterator curri = ai++;
659        SceneNode* n = *curri;
660        // Tracking this node
661        if (n->getAutoTrackTarget() == i->second)
662        {
663            // turn off, this will notify SceneManager to remove
664            n->setAutoTracking(false);
665        }
666        // node is itself a tracker
667        else if (n == i->second)
668        {
669            mAutoTrackingSceneNodes.erase(curri);
670        }
671    }
672
673        // detach from parent (don't do this in destructor since bulk destruction
674        // behaves differently)
675        Node* parentNode = i->second->getParent();
676        if (parentNode)
677        {
678                parentNode->removeChild(i->second);
679        }
680    delete i->second;
681    mSceneNodes.erase(i);
682}
683//-----------------------------------------------------------------------
684SceneNode* SceneManager::getRootSceneNode(void) const
685{
686    return mSceneRoot;
687}
688//-----------------------------------------------------------------------
689SceneNode* SceneManager::getSceneNode(const String& name) const
690{
691    SceneNodeList::const_iterator i = mSceneNodes.find(name);
692
693    if (i == mSceneNodes.end())
694    {
695        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
696            "SceneManager::getSceneNode");
697    }
698
699    return i->second;
700
701}
702//-----------------------------------------------------------------------
703const Pass* SceneManager::_setPass(const Pass* pass, bool evenIfSuppressed)
704{
705        if (!mSuppressRenderStateChanges || evenIfSuppressed)
706        {
707                if (mIlluminationStage == IRS_RENDER_TO_TEXTURE)
708                {
709                        // Derive a special shadow caster pass from this one
710                        pass = deriveShadowCasterPass(pass);
711                }
712                else if (mIlluminationStage == IRS_RENDER_RECEIVER_PASS)
713                {
714                        pass = deriveShadowReceiverPass(pass);
715                }
716
717                // TEST
718                /*
719                LogManager::getSingleton().logMessage("BEGIN PASS " + StringConverter::toString(pass->getIndex()) +
720                " of " + pass->getParent()->getParent()->getName());
721                */
722                bool passSurfaceAndLightParams = true;
723
724                if (pass->hasVertexProgram())
725                {
726                        mDestRenderSystem->bindGpuProgram(pass->getVertexProgram()->_getBindingDelegate());
727                        // bind parameters later since they can be per-object
728                        // does the vertex program want surface and light params passed to rendersystem?
729                        passSurfaceAndLightParams = pass->getVertexProgram()->getPassSurfaceAndLightStates();
730                }
731                else
732                {
733                        // Unbind program?
734                        if (mDestRenderSystem->isGpuProgramBound(GPT_VERTEX_PROGRAM))
735                        {
736                                mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
737                        }
738                        // Set fixed-function vertex parameters
739                }
740
741                if (passSurfaceAndLightParams)
742                {
743                        // Set surface reflectance properties, only valid if lighting is enabled
744                        if (pass->getLightingEnabled())
745                        {
746                                mDestRenderSystem->_setSurfaceParams(
747                                        pass->getAmbient(),
748                                        pass->getDiffuse(),
749                                        pass->getSpecular(),
750                                        pass->getSelfIllumination(),
751                                        pass->getShininess(),
752                        pass->getVertexColourTracking() );
753                        }
754
755                        // Dynamic lighting enabled?
756                        mDestRenderSystem->setLightingEnabled(pass->getLightingEnabled());
757                }
758
759                // Using a fragment program?
760                if (pass->hasFragmentProgram())
761                {
762                        mDestRenderSystem->bindGpuProgram(
763                                pass->getFragmentProgram()->_getBindingDelegate());
764                        // bind parameters later since they can be per-object
765                }
766                else
767                {
768                        // Unbind program?
769                        if (mDestRenderSystem->isGpuProgramBound(GPT_FRAGMENT_PROGRAM))
770                        {
771                                mDestRenderSystem->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
772                        }
773
774                        // Set fixed-function fragment settings
775                }
776
777        /* We need sets fog properties always. In D3D, it applies to shaders prior
778        to version vs_3_0 and ps_3_0. And in OGL, it applies to "ARB_fog_XXX" in
779        fragment program, and in other ways, them maybe access by gpu program via
780        "state.fog.XXX".
781        */
782        // New fog params can either be from scene or from material
783        FogMode newFogMode;
784        ColourValue newFogColour;
785        Real newFogStart, newFogEnd, newFogDensity;
786        if (pass->getFogOverride())
787        {
788            // New fog params from material
789            newFogMode = pass->getFogMode();
790            newFogColour = pass->getFogColour();
791            newFogStart = pass->getFogStart();
792            newFogEnd = pass->getFogEnd();
793            newFogDensity = pass->getFogDensity();
794        }
795        else
796        {
797            // New fog params from scene
798            newFogMode = mFogMode;
799            newFogColour = mFogColour;
800            newFogStart = mFogStart;
801            newFogEnd = mFogEnd;
802            newFogDensity = mFogDensity;
803        }
804        // Tell params about current fog
805        mAutoParamDataSource.setFog(
806            newFogMode, newFogColour, newFogDensity, newFogStart, newFogEnd);
807        mDestRenderSystem->_setFog(
808            newFogMode, newFogColour, newFogDensity, newFogStart, newFogEnd);
809
810                // The rest of the settings are the same no matter whether we use programs or not
811
812                // Set scene blending
813                mDestRenderSystem->_setSceneBlending(
814                        pass->getSourceBlendFactor(), pass->getDestBlendFactor());
815
816                // Set point parameters
817                mDestRenderSystem->_setPointParameters(
818                        pass->getPointSize(),
819                        pass->isPointAttenuationEnabled(),
820                        pass->getPointAttenuationConstant(),
821                        pass->getPointAttenuationLinear(),
822                        pass->getPointAttenuationQuadratic(),
823                        pass->getPointMinSize(),
824                        pass->getPointMaxSize());
825
826                mDestRenderSystem->_setPointSpritesEnabled(pass->getPointSpritesEnabled());
827
828                // Texture unit settings
829
830                Pass::ConstTextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
831                size_t unit = 0;
832                while(texIter.hasMoreElements())
833                {
834                        TextureUnitState* pTex = texIter.getNext();
835                        mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
836                        ++unit;
837                }
838                // Disable remaining texture units
839                mDestRenderSystem->_disableTextureUnitsFrom(pass->getNumTextureUnitStates());
840
841                // Set up non-texture related material settings
842                // Depth buffer settings
843                mDestRenderSystem->_setDepthBufferFunction(pass->getDepthFunction());
844                mDestRenderSystem->_setDepthBufferCheckEnabled(pass->getDepthCheckEnabled());
845                mDestRenderSystem->_setDepthBufferWriteEnabled(pass->getDepthWriteEnabled());
846                mDestRenderSystem->_setDepthBias(pass->getDepthBias());
847                // Alpha-reject settings
848                mDestRenderSystem->_setAlphaRejectSettings(
849                        pass->getAlphaRejectFunction(), pass->getAlphaRejectValue());
850                // Set colour write mode
851                // Right now we only use on/off, not per-channel
852                bool colWrite = pass->getColourWriteEnabled();
853                mDestRenderSystem->_setColourBufferWriteEnabled(colWrite, colWrite, colWrite, colWrite);
854                // Culling mode
855                mDestRenderSystem->_setCullingMode(pass->getCullingMode());
856                // Shading
857                mDestRenderSystem->setShadingType(pass->getShadingMode());
858                // Polygon mode
859                mDestRenderSystem->_setPolygonMode(pass->getPolygonMode());
860
861                // set pass number
862        mAutoParamDataSource.setPassNumber( pass->getIndex() );
863        }
864
865    return pass;
866}
867//-----------------------------------------------------------------------
868void SceneManager::prepareRenderQueue(void)
869{
870        RenderQueue* q = getRenderQueue();
871        // Clear the render queue
872        q->clear();
873
874        // Prep the ordering options
875
876        // If we're using a custom render squence, define based on that
877        RenderQueueInvocationSequence* seq =
878                mCurrentViewport->_getRenderQueueInvocationSequence();
879        if (seq)
880        {
881                // Iterate once to crate / reset all
882                RenderQueueInvocationIterator invokeIt = seq->iterator();
883                while (invokeIt.hasMoreElements())
884                {
885                        RenderQueueInvocation* invocation = invokeIt.getNext();
886                        RenderQueueGroup* group =
887                                q->getQueueGroup(invocation->getRenderQueueGroupID());
888                        group->resetOrganisationModes();
889                }
890                // Iterate again to build up options (may be more than one)
891                invokeIt = seq->iterator();
892                while (invokeIt.hasMoreElements())
893                {
894                        RenderQueueInvocation* invocation = invokeIt.getNext();
895                        RenderQueueGroup* group =
896                                q->getQueueGroup(invocation->getRenderQueueGroupID());
897                        group->addOrganisationMode(invocation->getSolidsOrganisation());
898                        // also set splitting options
899                        updateRenderQueueGroupSplitOptions(group, invocation->getSuppressShadows(),
900                                invocation->getSuppressRenderStateChanges());
901                }
902        }
903        else
904        {
905                // Default all the queue groups that are there, new ones will be created
906                // with defaults too
907                RenderQueue::QueueGroupIterator groupIter = q->_getQueueGroupIterator();
908                while (groupIter.hasMoreElements())
909                {
910                        RenderQueueGroup* g = groupIter.getNext();
911                        g->defaultOrganisationMode();
912                }
913                // Global split options
914                updateRenderQueueSplitOptions();
915        }
916
917}
918//-----------------------------------------------------------------------
919void SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)
920{
921    Root::getSingleton()._setCurrentSceneManager(this);
922        mActiveQueuedRenderableVisitor->targetSceneMgr = this;
923
924    if (isShadowTechniqueInUse())
925    {
926        // Prepare shadow materials
927        initShadowVolumeMaterials();
928    }
929
930    // Perform a quick pre-check to see whether we should override far distance
931    // When using stencil volumes we have to use infinite far distance
932    // to prevent dark caps getting clipped
933    if (isShadowTechniqueStencilBased() &&
934        camera->getProjectionType() == PT_PERSPECTIVE &&
935        camera->getFarClipDistance() != 0 &&
936        mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE) &&
937        mShadowUseInfiniteFarPlane)
938    {
939        // infinite far distance
940        camera->setFarClipDistance(0);
941    }
942
943    mCameraInProgress = camera;
944
945
946    // Update controllers
947    ControllerManager::getSingleton().updateAllControllers();
948
949    // Update the scene, only do this once per frame
950    unsigned long thisFrameNumber = Root::getSingleton().getCurrentFrameNumber();
951    if (thisFrameNumber != mLastFrameNumber)
952    {
953        // Update animations
954        _applySceneAnimations();
955        mLastFrameNumber = thisFrameNumber;
956    }
957
958    // Update scene graph for this camera (can happen multiple times per frame)
959    _updateSceneGraph(camera);
960
961    // Auto-track nodes
962    AutoTrackingSceneNodes::iterator atsni, atsniend;
963    atsniend = mAutoTrackingSceneNodes.end();
964    for (atsni = mAutoTrackingSceneNodes.begin(); atsni != atsniend; ++atsni)
965    {
966        (*atsni)->_autoTrack();
967    }
968    // Auto-track camera if required
969    camera->_autoTrack();
970
971
972    // Are we using any shadows at all?
973    if (isShadowTechniqueInUse() &&
974        mIlluminationStage != IRS_RENDER_TO_TEXTURE &&
975                vp->getShadowsEnabled() &&
976                mFindVisibleObjects)
977    {
978        // Locate any lights which could be affecting the frustum
979        findLightsAffectingFrustum(camera);
980        if (isShadowTechniqueTextureBased())
981        {
982            // *******
983            // WARNING
984            // *******
985            // This call will result in re-entrant calls to this method
986            // therefore anything which comes before this is NOT
987            // guaranteed persistent. Make sure that anything which
988            // MUST be specific to this camera / target is done
989            // AFTER THIS POINT
990            prepareShadowTextures(camera, vp);
991            // reset the cameras because of the re-entrant call
992            mCameraInProgress = camera;
993        }
994    }
995
996    // Invert vertex winding?
997    if (camera->isReflected())
998    {
999        mDestRenderSystem->setInvertVertexWinding(true);
1000    }
1001    else
1002    {
1003        mDestRenderSystem->setInvertVertexWinding(false);
1004    }
1005
1006    // Tell params about viewport
1007    mAutoParamDataSource.setCurrentViewport(vp);
1008    // Set the viewport
1009    setViewport(vp);
1010
1011    // Tell params about camera
1012    mAutoParamDataSource.setCurrentCamera(camera);
1013    // Set autoparams for finite dir light extrusion
1014    mAutoParamDataSource.setShadowDirLightExtrusionDistance(mShadowDirLightExtrudeDist);
1015
1016    // Tell params about current ambient light
1017    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
1018        // Tell rendersystem
1019        mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
1020
1021    // Tell params about render target
1022    mAutoParamDataSource.setCurrentRenderTarget(vp->getTarget());
1023
1024
1025    // Set camera window clipping planes (if any)
1026    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_USER_CLIP_PLANES))
1027    {
1028        if (camera->isWindowSet()) 
1029        {
1030            const std::vector<Plane>& planeList =
1031                camera->getWindowPlanes();
1032            for (ushort i = 0; i < 4; ++i)
1033            {
1034                mDestRenderSystem->enableClipPlane(i, true);
1035                mDestRenderSystem->setClipPlane(i, planeList[i]);
1036            }
1037        }
1038        else
1039        {
1040            for (ushort i = 0; i < 4; ++i)
1041            {
1042                mDestRenderSystem->enableClipPlane(i, false);
1043            }
1044        }
1045    }
1046
1047        // Prepare render queue for receiving new objects
1048#ifdef GAMETOOLS_ILLUMINATION_MODULE
1049        if (mFindVisibleObjects)
1050                prepareRenderQueue();
1051#else
1052                prepareRenderQueue();
1053#endif
1054
1055
1056    if (mFindVisibleObjects)
1057    {
1058        // Parse the scene and tag visibles
1059        _findVisibleObjects(camera,
1060            mIlluminationStage == IRS_RENDER_TO_TEXTURE? true : false);
1061    }
1062    // Add overlays, if viewport deems it
1063    if (vp->getOverlaysEnabled() && mIlluminationStage != IRS_RENDER_TO_TEXTURE)
1064    {
1065        OverlayManager::getSingleton()._queueOverlaysForRendering(camera, getRenderQueue(), vp);
1066    }
1067    // Queue skies, if viewport seems it
1068    if (vp->getSkiesEnabled() && mFindVisibleObjects && mIlluminationStage != IRS_RENDER_TO_TEXTURE)
1069    {
1070        _queueSkiesForRendering(camera);
1071    }
1072
1073
1074    mDestRenderSystem->_beginGeometryCount();
1075    // Begin the frame
1076    mDestRenderSystem->_beginFrame();
1077
1078    // Set rasterisation mode
1079    mDestRenderSystem->_setPolygonMode(camera->getPolygonMode());
1080
1081        // Set initial camera state
1082        mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrixRS());
1083        mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix(true));
1084
1085    // Render scene content
1086    _renderVisibleObjects();
1087
1088    // End frame
1089    mDestRenderSystem->_endFrame();
1090
1091    // Notify camera or vis faces
1092    camera->_notifyRenderedFaces(mDestRenderSystem->_getFaceCount());
1093
1094
1095
1096}
1097
1098
1099//-----------------------------------------------------------------------
1100void SceneManager::_setDestinationRenderSystem(RenderSystem* sys)
1101{
1102    mDestRenderSystem = sys;
1103
1104}
1105
1106
1107//-----------------------------------------------------------------------
1108void SceneManager::setWorldGeometry(const String& filename)
1109{
1110    // This default implementation cannot handle world geometry
1111    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1112        "World geometry is not supported by the generic SceneManager.",
1113        "SceneManager::setWorldGeometry");
1114}
1115//-----------------------------------------------------------------------
1116void SceneManager::setWorldGeometry(DataStreamPtr& stream,
1117        const String& typeName)
1118{
1119    // This default implementation cannot handle world geometry
1120    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1121        "World geometry is not supported by the generic SceneManager.",
1122        "SceneManager::setWorldGeometry");
1123}
1124
1125//-----------------------------------------------------------------------
1126bool SceneManager::materialLess::operator() (const Material* x, const Material* y) const
1127{
1128    // If x transparent and y not, x > y (since x has to overlap y)
1129    if (x->isTransparent() && !y->isTransparent())
1130    {
1131        return false;
1132    }
1133    // If y is transparent and x not, x < y
1134    else if (!x->isTransparent() && y->isTransparent())
1135    {
1136        return true;
1137    }
1138    else
1139    {
1140        // Otherwise don't care (both transparent or both solid)
1141        // Just arbitrarily use pointer
1142        return x < y;
1143    }
1144
1145}
1146
1147//-----------------------------------------------------------------------
1148void SceneManager::setSkyPlane(
1149                               bool enable,
1150                               const Plane& plane,
1151                               const String& materialName,
1152                               Real gscale,
1153                               Real tiling,
1154                               bool drawFirst,
1155                               Real bow,
1156                               int xsegments, int ysegments,
1157                               const String& groupName)
1158{
1159    if (enable)
1160    {
1161        String meshName = mName + "SkyPlane";
1162        mSkyPlane = plane;
1163
1164        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
1165        if (m.isNull())
1166        {
1167            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1168                "Sky plane material '" + materialName + "' not found.",
1169                "SceneManager::setSkyPlane");
1170        }
1171        // Make sure the material doesn't update the depth buffer
1172        m->setDepthWriteEnabled(false);
1173        // Ensure loaded
1174        m->load();
1175
1176        mSkyPlaneDrawFirst = drawFirst;
1177
1178        // Set up the plane
1179        MeshPtr planeMesh = MeshManager::getSingleton().getByName(meshName);
1180        if (!planeMesh.isNull())
1181        {
1182            // Destroy the old one
1183            MeshManager::getSingleton().remove(planeMesh->getHandle());
1184        }
1185
1186        // Create up vector
1187        Vector3 up = plane.normal.crossProduct(Vector3::UNIT_X);
1188        if (up == Vector3::ZERO)
1189            up = plane.normal.crossProduct(-Vector3::UNIT_Z);
1190
1191        // Create skyplane
1192        if( bow > 0 )
1193        {
1194            // Build a curved skyplane
1195            planeMesh = MeshManager::getSingleton().createCurvedPlane(
1196                meshName, groupName, plane, gscale * 100, gscale * 100, gscale * bow * 100,
1197                xsegments, ysegments, false, 1, tiling, tiling, up);
1198        }
1199        else
1200        {
1201            planeMesh = MeshManager::getSingleton().createPlane(
1202                meshName, groupName, plane, gscale * 100, gscale * 100, xsegments, ysegments, false,
1203                1, tiling, tiling, up);
1204        }
1205
1206        // Create entity
1207        if (mSkyPlaneEntity)
1208        {
1209            // destroy old one, do it by name for speed
1210            destroyEntity(meshName);
1211        }
1212        // Create, use the same name for mesh and entity
1213        mSkyPlaneEntity = createEntity(meshName, meshName);
1214        mSkyPlaneEntity->setMaterialName(materialName);
1215        mSkyPlaneEntity->setCastShadows(false);
1216
1217        // Create node and attach
1218        if (!mSkyPlaneNode)
1219        {
1220            mSkyPlaneNode = createSceneNode(meshName + "Node");
1221        }
1222        else
1223        {
1224            mSkyPlaneNode->detachAllObjects();
1225        }
1226        mSkyPlaneNode->attachObject(mSkyPlaneEntity);
1227
1228    }
1229        mSkyPlaneEnabled = enable;
1230        mSkyPlaneGenParameters.skyPlaneBow = bow;
1231        mSkyPlaneGenParameters.skyPlaneScale = gscale;
1232        mSkyPlaneGenParameters.skyPlaneTiling = tiling;
1233        mSkyPlaneGenParameters.skyPlaneXSegments = xsegments;
1234        mSkyPlaneGenParameters.skyPlaneYSegments = ysegments;
1235}
1236//-----------------------------------------------------------------------
1237void SceneManager::setSkyBox(
1238                             bool enable,
1239                             const String& materialName,
1240                             Real distance,
1241                             bool drawFirst,
1242                             const Quaternion& orientation,
1243                             const String& groupName)
1244{
1245    if (enable)
1246    {
1247        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
1248        if (m.isNull())
1249        {
1250            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1251                "Sky box material '" + materialName + "' not found.",
1252                "SceneManager::setSkyBox");
1253        }
1254        // Make sure the material doesn't update the depth buffer
1255        m->setDepthWriteEnabled(false);
1256        // Ensure loaded
1257        m->load();
1258        // Also clamp texture, don't wrap (otherwise edges can get filtered)
1259        m->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
1260
1261
1262        mSkyBoxDrawFirst = drawFirst;
1263
1264        // Create node
1265        if (!mSkyBoxNode)
1266        {
1267            mSkyBoxNode = createSceneNode("SkyBoxNode");
1268        }
1269        else
1270        {
1271            mSkyBoxNode->detachAllObjects();
1272        }
1273
1274        MaterialManager& matMgr = MaterialManager::getSingleton();
1275        // Set up the box (6 planes)
1276        for (int i = 0; i < 6; ++i)
1277        {
1278            MeshPtr planeMesh = createSkyboxPlane((BoxPlane)i, distance, orientation, groupName);
1279            String entName = mName + "SkyBoxPlane" + StringConverter::toString(i);
1280
1281            // Create entity
1282            if (mSkyBoxEntity[i])
1283            {
1284                // destroy old one, do it by name for speed
1285                destroyEntity(entName);
1286            }
1287            mSkyBoxEntity[i] = createEntity(entName, planeMesh->getName());
1288            mSkyBoxEntity[i]->setCastShadows(false);
1289            // Have to create 6 materials, one for each frame
1290            // Used to use combined material but now we're using queue we can't split to change frame
1291            // This doesn't use much memory because textures aren't duplicated
1292            MaterialPtr boxMat = matMgr.getByName(entName);
1293            if (boxMat.isNull())
1294            {
1295                // Create new by clone
1296                boxMat = m->clone(entName);
1297                boxMat->load();
1298            }
1299            else
1300            {
1301                // Copy over existing
1302                m->copyDetailsTo(boxMat);
1303                boxMat->load();
1304            }
1305            // Set active frame
1306            boxMat->getBestTechnique()->getPass(0)->getTextureUnitState(0)
1307                ->setCurrentFrame(i);
1308
1309            mSkyBoxEntity[i]->setMaterialName(boxMat->getName());
1310
1311            // Attach to node
1312            mSkyBoxNode->attachObject(mSkyBoxEntity[i]);
1313        } // for each plane
1314
1315    }
1316        mSkyBoxEnabled = enable;
1317        mSkyBoxGenParameters.skyBoxDistance = distance;
1318}
1319//-----------------------------------------------------------------------
1320void SceneManager::setSkyDome(
1321                              bool enable,
1322                              const String& materialName,
1323                              Real curvature,
1324                              Real tiling,
1325                              Real distance,
1326                              bool drawFirst,
1327                              const Quaternion& orientation,
1328                              int xsegments, int ysegments, int ySegmentsToKeep,
1329                              const String& groupName)
1330{
1331    if (enable)
1332    {
1333        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
1334        if (m.isNull())
1335        {
1336            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1337                "Sky dome material '" + materialName + "' not found.",
1338                "SceneManager::setSkyDome");
1339        }
1340        // Make sure the material doesn't update the depth buffer
1341        m->setDepthWriteEnabled(false);
1342        // Ensure loaded
1343        m->load();
1344
1345        mSkyDomeDrawFirst = drawFirst;
1346
1347        // Create node
1348        if (!mSkyDomeNode)
1349        {
1350            mSkyDomeNode = createSceneNode("SkyDomeNode");
1351        }
1352        else
1353        {
1354            mSkyDomeNode->detachAllObjects();
1355        }
1356
1357        // Set up the dome (5 planes)
1358        for (int i = 0; i < 5; ++i)
1359        {
1360            MeshPtr planeMesh = createSkydomePlane((BoxPlane)i, curvature,
1361                tiling, distance, orientation, xsegments, ysegments,
1362                i!=BP_UP ? ySegmentsToKeep : -1, groupName);
1363
1364            String entName = "SkyDomePlane" + StringConverter::toString(i);
1365
1366            // Create entity
1367            if (mSkyDomeEntity[i])
1368            {
1369                // destroy old one, do it by name for speed
1370                destroyEntity(entName);
1371            }
1372            mSkyDomeEntity[i] = createEntity(entName, planeMesh->getName());
1373            mSkyDomeEntity[i]->setMaterialName(m->getName());
1374            mSkyDomeEntity[i]->setCastShadows(false);
1375
1376            // Attach to node
1377            mSkyDomeNode->attachObject(mSkyDomeEntity[i]);
1378        } // for each plane
1379
1380    }
1381        mSkyDomeEnabled = enable;
1382        mSkyDomeGenParameters.skyDomeCurvature = curvature;
1383        mSkyDomeGenParameters.skyDomeDistance = distance;
1384        mSkyDomeGenParameters.skyDomeTiling = tiling;
1385        mSkyDomeGenParameters.skyDomeXSegments = xsegments;
1386        mSkyDomeGenParameters.skyDomeYSegments = ysegments;
1387        mSkyDomeGenParameters.skyDomeYSegments_keep = ySegmentsToKeep;
1388}
1389//-----------------------------------------------------------------------
1390MeshPtr SceneManager::createSkyboxPlane(
1391                                      BoxPlane bp,
1392                                      Real distance,
1393                                      const Quaternion& orientation,
1394                                      const String& groupName)
1395{
1396    Plane plane;
1397    String meshName;
1398    Vector3 up;
1399
1400    meshName = mName + "SkyBoxPlane_";
1401    // Set up plane equation
1402    plane.d = distance;
1403    switch(bp)
1404    {
1405    case BP_FRONT:
1406        plane.normal = Vector3::UNIT_Z;
1407        up = Vector3::UNIT_Y;
1408        meshName += "Front";
1409        break;
1410    case BP_BACK:
1411        plane.normal = -Vector3::UNIT_Z;
1412        up = Vector3::UNIT_Y;
1413        meshName += "Back";
1414        break;
1415    case BP_LEFT:
1416        plane.normal = Vector3::UNIT_X;
1417        up = Vector3::UNIT_Y;
1418        meshName += "Left";
1419        break;
1420    case BP_RIGHT:
1421        plane.normal = -Vector3::UNIT_X;
1422        up = Vector3::UNIT_Y;
1423        meshName += "Right";
1424        break;
1425    case BP_UP:
1426        plane.normal = -Vector3::UNIT_Y;
1427        up = Vector3::UNIT_Z;
1428        meshName += "Up";
1429        break;
1430    case BP_DOWN:
1431        plane.normal = Vector3::UNIT_Y;
1432        up = -Vector3::UNIT_Z;
1433        meshName += "Down";
1434        break;
1435    }
1436    // Modify by orientation
1437    plane.normal = orientation * plane.normal;
1438    up = orientation * up;
1439
1440
1441    // Check to see if existing plane
1442    MeshManager& mm = MeshManager::getSingleton();
1443    MeshPtr planeMesh = mm.getByName(meshName);
1444    if(!planeMesh.isNull())
1445    {
1446        // destroy existing
1447        mm.remove(planeMesh->getHandle());
1448    }
1449    // Create new
1450    Real planeSize = distance * 2;
1451    const int BOX_SEGMENTS = 1;
1452    planeMesh = mm.createPlane(meshName, groupName, plane, planeSize, planeSize,
1453        BOX_SEGMENTS, BOX_SEGMENTS, false, 1, 1, 1, up);
1454
1455    //planeMesh->_dumpContents(meshName);
1456
1457    return planeMesh;
1458
1459}
1460//-----------------------------------------------------------------------
1461MeshPtr SceneManager::createSkydomePlane(
1462                                       BoxPlane bp,
1463                                       Real curvature,
1464                                       Real tiling,
1465                                       Real distance,
1466                                       const Quaternion& orientation,
1467                                       int xsegments, int ysegments, int ysegments_keep,
1468                                       const String& groupName)
1469{
1470
1471    Plane plane;
1472    String meshName;
1473    Vector3 up;
1474
1475    meshName = mName + "SkyDomePlane_";
1476    // Set up plane equation
1477    plane.d = distance;
1478    switch(bp)
1479    {
1480    case BP_FRONT:
1481        plane.normal = Vector3::UNIT_Z;
1482        up = Vector3::UNIT_Y;
1483        meshName += "Front";
1484        break;
1485    case BP_BACK:
1486        plane.normal = -Vector3::UNIT_Z;
1487        up = Vector3::UNIT_Y;
1488        meshName += "Back";
1489        break;
1490    case BP_LEFT:
1491        plane.normal = Vector3::UNIT_X;
1492        up = Vector3::UNIT_Y;
1493        meshName += "Left";
1494        break;
1495    case BP_RIGHT:
1496        plane.normal = -Vector3::UNIT_X;
1497        up = Vector3::UNIT_Y;
1498        meshName += "Right";
1499        break;
1500    case BP_UP:
1501        plane.normal = -Vector3::UNIT_Y;
1502        up = Vector3::UNIT_Z;
1503        meshName += "Up";
1504        break;
1505    case BP_DOWN:
1506        // no down
1507        return MeshPtr();
1508    }
1509    // Modify by orientation
1510    plane.normal = orientation * plane.normal;
1511    up = orientation * up;
1512
1513    // Check to see if existing plane
1514    MeshManager& mm = MeshManager::getSingleton();
1515    MeshPtr planeMesh = mm.getByName(meshName);
1516    if(!planeMesh.isNull())
1517    {
1518        // destroy existing
1519        mm.remove(planeMesh->getHandle());
1520    }
1521    // Create new
1522    Real planeSize = distance * 2;
1523    planeMesh = mm.createCurvedIllusionPlane(meshName, groupName, plane,
1524        planeSize, planeSize, curvature,
1525        xsegments, ysegments, false, 1, tiling, tiling, up,
1526        orientation, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, HardwareBuffer::HBU_STATIC_WRITE_ONLY,
1527        false, false, ysegments_keep);
1528
1529    //planeMesh->_dumpContents(meshName);
1530
1531    return planeMesh;
1532
1533}
1534
1535
1536//-----------------------------------------------------------------------
1537void SceneManager::_updateSceneGraph(Camera* cam)
1538{
1539        // Process queued needUpdate calls
1540        Node::processQueuedUpdates();
1541
1542    // Cascade down the graph updating transforms & world bounds
1543    // In this implementation, just update from the root
1544    // Smarter SceneManager subclasses may choose to update only
1545    //   certain scene graph branches
1546    mSceneRoot->_update(true, false);
1547
1548
1549}
1550//-----------------------------------------------------------------------
1551void SceneManager::_findVisibleObjects(Camera* cam, bool onlyShadowCasters)
1552{
1553    // Tell nodes to find, cascade down all nodes
1554    mSceneRoot->_findVisibleObjects(cam, getRenderQueue(), true,
1555        mDisplayNodes, onlyShadowCasters);
1556
1557}
1558//-----------------------------------------------------------------------
1559void SceneManager::_renderVisibleObjects(void)
1560{
1561        RenderQueueInvocationSequence* invocationSequence =
1562                mCurrentViewport->_getRenderQueueInvocationSequence();
1563        // Use custom sequence only if we're not doing the texture shadow render
1564        // since texture shadow render should not be interfered with by suppressing
1565        // render state changes for example
1566        if (invocationSequence && mIlluminationStage != IRS_RENDER_TO_TEXTURE)
1567        {
1568                renderVisibleObjectsCustomSequence(invocationSequence);
1569        }
1570        else
1571        {
1572                renderVisibleObjectsDefaultSequence();
1573        }
1574}
1575//-----------------------------------------------------------------------
1576void SceneManager::renderVisibleObjectsCustomSequence(RenderQueueInvocationSequence* seq)
1577{
1578        RenderQueueInvocationIterator invocationIt = seq->iterator();
1579        while (invocationIt.hasMoreElements())
1580        {
1581                RenderQueueInvocation* invocation = invocationIt.getNext();
1582                uint8 qId = invocation->getRenderQueueGroupID();
1583                // Skip this one if not to be processed
1584                if (!isRenderQueueToBeProcessed(qId))
1585                        continue;
1586
1587
1588                bool repeatQueue = false;
1589                const String& invocationName = invocation->getInvocationName();
1590                RenderQueueGroup* queueGroup = getRenderQueue()->getQueueGroup(qId);
1591                do // for repeating queues
1592                {
1593                        // Fire queue started event
1594                        if (fireRenderQueueStarted(qId, invocationName))
1595                        {
1596                                // Someone requested we skip this queue
1597                                break;
1598                        }
1599
1600                        // Invoke it
1601                        invocation->invoke(queueGroup, this);
1602
1603                        // Fire queue ended event
1604                        if (fireRenderQueueEnded(qId, invocationName))
1605                        {
1606                                // Someone requested we repeat this queue
1607                                repeatQueue = true;
1608                        }
1609                        else
1610                        {
1611                                repeatQueue = false;
1612                        }
1613                } while (repeatQueue);
1614
1615
1616        }
1617}
1618//-----------------------------------------------------------------------
1619void SceneManager::renderVisibleObjectsDefaultSequence(void)
1620{
1621    // Render each separate queue
1622    RenderQueue::QueueGroupIterator queueIt = getRenderQueue()->_getQueueGroupIterator();
1623
1624    // NB only queues which have been created are rendered, no time is wasted
1625    //   parsing through non-existent queues (even though there are 10 available)
1626
1627    while (queueIt.hasMoreElements())
1628    {
1629        // Get queue group id
1630        uint8 qId = queueIt.peekNextKey();
1631                RenderQueueGroup* pGroup = queueIt.getNext();
1632                // Skip this one if not to be processed
1633                if (!isRenderQueueToBeProcessed(qId))
1634                        continue;
1635
1636
1637        bool repeatQueue = false;
1638        do // for repeating queues
1639        {
1640            // Fire queue started event
1641                        if (fireRenderQueueStarted(qId,
1642                                mIlluminationStage == IRS_RENDER_TO_TEXTURE ?
1643                                        RenderQueueInvocation::RENDER_QUEUE_INVOCATION_SHADOWS :
1644                                        StringUtil::BLANK))
1645            {
1646                // Someone requested we skip this queue
1647                break;
1648            }
1649
1650                        _renderQueueGroupObjects(pGroup, QueuedRenderableCollection::OM_PASS_GROUP);
1651
1652            // Fire queue ended event
1653                        if (fireRenderQueueEnded(qId,
1654                                mIlluminationStage == IRS_RENDER_TO_TEXTURE ?
1655                                        RenderQueueInvocation::RENDER_QUEUE_INVOCATION_SHADOWS :
1656                                        StringUtil::BLANK))
1657            {
1658                // Someone requested we repeat this queue
1659                repeatQueue = true;
1660            }
1661            else
1662            {
1663                repeatQueue = false;
1664            }
1665        } while (repeatQueue);
1666
1667    } // for each queue group
1668
1669}
1670//-----------------------------------------------------------------------
1671void SceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
1672        RenderQueueGroup* pGroup,
1673        QueuedRenderableCollection::OrganisationMode om)
1674{
1675    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1676    LightList lightList;
1677
1678    while (groupIt.hasMoreElements())
1679    {
1680        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1681
1682        // Sort the queue first
1683        pPriorityGrp->sort(mCameraInProgress);
1684
1685        // Clear light list
1686        lightList.clear();
1687
1688        // Render all the ambient passes first, no light iteration, no lights
1689        renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
1690        // Also render any objects which have receive shadows disabled
1691        renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1692
1693
1694        // Now iterate per light
1695        // Iterate over lights, render all volumes to stencil
1696        LightList::const_iterator li, liend;
1697        liend = mLightsAffectingFrustum.end();
1698
1699        for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
1700        {
1701            Light* l = *li;
1702            // Set light state
1703
1704            if (l->getCastShadows())
1705            {
1706                // Clear stencil
1707                mDestRenderSystem->clearFrameBuffer(FBT_STENCIL);
1708                renderShadowVolumesToStencil(l, mCameraInProgress);
1709                // turn stencil check on
1710                mDestRenderSystem->setStencilCheckEnabled(true);
1711                // NB we render where the stencil is equal to zero to render lit areas
1712                mDestRenderSystem->setStencilBufferParams(CMPF_EQUAL, 0);
1713            }
1714
1715            // render lighting passes for this light
1716            if (lightList.empty())
1717                lightList.push_back(l);
1718            else
1719                lightList[0] = l;
1720            renderObjects(pPriorityGrp->getSolidsDiffuseSpecular(), om, false, &lightList);
1721
1722            // Reset stencil params
1723            mDestRenderSystem->setStencilBufferParams();
1724            mDestRenderSystem->setStencilCheckEnabled(false);
1725            mDestRenderSystem->_setDepthBufferParams();
1726
1727        }// for each light
1728
1729
1730        // Now render decal passes, no need to set lights as lighting will be disabled
1731        renderObjects(pPriorityGrp->getSolidsDecal(), om, false);
1732
1733
1734    }// for each priority
1735
1736    // Iterate again - variable name changed to appease gcc.
1737    RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
1738    while (groupIt2.hasMoreElements())
1739    {
1740        RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
1741
1742        // Do transparents (always descending sort)
1743        renderObjects(pPriorityGrp->getTransparents(),
1744                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
1745
1746    }// for each priority
1747
1748
1749}
1750//-----------------------------------------------------------------------
1751void SceneManager::renderModulativeStencilShadowedQueueGroupObjects(
1752        RenderQueueGroup* pGroup,
1753        QueuedRenderableCollection::OrganisationMode om)
1754{
1755    /* For each light, we need to render all the solids from each group,
1756    then do the modulative shadows, then render the transparents from
1757    each group.
1758    Now, this means we are going to reorder things more, but that it required
1759    if the shadows are to look correct. The overall order is preserved anyway,
1760    it's just that all the transparents are at the end instead of them being
1761    interleaved as in the normal rendering loop.
1762    */
1763    // Iterate through priorities
1764    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1765
1766    while (groupIt.hasMoreElements())
1767    {
1768        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1769
1770        // Sort the queue first
1771        pPriorityGrp->sort(mCameraInProgress);
1772
1773        // Do (shadowable) solids
1774        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1775    }
1776
1777
1778    // Iterate over lights, render all volumes to stencil
1779    LightList::const_iterator li, liend;
1780    liend = mLightsAffectingFrustum.end();
1781
1782    for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
1783    {
1784        Light* l = *li;
1785        if (l->getCastShadows())
1786        {
1787            // Clear stencil
1788            mDestRenderSystem->clearFrameBuffer(FBT_STENCIL);
1789            renderShadowVolumesToStencil(l, mCameraInProgress);
1790            // render full-screen shadow modulator for all lights
1791            _setPass(mShadowModulativePass);
1792            // turn stencil check on
1793            mDestRenderSystem->setStencilCheckEnabled(true);
1794            // NB we render where the stencil is not equal to zero to render shadows, not lit areas
1795            mDestRenderSystem->setStencilBufferParams(CMPF_NOT_EQUAL, 0);
1796            renderSingleObject(mFullScreenQuad, mShadowModulativePass, false);
1797            // Reset stencil params
1798            mDestRenderSystem->setStencilBufferParams();
1799            mDestRenderSystem->setStencilCheckEnabled(false);
1800            mDestRenderSystem->_setDepthBufferParams();
1801        }
1802
1803    }// for each light
1804
1805    // Iterate again - variable name changed to appease gcc.
1806    RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
1807    while (groupIt2.hasMoreElements())
1808    {
1809        RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
1810
1811        // Do non-shadowable solids
1812        renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1813
1814    }// for each priority
1815
1816
1817    // Iterate again - variable name changed to appease gcc.
1818    RenderQueueGroup::PriorityMapIterator groupIt3 = pGroup->getIterator();
1819    while (groupIt3.hasMoreElements())
1820    {
1821        RenderPriorityGroup* pPriorityGrp = groupIt3.getNext();
1822
1823        // Do transparents (always descending sort)
1824        renderObjects(pPriorityGrp->getTransparents(),
1825                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
1826
1827    }// for each priority
1828
1829}
1830//-----------------------------------------------------------------------
1831void SceneManager::renderTextureShadowCasterQueueGroupObjects(
1832        RenderQueueGroup* pGroup,
1833        QueuedRenderableCollection::OrganisationMode om)
1834{
1835    static LightList nullLightList;
1836    // This is like the basic group render, except we skip all transparents
1837    // and we also render any non-shadowed objects
1838    // Note that non-shadow casters will have already been eliminated during
1839    // _findVisibleObjects
1840
1841    // Iterate through priorities
1842    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1843
1844    // Override auto param ambient to force vertex programs and fixed function to
1845        if (isShadowTechniqueAdditive())
1846        {
1847                // Use simple black / white mask if additive
1848                mAutoParamDataSource.setAmbientLightColour(ColourValue::Black);
1849                mDestRenderSystem->setAmbientLight(0, 0, 0);
1850        }
1851        else
1852        {
1853                // Use shadow colour as caster colour if modulative
1854                mAutoParamDataSource.setAmbientLightColour(mShadowColour);
1855                mDestRenderSystem->setAmbientLight(mShadowColour.r, mShadowColour.g, mShadowColour.b);
1856        }
1857
1858    while (groupIt.hasMoreElements())
1859    {
1860        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1861
1862        // Sort the queue first
1863        pPriorityGrp->sort(mCameraInProgress);
1864
1865        // Do solids, override light list incase any vertex programs use them
1866        renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &nullLightList);
1867        renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, false, &nullLightList);
1868                // Do transparents that cast shadows
1869                renderTransparentShadowCasterObjects(
1870                                pPriorityGrp->getTransparents(),
1871                                QueuedRenderableCollection::OM_SORT_DESCENDING,
1872                                false, &nullLightList);
1873
1874
1875    }// for each priority
1876
1877    // reset ambient light
1878    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
1879    mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
1880}
1881//-----------------------------------------------------------------------
1882void SceneManager::renderModulativeTextureShadowedQueueGroupObjects(
1883        RenderQueueGroup* pGroup,
1884        QueuedRenderableCollection::OrganisationMode om)
1885{
1886    /* For each light, we need to render all the solids from each group,
1887    then do the modulative shadows, then render the transparents from
1888    each group.
1889    Now, this means we are going to reorder things more, but that it required
1890    if the shadows are to look correct. The overall order is preserved anyway,
1891    it's just that all the transparents are at the end instead of them being
1892    interleaved as in the normal rendering loop.
1893    */
1894    // Iterate through priorities
1895    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1896
1897    while (groupIt.hasMoreElements())
1898    {
1899        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1900
1901        // Sort the queue first
1902        pPriorityGrp->sort(mCameraInProgress);
1903
1904        // Do solids
1905        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1906        renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1907    }
1908
1909
1910    // Iterate over lights, render received shadows
1911    // only perform this if we're in the 'normal' render stage, to avoid
1912    // doing it during the render to texture
1913    if (mIlluminationStage == IRS_NONE)
1914    {
1915        mIlluminationStage = IRS_RENDER_RECEIVER_PASS;
1916
1917        LightList::iterator i, iend;
1918        ShadowTextureList::iterator si, siend;
1919        iend = mLightsAffectingFrustum.end();
1920        siend = mShadowTextures.end();
1921        for (i = mLightsAffectingFrustum.begin(), si = mShadowTextures.begin();
1922            i != iend && si != siend; ++i)
1923        {
1924            Light* l = *i;
1925
1926            if (!l->getCastShadows())
1927                continue;
1928
1929                        // Store current shadow texture
1930            mCurrentShadowTexture = si->getPointer();
1931                        // Get camera for current shadow texture
1932            Camera *cam = mCurrentShadowTexture->getBuffer()->getRenderTarget()->getViewport(0)->getCamera();
1933            // Hook up receiver texture
1934                        Pass* targetPass = mShadowTextureCustomReceiverPass ?
1935                                mShadowTextureCustomReceiverPass : mShadowReceiverPass;
1936            targetPass->getTextureUnitState(0)->setTextureName(
1937                mCurrentShadowTexture->getName());
1938            // Hook up projection frustum
1939            targetPass->getTextureUnitState(0)->setProjectiveTexturing(true, cam);
1940            mAutoParamDataSource.setTextureProjector(cam);
1941            // if this light is a spotlight, we need to add the spot fader layer
1942            if (l->getType() == Light::LT_SPOTLIGHT)
1943            {
1944                                // remove all TUs except 0 & 1
1945                                // (only an issue if additive shadows have been used)
1946                                while(targetPass->getNumTextureUnitStates() > 2)
1947                                        targetPass->removeTextureUnitState(2);
1948
1949                // Add spot fader if not present already
1950                if (targetPass->getNumTextureUnitStates() == 2 &&
1951                                        targetPass->getTextureUnitState(1)->getTextureName() ==
1952                                                "spot_shadow_fade.png")
1953                                {
1954                                        // Just set
1955                                        TextureUnitState* t =
1956                                                targetPass->getTextureUnitState(1);
1957                                        t->setProjectiveTexturing(true, cam);
1958                                }
1959                else
1960                                {
1961                                        // Remove any non-conforming spot layers
1962                                        while(targetPass->getNumTextureUnitStates() > 1)
1963                                                targetPass->removeTextureUnitState(1);
1964
1965                    TextureUnitState* t =
1966                        mShadowReceiverPass->createTextureUnitState("spot_shadow_fade.png");
1967                    t->setProjectiveTexturing(true, cam);
1968                    t->setColourOperation(LBO_ADD);
1969                    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
1970                }
1971            }
1972            else
1973            {
1974                                // remove all TUs except 0 including spot
1975                                while(targetPass->getNumTextureUnitStates() > 1)
1976                        targetPass->removeTextureUnitState(1);
1977
1978            }
1979                        // Set lighting / blending modes
1980                        targetPass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
1981                        targetPass->setLightingEnabled(false);
1982
1983            targetPass->_load();
1984
1985                        // Fire pre-receiver event
1986                        fireShadowTexturesPreReceiver(l, cam);
1987
1988            renderTextureShadowReceiverQueueGroupObjects(pGroup, om);
1989
1990            ++si;
1991
1992        }// for each light
1993
1994        mIlluminationStage = IRS_NONE;
1995
1996    }
1997
1998    // Iterate again - variable name changed to appease gcc.
1999    RenderQueueGroup::PriorityMapIterator groupIt3 = pGroup->getIterator();
2000    while (groupIt3.hasMoreElements())
2001    {
2002        RenderPriorityGroup* pPriorityGrp = groupIt3.getNext();
2003
2004        // Do transparents (always descending)
2005        renderObjects(pPriorityGrp->getTransparents(),
2006                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
2007
2008    }// for each priority
2009
2010}
2011//-----------------------------------------------------------------------
2012void SceneManager::renderAdditiveTextureShadowedQueueGroupObjects(
2013        RenderQueueGroup* pGroup,
2014        QueuedRenderableCollection::OrganisationMode om)
2015{
2016        RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
2017        LightList lightList;
2018
2019        while (groupIt.hasMoreElements())
2020        {
2021                RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
2022
2023                // Sort the queue first
2024                pPriorityGrp->sort(mCameraInProgress);
2025
2026                // Clear light list
2027                lightList.clear();
2028
2029                // Render all the ambient passes first, no light iteration, no lights
2030                renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
2031                // Also render any objects which have receive shadows disabled
2032                renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
2033
2034
2035                // only perform this next part if we're in the 'normal' render stage, to avoid
2036                // doing it during the render to texture
2037                if (mIlluminationStage == IRS_NONE)
2038                {
2039                        // Iterate over lights, render masked
2040                        LightList::const_iterator li, liend;
2041                        ShadowTextureList::iterator si, siend;
2042                        liend = mLightsAffectingFrustum.end();
2043                        siend = mShadowTextures.end();
2044            si = mShadowTextures.begin();
2045
2046                        for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
2047                        {
2048                                Light* l = *li;
2049
2050                                if (l->getCastShadows() && si != siend)
2051                                {
2052                                        // Store current shadow texture
2053                                        mCurrentShadowTexture = si->getPointer();
2054                                        // Get camera for current shadow texture
2055                                        Camera *cam = mCurrentShadowTexture->getBuffer()->getRenderTarget()->getViewport(0)->getCamera();
2056                                        // Hook up receiver texture
2057                                        Pass* targetPass = mShadowTextureCustomReceiverPass ?
2058                                                mShadowTextureCustomReceiverPass : mShadowReceiverPass;
2059                                        targetPass->getTextureUnitState(0)->setTextureName(
2060                                                mCurrentShadowTexture->getName());
2061                                        // Hook up projection frustum
2062                                        targetPass->getTextureUnitState(0)->setProjectiveTexturing(true, cam);
2063                                        mAutoParamDataSource.setTextureProjector(cam);
2064                                        // Remove any spot fader layer
2065                                        if (targetPass->getNumTextureUnitStates() > 1 &&
2066                                                targetPass->getTextureUnitState(1)->getTextureName()
2067                                                        == "spot_shadow_fade.png")
2068                                        {
2069                                                // remove spot fader layer (should only be there if
2070                                                // we previously used modulative shadows)
2071                                                targetPass->removeTextureUnitState(1);
2072                                        }
2073                                        // Set lighting / blending modes
2074                                        targetPass->setSceneBlending(SBF_ONE, SBF_ONE);
2075                                        targetPass->setLightingEnabled(true);
2076                                        targetPass->_load();
2077
2078                                        // increment shadow texture since used
2079                                        ++si;
2080
2081                                        mIlluminationStage = IRS_RENDER_RECEIVER_PASS;
2082
2083                                }
2084                                else
2085                                {
2086                                        mIlluminationStage = IRS_NONE;
2087
2088                                }
2089
2090                // render lighting passes for this light
2091                if (lightList.empty())
2092                    lightList.push_back(l);
2093                else
2094                    lightList[0] = l;
2095                                renderObjects(pPriorityGrp->getSolidsDiffuseSpecular(), om, false, &lightList);
2096
2097                        }// for each light
2098
2099                        mIlluminationStage = IRS_NONE;
2100
2101                        // Now render decal passes, no need to set lights as lighting will be disabled
2102                        renderObjects(pPriorityGrp->getSolidsDecal(), om, false);
2103
2104                }
2105
2106
2107        }// for each priority
2108
2109        // Iterate again - variable name changed to appease gcc.
2110        RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
2111        while (groupIt2.hasMoreElements())
2112        {
2113                RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
2114
2115                // Do transparents (always descending sort)
2116                renderObjects(pPriorityGrp->getTransparents(),
2117                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
2118
2119        }// for each priority
2120
2121}
2122//-----------------------------------------------------------------------
2123void SceneManager::renderTextureShadowReceiverQueueGroupObjects(
2124        RenderQueueGroup* pGroup,
2125        QueuedRenderableCollection::OrganisationMode om)
2126{
2127    static LightList nullLightList;
2128
2129    // Iterate through priorities
2130    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
2131
2132    // Override auto param ambient to force vertex programs to go full-bright
2133    mAutoParamDataSource.setAmbientLightColour(ColourValue::White);
2134    mDestRenderSystem->setAmbientLight(1, 1, 1);
2135
2136    while (groupIt.hasMoreElements())
2137    {
2138        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
2139
2140        // Do solids, override light list incase any vertex programs use them
2141        renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &nullLightList);
2142
2143        // Don't render transparents or passes which have shadow receipt disabled
2144
2145    }// for each priority
2146
2147    // reset ambient
2148    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
2149    mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
2150
2151}
2152//-----------------------------------------------------------------------
2153void SceneManager::SceneMgrQueuedRenderableVisitor::visit(const Renderable* r)
2154{
2155        // Give SM a chance to eliminate
2156        if (targetSceneMgr->validateRenderableForRendering(mUsedPass, r))
2157        {
2158                // Render a single object, this will set up auto params if required
2159                targetSceneMgr->renderSingleObject(r, mUsedPass, autoLights, manualLightList);
2160        }
2161}
2162//-----------------------------------------------------------------------
2163bool SceneManager::SceneMgrQueuedRenderableVisitor::visit(const Pass* p)
2164{
2165        // Give SM a chance to eliminate this pass
2166        if (!targetSceneMgr->validatePassForRendering(p))
2167                return false;
2168
2169        // Set pass, store the actual one used
2170        mUsedPass = targetSceneMgr->_setPass(p);
2171
2172
2173        return true;
2174}
2175//-----------------------------------------------------------------------
2176void SceneManager::SceneMgrQueuedRenderableVisitor::visit(const RenderablePass* rp)
2177{
2178        // Skip this one if we're in transparency cast shadows mode & it doesn't
2179        // Don't need to implement this one in the other visit methods since
2180        // transparents are never grouped, always sorted
2181        if (transparentShadowCastersMode &&
2182                !rp->pass->getParent()->getParent()->getTransparencyCastsShadows())
2183                return;
2184
2185        // Give SM a chance to eliminate
2186        if (targetSceneMgr->validateRenderableForRendering(rp->pass, rp->renderable))
2187        {
2188                targetSceneMgr->_setPass(rp->pass);
2189                targetSceneMgr->renderSingleObject(rp->renderable, rp->pass, autoLights,
2190                        manualLightList);
2191        }
2192}
2193//-----------------------------------------------------------------------
2194bool SceneManager::validatePassForRendering(const Pass* pass)
2195{
2196    // Bypass if we're doing a texture shadow render and
2197    // this pass is after the first (only 1 pass needed for modulative shadow texture)
2198        // Also bypass if passes above the first if render state changes are
2199        // suppressed since we're not actually using this pass data anyway
2200    if (!mSuppressShadows && mCurrentViewport->getShadowsEnabled() &&
2201                isShadowTechniqueModulative() &&
2202                (mIlluminationStage == IRS_RENDER_TO_TEXTURE ||
2203        mIlluminationStage == IRS_RENDER_RECEIVER_PASS ||
2204                mSuppressRenderStateChanges) &&
2205        pass->getIndex() > 0)
2206    {
2207        return false;
2208    }
2209
2210#ifdef GAMETOOLS_ILLUMINATION_MODULE
2211        if(!pass->isActive())
2212                return false;
2213#endif
2214
2215    return true;
2216}
2217//-----------------------------------------------------------------------
2218bool SceneManager::validateRenderableForRendering(const Pass* pass, const Renderable* rend)
2219{
2220    // Skip this renderable if we're doing modulative texture shadows, it casts shadows
2221    // and we're doing the render receivers pass and we're not self-shadowing
2222    if (!mSuppressShadows && mCurrentViewport->getShadowsEnabled() &&
2223                isShadowTechniqueTextureBased() &&
2224        mIlluminationStage == IRS_RENDER_RECEIVER_PASS &&
2225        rend->getCastsShadows() && !mShadowTextureSelfShadow &&
2226                isShadowTechniqueModulative())
2227    {
2228        return false;
2229    }
2230
2231    return true;
2232
2233}
2234//-----------------------------------------------------------------------
2235void SceneManager::renderObjects(const QueuedRenderableCollection& objs,
2236                                                                 QueuedRenderableCollection::OrganisationMode om,
2237                                                                 bool doLightIteration,
2238                                 const LightList* manualLightList)
2239{
2240        mActiveQueuedRenderableVisitor->autoLights = doLightIteration;
2241        mActiveQueuedRenderableVisitor->manualLightList = manualLightList;
2242        mActiveQueuedRenderableVisitor->transparentShadowCastersMode = false;
2243        // Use visitor
2244        objs.acceptVisitor(mActiveQueuedRenderableVisitor, om);
2245}
2246//-----------------------------------------------------------------------
2247void SceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
2248                                                                                   QueuedRenderableCollection::OrganisationMode om)
2249{
2250        bool doShadows =
2251                pGroup->getShadowsEnabled() &&
2252                mCurrentViewport->getShadowsEnabled() &&
2253                !mSuppressShadows && !mSuppressRenderStateChanges;
2254       
2255    if (doShadows && mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
2256    {
2257        // Additive stencil shadows in use
2258        renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
2259    }
2260    else if (doShadows && mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
2261    {
2262        // Modulative stencil shadows in use
2263        renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
2264    }
2265    else if (isShadowTechniqueTextureBased())
2266    {
2267        // Modulative texture shadows in use
2268        if (mIlluminationStage == IRS_RENDER_TO_TEXTURE)
2269        {
2270            // Shadow caster pass
2271            if (mCurrentViewport->getShadowsEnabled() &&
2272                !mSuppressShadows && !mSuppressRenderStateChanges)
2273            {
2274                renderTextureShadowCasterQueueGroupObjects(pGroup, om);
2275            }
2276        }
2277        else
2278        {
2279            // Ordinary + receiver pass
2280            if (doShadows)
2281                        {
2282                                // Receiver pass(es)
2283                                if (isShadowTechniqueAdditive())
2284                                {
2285                                        // Additive
2286                                        renderAdditiveTextureShadowedQueueGroupObjects(pGroup, om);
2287                                }
2288                                else
2289                                {
2290                                        // Modulative
2291                        renderModulativeTextureShadowedQueueGroupObjects(pGroup, om);
2292                                }
2293                        }
2294                        else
2295                                renderBasicQueueGroupObjects(pGroup, om);
2296        }
2297    }
2298    else
2299    {
2300        // No shadows, ordinary pass
2301        renderBasicQueueGroupObjects(pGroup, om);
2302    }
2303
2304
2305}
2306//-----------------------------------------------------------------------
2307void SceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
2308                                                                                                QueuedRenderableCollection::OrganisationMode om)
2309{
2310    // Basic render loop
2311    // Iterate through priorities
2312    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
2313
2314    while (groupIt.hasMoreElements())
2315    {
2316        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
2317
2318        // Sort the queue first
2319        pPriorityGrp->sort(mCameraInProgress);
2320
2321        // Do solids
2322        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
2323        // Do transparents (always descending)
2324        renderObjects(pPriorityGrp->getTransparents(),
2325                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
2326
2327
2328    }// for each priority
2329}
2330//-----------------------------------------------------------------------
2331void SceneManager::renderTransparentShadowCasterObjects(
2332        const QueuedRenderableCollection& objs,
2333        QueuedRenderableCollection::OrganisationMode om, bool doLightIteration,
2334        const LightList* manualLightList)
2335{
2336        mActiveQueuedRenderableVisitor->transparentShadowCastersMode = true;
2337        mActiveQueuedRenderableVisitor->autoLights = doLightIteration;
2338        mActiveQueuedRenderableVisitor->manualLightList = manualLightList;
2339       
2340        // Sort descending (transparency)
2341        objs.acceptVisitor(mActiveQueuedRenderableVisitor,
2342                QueuedRenderableCollection::OM_SORT_DESCENDING);
2343
2344        mActiveQueuedRenderableVisitor->transparentShadowCastersMode = false;
2345}
2346//-----------------------------------------------------------------------
2347void SceneManager::renderSingleObject(const Renderable* rend, const Pass* pass,
2348                                      bool doLightIteration, const LightList* manualLightList)
2349{
2350    unsigned short numMatrices;
2351    static RenderOperation ro;
2352    static LightList localLightList;
2353
2354    // Set up rendering operation
2355    // I know, I know, const_cast is nasty but otherwise it requires all internal
2356    // state of the Renderable assigned to the rop to be mutable
2357    const_cast<Renderable*>(rend)->getRenderOperation(ro);
2358    ro.srcRenderable = rend;
2359
2360    // Set world transformation
2361    rend->getWorldTransforms(mTempXform);
2362    numMatrices = rend->getNumWorldTransforms();
2363    if (numMatrices > 1)
2364    {
2365        mDestRenderSystem->_setWorldMatrices(mTempXform, numMatrices);
2366    }
2367    else
2368    {
2369        mDestRenderSystem->_setWorldMatrix(*mTempXform);
2370    }
2371
2372    // Issue view / projection changes if any
2373    useRenderableViewProjMode(rend);
2374
2375    if (!mSuppressRenderStateChanges)
2376    {
2377        bool passSurfaceAndLightParams = true;
2378
2379        if (pass->isProgrammable())
2380        {
2381            // Tell auto params object about the renderable change
2382            mAutoParamDataSource.setCurrentRenderable(rend);
2383            pass->_updateAutoParamsNoLights(mAutoParamDataSource);
2384            if (pass->hasVertexProgram())
2385            {
2386                passSurfaceAndLightParams = pass->getVertexProgram()->getPassSurfaceAndLightStates();
2387            }
2388        }
2389
2390        // Reissue any texture gen settings which are dependent on view matrix
2391        Pass::ConstTextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
2392        size_t unit = 0;
2393        while(texIter.hasMoreElements())
2394        {
2395            TextureUnitState* pTex = texIter.getNext();
2396            if (pTex->hasViewRelativeTextureCoordinateGeneration())
2397            {
2398                mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
2399            }
2400            ++unit;
2401        }
2402
2403        // Sort out normalisation
2404        mDestRenderSystem->setNormaliseNormals(rend->getNormaliseNormals());
2405
2406        // Set up the solid / wireframe override
2407                // Precedence is Camera, Object, Material
2408                // Camera might not override object if not overrideable
2409                PolygonMode reqMode = pass->getPolygonMode();
2410                if (rend->getPolygonModeOverrideable())
2411                {
2412            PolygonMode camPolyMode = mCameraInProgress->getPolygonMode();
2413                        // check camera detial only when render detail is overridable
2414                        if (reqMode > camPolyMode)
2415                        {
2416                                // only downgrade detail; if cam says wireframe we don't go up to solid
2417                                reqMode = camPolyMode;
2418                        }
2419                }
2420                mDestRenderSystem->_setPolygonMode(reqMode);
2421
2422                mDestRenderSystem->setClipPlanes(rend->getClipPlanes());
2423
2424                if (doLightIteration)
2425                {
2426                        // Here's where we issue the rendering operation to the render system
2427                        // Note that we may do this once per light, therefore it's in a loop
2428                        // and the light parameters are updated once per traversal through the
2429                        // loop
2430                        const LightList& rendLightList = rend->getLights();
2431                        bool iteratePerLight = pass->getIteratePerLight();
2432                        size_t numIterations = iteratePerLight ? rendLightList.size() : 1;
2433                        const LightList* pLightListToUse;
2434                        for (size_t i = 0; i < numIterations; ++i)
2435                        {
2436                                // Determine light list to use
2437                                if (iteratePerLight)
2438                                {
2439                                        // Change the only element of local light list to be
2440                                        // the light at index i
2441                                        localLightList.clear();
2442                                        // Check whether we need to filter this one out
2443                                        if (pass->getRunOnlyForOneLightType() &&
2444                                                pass->getOnlyLightType() != rendLightList[i]->getType())
2445                                        {
2446                                                // Skip
2447                                                continue;
2448                                        }
2449
2450                                        localLightList.push_back(rendLightList[i]);
2451                                        pLightListToUse = &localLightList;
2452                                }
2453                                else
2454                                {
2455                                        // Use complete light list
2456                                        pLightListToUse = &rendLightList;
2457                                }
2458
2459
2460                                // Do we need to update GPU program parameters?
2461                                if (pass->isProgrammable())
2462                                {
2463                                        // Update any automatic gpu params for lights
2464                                        // Other bits of information will have to be looked up
2465                                        mAutoParamDataSource.setCurrentLightList(pLightListToUse);
2466                                        pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
2467                                        // NOTE: We MUST bind parameters AFTER updating the autos
2468                                        // TEST
2469                                        if (pass->hasVertexProgram())
2470                                        {
2471                                                mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM,
2472                                                        pass->getVertexProgramParameters());
2473                                        }
2474                                        if (pass->hasFragmentProgram())
2475                                        {
2476                                                mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM,
2477                                                        pass->getFragmentProgramParameters());
2478                                        }
2479                                }
2480                                // Do we need to update light states?
2481                                // Only do this if fixed-function vertex lighting applies
2482                                if (pass->getLightingEnabled() && passSurfaceAndLightParams)
2483                                {
2484                                        mDestRenderSystem->_useLights(*pLightListToUse, pass->getMaxSimultaneousLights());
2485                                }
2486                                // issue the render op         
2487                                // nfz: check for gpu_multipass
2488                                mDestRenderSystem->setCurrentPassIterationCount(pass->getPassIterationCount());
2489                                mDestRenderSystem->_render(ro);
2490                        } // possibly iterate per light
2491                }
2492                else // no automatic light processing
2493                {
2494                        // Do we need to update GPU program parameters?
2495                        if (pass->isProgrammable())
2496                        {
2497                                // Do we have a manual light list?
2498                                if (manualLightList)
2499                                {
2500                                        // Update any automatic gpu params for lights
2501                                        mAutoParamDataSource.setCurrentLightList(manualLightList);
2502                                        pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
2503                                }
2504
2505                                if (pass->hasVertexProgram())
2506                                {
2507                                        mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM,
2508                                                pass->getVertexProgramParameters());
2509                                }
2510                                if (pass->hasFragmentProgram())
2511                                {
2512                                        mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM,
2513                                                pass->getFragmentProgramParameters());
2514                                }
2515                        }
2516
2517                        // Use manual lights if present, and not using vertex programs that don't use fixed pipeline
2518                        if (manualLightList &&
2519                                pass->getLightingEnabled() && passSurfaceAndLightParams)
2520                        {
2521                                mDestRenderSystem->_useLights(*manualLightList, pass->getMaxSimultaneousLights());
2522                        }
2523                        // issue the render op         
2524                        // nfz: set up multipass rendering
2525                        mDestRenderSystem->setCurrentPassIterationCount(pass->getPassIterationCount());
2526                        mDestRenderSystem->_render(ro);
2527                }
2528
2529        }
2530        else // mSuppressRenderStateChanges
2531        {
2532                // Just render
2533                mDestRenderSystem->setCurrentPassIterationCount(1);
2534                mDestRenderSystem->_render(ro);
2535        }
2536       
2537    // Reset view / projection changes if any
2538    resetViewProjMode();
2539
2540}
2541//-----------------------------------------------------------------------
2542void SceneManager::setAmbientLight(const ColourValue& colour)
2543{
2544    mAmbientLight = colour;
2545}
2546//-----------------------------------------------------------------------
2547const ColourValue& SceneManager::getAmbientLight(void) const
2548{
2549    return mAmbientLight;
2550}
2551//-----------------------------------------------------------------------
2552ViewPoint SceneManager::getSuggestedViewpoint(bool random)
2553{
2554    // By default return the origin
2555    ViewPoint vp;
2556    vp.position = Vector3::ZERO;
2557    vp.orientation = Quaternion::IDENTITY;
2558    return vp;
2559}
2560//-----------------------------------------------------------------------
2561void SceneManager::setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
2562{
2563    mFogMode = mode;
2564    mFogColour = colour;
2565    mFogStart = start;
2566    mFogEnd = end;
2567    mFogDensity = density;
2568}
2569//-----------------------------------------------------------------------
2570FogMode SceneManager::getFogMode(void) const
2571{
2572    return mFogMode;
2573}
2574//-----------------------------------------------------------------------
2575const ColourValue& SceneManager::getFogColour(void) const
2576{
2577    return mFogColour;
2578}
2579//-----------------------------------------------------------------------
2580Real SceneManager::getFogStart(void) const
2581{
2582    return mFogStart;
2583}
2584//-----------------------------------------------------------------------
2585Real SceneManager::getFogEnd(void) const
2586{
2587    return mFogEnd;
2588}
2589//-----------------------------------------------------------------------
2590Real SceneManager::getFogDensity(void) const
2591{
2592    return mFogDensity;
2593}
2594//-----------------------------------------------------------------------
2595BillboardSet* SceneManager::createBillboardSet(const String& name, unsigned int poolSize)
2596{
2597        NameValuePairList params;
2598        params["poolSize"] = StringConverter::toString(poolSize);
2599        return static_cast<BillboardSet*>(
2600                createMovableObject(name, BillboardSetFactory::FACTORY_TYPE_NAME, &params));
2601}
2602//-----------------------------------------------------------------------
2603BillboardSet* SceneManager::getBillboardSet(const String& name)
2604{
2605        return static_cast<BillboardSet*>(
2606                getMovableObject(name, BillboardSetFactory::FACTORY_TYPE_NAME));
2607}
2608//-----------------------------------------------------------------------
2609void SceneManager::destroyBillboardSet(BillboardSet* set)
2610{
2611        destroyMovableObject(set);
2612}
2613//-----------------------------------------------------------------------
2614void SceneManager::destroyBillboardSet(const String& name)
2615{
2616        destroyMovableObject(name, BillboardSetFactory::FACTORY_TYPE_NAME);
2617}
2618//-----------------------------------------------------------------------
2619void SceneManager::setDisplaySceneNodes(bool display)
2620{
2621    mDisplayNodes = display;
2622}
2623//-----------------------------------------------------------------------
2624Animation* SceneManager::createAnimation(const String& name, Real length)
2625{
2626    // Check name not used
2627    if (mAnimationsList.find(name) != mAnimationsList.end())
2628    {
2629        OGRE_EXCEPT(
2630            Exception::ERR_DUPLICATE_ITEM,
2631            "An animation with the name " + name + " already exists",
2632            "SceneManager::createAnimation" );
2633    }
2634
2635    Animation* pAnim = new Animation(name, length);
2636    mAnimationsList[name] = pAnim;
2637    return pAnim;
2638}
2639//-----------------------------------------------------------------------
2640Animation* SceneManager::getAnimation(const String& name) const
2641{
2642    AnimationList::const_iterator i = mAnimationsList.find(name);
2643    if (i == mAnimationsList.end())
2644    {
2645        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
2646            "Cannot find animation with name " + name,
2647            "SceneManager::getAnimation");
2648    }
2649    return i->second;
2650}
2651//-----------------------------------------------------------------------
2652void SceneManager::destroyAnimation(const String& name)
2653{
2654    // Also destroy any animation states referencing this animation
2655        mAnimationStates.removeAnimationState(name);
2656
2657    AnimationList::iterator i = mAnimationsList.find(name);
2658    if (i == mAnimationsList.end())
2659    {
2660        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
2661            "Cannot find animation with name " + name,
2662            "SceneManager::getAnimation");
2663    }
2664
2665    // Free memory
2666    delete i->second;
2667
2668    mAnimationsList.erase(i);
2669
2670
2671}
2672//-----------------------------------------------------------------------
2673void SceneManager::destroyAllAnimations(void)
2674{
2675    // Destroy all states too, since they cannot reference destroyed animations
2676    destroyAllAnimationStates();
2677
2678    AnimationList::iterator i;
2679    for (i = mAnimationsList.begin(); i != mAnimationsList.end(); ++i)
2680    {
2681        // destroy
2682        delete i->second;
2683    }
2684    mAnimationsList.clear();
2685}
2686//-----------------------------------------------------------------------
2687AnimationState* SceneManager::createAnimationState(const String& animName)
2688{
2689
2690    // Get animation, this will throw an exception if not found
2691    Animation* anim = getAnimation(animName);
2692
2693    // Create new state
2694        return mAnimationStates.createAnimationState(animName, 0, anim->getLength());
2695
2696}
2697//-----------------------------------------------------------------------
2698AnimationState* SceneManager::getAnimationState(const String& animName)
2699{
2700        return mAnimationStates.getAnimationState(animName);
2701
2702}
2703//-----------------------------------------------------------------------
2704void SceneManager::destroyAnimationState(const String& name)
2705{
2706        mAnimationStates.removeAnimationState(name);
2707}
2708//-----------------------------------------------------------------------
2709void SceneManager::destroyAllAnimationStates(void)
2710{
2711    mAnimationStates.removeAllAnimationStates();
2712}
2713//-----------------------------------------------------------------------
2714void SceneManager::_applySceneAnimations(void)
2715{
2716    ConstEnabledAnimationStateIterator stateIt = mAnimationStates.getEnabledAnimationStateIterator();
2717
2718    while (stateIt.hasMoreElements())
2719    {
2720        const AnimationState* state = stateIt.getNext();
2721        Animation* anim = getAnimation(state->getAnimationName());
2722
2723        // Reset any nodes involved
2724        // NB this excludes blended animations
2725        Animation::NodeTrackIterator nodeTrackIt = anim->getNodeTrackIterator();
2726        while(nodeTrackIt.hasMoreElements())
2727        {
2728            Node* nd = nodeTrackIt.getNext()->getAssociatedNode();
2729            nd->resetToInitialState();
2730        }
2731
2732        Animation::NumericTrackIterator numTrackIt = anim->getNumericTrackIterator();
2733        while(numTrackIt.hasMoreElements())
2734        {
2735            numTrackIt.getNext()->getAssociatedAnimable()->resetToBaseValue();
2736        }
2737
2738        // Apply the animation
2739        anim->apply(state->getTimePosition(), state->getWeight());
2740    }
2741
2742
2743}
2744//---------------------------------------------------------------------
2745void SceneManager::manualRender(RenderOperation* rend,
2746                                Pass* pass, Viewport* vp, const Matrix4& worldMatrix,
2747                                const Matrix4& viewMatrix, const Matrix4& projMatrix,
2748                                bool doBeginEndFrame)
2749{
2750    mDestRenderSystem->_setViewport(vp);
2751    mDestRenderSystem->_setWorldMatrix(worldMatrix);
2752    mDestRenderSystem->_setViewMatrix(viewMatrix);
2753    mDestRenderSystem->_setProjectionMatrix(projMatrix);
2754
2755    if (doBeginEndFrame)
2756        mDestRenderSystem->_beginFrame();
2757
2758    _setPass(pass);
2759    mDestRenderSystem->_render(*rend);
2760
2761    if (doBeginEndFrame)
2762        mDestRenderSystem->_endFrame();
2763
2764}
2765//---------------------------------------------------------------------
2766void SceneManager::useRenderableViewProjMode(const Renderable* pRend)
2767{
2768    // Check view matrix
2769    bool useIdentityView = pRend->useIdentityView();
2770    if (useIdentityView)
2771    {
2772        // Using identity view now, change it
2773        mDestRenderSystem->_setViewMatrix(Matrix4::IDENTITY);
2774        mResetIdentityView = true;
2775    }
2776
2777    bool useIdentityProj = pRend->useIdentityProjection();
2778    if (useIdentityProj)
2779    {
2780        // Use identity projection matrix, still need to take RS depth into account.
2781        Matrix4 mat;
2782        mDestRenderSystem->_convertProjectionMatrix(Matrix4::IDENTITY, mat);
2783        mDestRenderSystem->_setProjectionMatrix(mat);
2784
2785        mResetIdentityProj = true;
2786    }
2787
2788   
2789}
2790//---------------------------------------------------------------------
2791void SceneManager::resetViewProjMode(void)
2792{
2793    if (mResetIdentityView)
2794    {
2795        // Coming back to normal from identity view
2796        mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix(true));
2797        mResetIdentityView = false;
2798    }
2799   
2800    if (mResetIdentityProj)
2801    {
2802        // Coming back from flat projection
2803        mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrixRS());
2804        mResetIdentityProj = false;
2805    }
2806   
2807
2808}
2809//---------------------------------------------------------------------
2810void SceneManager::_queueSkiesForRendering(Camera* cam)
2811{
2812    // Update nodes
2813    // Translate the box by the camera position (constant distance)
2814    if (mSkyPlaneNode)
2815    {
2816        // The plane position relative to the camera has already been set up
2817        mSkyPlaneNode->setPosition(cam->getDerivedPosition());
2818    }
2819
2820    if (mSkyBoxNode)
2821    {
2822        mSkyBoxNode->setPosition(cam->getDerivedPosition());
2823    }
2824
2825    if (mSkyDomeNode)
2826    {
2827        mSkyDomeNode->setPosition(cam->getDerivedPosition());
2828    }
2829
2830    uint8 qid;
2831    if (mSkyPlaneEnabled)
2832    {
2833        qid = mSkyPlaneDrawFirst?
2834RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
2835        getRenderQueue()->addRenderable(mSkyPlaneEntity->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
2836    }
2837
2838    uint plane;
2839    if (mSkyBoxEnabled)
2840    {
2841        qid = mSkyBoxDrawFirst?
2842RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
2843
2844        for (plane = 0; plane < 6; ++plane)
2845        {
2846            getRenderQueue()->addRenderable(
2847                mSkyBoxEntity[plane]->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
2848        }
2849    }
2850
2851    if (mSkyDomeEnabled)
2852    {
2853        qid = mSkyDomeDrawFirst?
2854RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
2855
2856        for (plane = 0; plane < 5; ++plane)
2857        {
2858            getRenderQueue()->addRenderable(
2859                mSkyDomeEntity[plane]->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
2860        }
2861    }
2862}
2863//---------------------------------------------------------------------
2864void SceneManager::addRenderQueueListener(RenderQueueListener* newListener)
2865{
2866    mRenderQueueListeners.push_back(newListener);
2867}
2868//---------------------------------------------------------------------
2869void SceneManager::removeRenderQueueListener(RenderQueueListener* delListener)
2870{
2871    RenderQueueListenerList::iterator i, iend;
2872    iend = mRenderQueueListeners.end();
2873    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
2874    {
2875        if (*i == delListener)
2876        {
2877            mRenderQueueListeners.erase(i);
2878            break;
2879        }
2880    }
2881
2882}
2883//---------------------------------------------------------------------
2884void SceneManager::addShadowListener(ShadowListener* newListener)
2885{
2886    mShadowListeners.push_back(newListener);
2887}
2888//---------------------------------------------------------------------
2889void SceneManager::removeShadowListener(ShadowListener* delListener)
2890{
2891    ShadowListenerList::iterator i, iend;
2892    iend = mShadowListeners.end();
2893    for (i = mShadowListeners.begin(); i != iend; ++i)
2894    {
2895        if (*i == delListener)
2896        {
2897            mShadowListeners.erase(i);
2898            break;
2899        }
2900    }
2901
2902}
2903//---------------------------------------------------------------------
2904bool SceneManager::fireRenderQueueStarted(uint8 id, const String& invocation)
2905{
2906    RenderQueueListenerList::iterator i, iend;
2907    bool skip = false;
2908
2909    iend = mRenderQueueListeners.end();
2910    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
2911    {
2912        (*i)->renderQueueStarted(id, invocation, skip);
2913    }
2914    return skip;
2915}
2916//---------------------------------------------------------------------
2917bool SceneManager::fireRenderQueueEnded(uint8 id, const String& invocation)
2918{
2919    RenderQueueListenerList::iterator i, iend;
2920    bool repeat = false;
2921
2922    iend = mRenderQueueListeners.end();
2923    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
2924    {
2925        (*i)->renderQueueEnded(id, invocation, repeat);
2926    }
2927    return repeat;
2928}
2929//---------------------------------------------------------------------
2930void SceneManager::fireShadowTexturesUpdated(size_t numberOfShadowTextures)
2931{
2932    ShadowListenerList::iterator i, iend;
2933
2934    iend = mShadowListeners.end();
2935    for (i = mShadowListeners.begin(); i != iend; ++i)
2936    {
2937        (*i)->shadowTexturesUpdated(numberOfShadowTextures);
2938    }
2939}
2940//---------------------------------------------------------------------
2941void SceneManager::fireShadowTexturesPreCaster(Light* light, Camera* camera)
2942{
2943    ShadowListenerList::iterator i, iend;
2944
2945    iend = mShadowListeners.end();
2946    for (i = mShadowListeners.begin(); i != iend; ++i)
2947    {
2948        (*i)->shadowTextureCasterPreViewProj(light, camera);
2949    }
2950}
2951//---------------------------------------------------------------------
2952void SceneManager::fireShadowTexturesPreReceiver(Light* light, Frustum* f)
2953{
2954    ShadowListenerList::iterator i, iend;
2955
2956    iend = mShadowListeners.end();
2957    for (i = mShadowListeners.begin(); i != iend; ++i)
2958    {
2959        (*i)->shadowTextureReceiverPreViewProj(light, f);
2960    }
2961}
2962//---------------------------------------------------------------------
2963void SceneManager::setViewport(Viewport* vp)
2964{
2965    mCurrentViewport = vp;
2966    // Set viewport in render system
2967    mDestRenderSystem->_setViewport(vp);
2968        // Set the active material scheme for this viewport
2969        MaterialManager::getSingleton().setActiveScheme(vp->getMaterialScheme());
2970}
2971//---------------------------------------------------------------------
2972void SceneManager::showBoundingBoxes(bool bShow)
2973{
2974    mShowBoundingBoxes = bShow;
2975}
2976//---------------------------------------------------------------------
2977bool SceneManager::getShowBoundingBoxes() const
2978{
2979    return mShowBoundingBoxes;
2980}
2981//---------------------------------------------------------------------
2982void SceneManager::_notifyAutotrackingSceneNode(SceneNode* node, bool autoTrack)
2983{
2984    if (autoTrack)
2985    {
2986        mAutoTrackingSceneNodes.insert(node);
2987    }
2988    else
2989    {
2990        mAutoTrackingSceneNodes.erase(node);
2991    }
2992}
2993//---------------------------------------------------------------------
2994void SceneManager::setShadowTechnique(ShadowTechnique technique)
2995{
2996    mShadowTechnique = technique;
2997    if (isShadowTechniqueStencilBased())
2998    {
2999        // Firstly check that we  have a stencil
3000        // Otherwise forget it
3001        if (!mDestRenderSystem->getCapabilities()->hasCapability(RSC_HWSTENCIL))
3002        {
3003            LogManager::getSingleton().logMessage(
3004                "WARNING: Stencil shadows were requested, but this device does not "
3005                "have a hardware stencil. Shadows disabled.");
3006            mShadowTechnique = SHADOWTYPE_NONE;
3007        }
3008        else if (mShadowIndexBuffer.isNull())
3009        {
3010            // Create an estimated sized shadow index buffer
3011            mShadowIndexBuffer = HardwareBufferManager::getSingleton().
3012                createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
3013                mShadowIndexBufferSize,
3014                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,
3015                false);
3016            // tell all meshes to prepare shadow volumes
3017            MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(true);
3018        }
3019        }
3020
3021    if (isShadowTechniqueTextureBased())
3022    {
3023        createShadowTextures(mShadowTextureSize, mShadowTextureCount, mShadowTextureFormat);
3024    }
3025    else
3026    {
3027        // Destroy shadow textures to optimise resource usage
3028        destroyShadowTextures();
3029    }
3030
3031}
3032//---------------------------------------------------------------------
3033void SceneManager::_suppressShadows(bool suppress)
3034{
3035        mSuppressShadows = suppress;
3036}
3037//---------------------------------------------------------------------
3038void SceneManager::_suppressRenderStateChanges(bool suppress)
3039{
3040        mSuppressRenderStateChanges = suppress;
3041}
3042//---------------------------------------------------------------------
3043void SceneManager::updateRenderQueueSplitOptions(void)
3044{
3045        if (isShadowTechniqueStencilBased())
3046        {
3047                // Casters can always be receivers
3048                getRenderQueue()->setShadowCastersCannotBeReceivers(false);
3049        }
3050        else // texture based
3051        {
3052                getRenderQueue()->setShadowCastersCannotBeReceivers(!mShadowTextureSelfShadow);
3053        }
3054
3055        if (isShadowTechniqueAdditive() && mCurrentViewport->getShadowsEnabled())
3056        {
3057                // Additive lighting, we need to split everything by illumination stage
3058                getRenderQueue()->setSplitPassesByLightingType(true);
3059        }
3060        else
3061        {
3062                getRenderQueue()->setSplitPassesByLightingType(false);
3063        }
3064
3065        if (isShadowTechniqueInUse() && mCurrentViewport->getShadowsEnabled())
3066        {
3067                // Tell render queue to split off non-shadowable materials
3068                getRenderQueue()->setSplitNoShadowPasses(true);
3069        }
3070        else
3071        {
3072                getRenderQueue()->setSplitNoShadowPasses(false);
3073        }
3074
3075
3076}
3077//---------------------------------------------------------------------
3078void SceneManager::updateRenderQueueGroupSplitOptions(RenderQueueGroup* group,
3079        bool suppressShadows, bool suppressRenderState)
3080{
3081        if (isShadowTechniqueStencilBased())
3082        {
3083                // Casters can always be receivers
3084                group->setShadowCastersCannotBeReceivers(false);
3085        }
3086        else if (isShadowTechniqueTextureBased())
3087        {
3088                group->setShadowCastersCannotBeReceivers(!mShadowTextureSelfShadow);
3089        }
3090
3091        if (!suppressShadows && mCurrentViewport->getShadowsEnabled() &&
3092                isShadowTechniqueAdditive())
3093        {
3094                // Additive lighting, we need to split everything by illumination stage
3095                group->setSplitPassesByLightingType(true);
3096        }
3097        else
3098        {
3099                group->setSplitPassesByLightingType(false);
3100        }
3101
3102        if (!suppressShadows && mCurrentViewport->getShadowsEnabled()
3103                && isShadowTechniqueInUse())
3104        {
3105                // Tell render queue to split off non-shadowable materials
3106                group->setSplitNoShadowPasses(true);
3107        }
3108        else
3109        {
3110                group->setSplitNoShadowPasses(false);
3111        }
3112
3113
3114}
3115//---------------------------------------------------------------------
3116void SceneManager::findLightsAffectingFrustum(const Camera* camera)
3117{
3118    // Basic iteration for this SM
3119    mLightsAffectingFrustum.clear();
3120    Sphere sphere;
3121        MovableObjectIterator it =
3122                getMovableObjectIterator(LightFactory::FACTORY_TYPE_NAME);
3123    while(it.hasMoreElements())
3124    {
3125        Light* l = static_cast<Light*>(it.getNext());
3126                if (l->isVisible())
3127                {
3128                        if (l->getType() == Light::LT_DIRECTIONAL)
3129                        {
3130                                // Always visible
3131                                mLightsAffectingFrustum.push_back(l);
3132                        }
3133                        else
3134                        {
3135                                // NB treating spotlight as point for simplicity
3136                                // Just see if the lights attenuation range is within the frustum
3137                                sphere.setCenter(l->getDerivedPosition());
3138                                sphere.setRadius(l->getAttenuationRange());
3139                                if (camera->isVisible(sphere))
3140                                {
3141                                        mLightsAffectingFrustum.push_back(l);
3142                                }
3143
3144                        }
3145                }
3146    }
3147
3148}
3149//---------------------------------------------------------------------
3150bool SceneManager::ShadowCasterSceneQueryListener::queryResult(
3151    MovableObject* object)
3152{
3153    if (object->getCastShadows() && object->isVisible() &&
3154                mSceneMgr->isRenderQueueToBeProcessed(object->getRenderQueueGroup()))
3155    {
3156        if (mFarDistSquared)
3157        {
3158            // Check object is within the shadow far distance
3159            Vector3 toObj = object->getParentNode()->_getDerivedPosition()
3160                - mCamera->getDerivedPosition();
3161            Real radius = object->getWorldBoundingSphere().getRadius();
3162            Real dist =  toObj.squaredLength();               
3163            if (dist - (radius * radius) > mFarDistSquared)
3164            {
3165                // skip, beyond max range
3166                return true;
3167            }
3168        }
3169
3170        // If the object is in the frustum, we can always see the shadow
3171        if (mCamera->isVisible(object->getWorldBoundingBox()))
3172        {
3173            mCasterList->push_back(object);
3174            return true;
3175        }
3176
3177        // Otherwise, object can only be casting a shadow into our view if
3178        // the light is outside the frustum (or it's a directional light,
3179        // which are always outside), and the object is intersecting
3180        // on of the volumes formed between the edges of the frustum and the
3181        // light
3182        if (!mIsLightInFrustum || mLight->getType() == Light::LT_DIRECTIONAL)
3183        {
3184            // Iterate over volumes
3185            PlaneBoundedVolumeList::const_iterator i, iend;
3186            iend = mLightClipVolumeList->end();
3187            for (i = mLightClipVolumeList->begin(); i != iend; ++i)
3188            {
3189                if (i->intersects(object->getWorldBoundingBox()))
3190                {
3191                    mCasterList->push_back(object);
3192                    return true;
3193                }
3194
3195            }
3196
3197        }
3198    }
3199    return true;
3200}
3201//---------------------------------------------------------------------
3202bool SceneManager::ShadowCasterSceneQueryListener::queryResult(
3203    SceneQuery::WorldFragment* fragment)
3204{
3205    // don't deal with world geometry
3206    return true;
3207}
3208//---------------------------------------------------------------------
3209const SceneManager::ShadowCasterList& SceneManager::findShadowCastersForLight(
3210    const Light* light, const Camera* camera)
3211{
3212    mShadowCasterList.clear();
3213
3214    if (light->getType() == Light::LT_DIRECTIONAL)
3215    {
3216        // Basic AABB query encompassing the frustum and the extrusion of it
3217        AxisAlignedBox aabb;
3218        const Vector3* corners = camera->getWorldSpaceCorners();
3219        Vector3 min, max;
3220        Vector3 extrude = light->getDerivedDirection() * -mShadowDirLightExtrudeDist;
3221        // do first corner
3222        min = max = corners[0];
3223        min.makeFloor(corners[0] + extrude);
3224        max.makeCeil(corners[0] + extrude);
3225        for (size_t c = 1; c < 8; ++c)
3226        {
3227            min.makeFloor(corners[c]);
3228            max.makeCeil(corners[c]);
3229            min.makeFloor(corners[c] + extrude);
3230            max.makeCeil(corners[c] + extrude);
3231        }
3232        aabb.setExtents(min, max);
3233
3234        if (!mShadowCasterAABBQuery)
3235            mShadowCasterAABBQuery = createAABBQuery(aabb);
3236        else
3237            mShadowCasterAABBQuery->setBox(aabb);
3238        // Execute, use callback
3239        mShadowCasterQueryListener->prepare(false,
3240            &(light->_getFrustumClipVolumes(camera)),
3241            light, camera, &mShadowCasterList, mShadowFarDistSquared);
3242        mShadowCasterAABBQuery->execute(mShadowCasterQueryListener);
3243
3244
3245    }
3246    else
3247    {
3248        Sphere s(light->getDerivedPosition(), light->getAttenuationRange());
3249        // eliminate early if camera cannot see light sphere
3250        if (camera->isVisible(s))
3251        {
3252            if (!mShadowCasterSphereQuery)
3253                mShadowCasterSphereQuery = createSphereQuery(s);
3254            else
3255                mShadowCasterSphereQuery->setSphere(s);
3256
3257            // Determine if light is inside or outside the frustum
3258            bool lightInFrustum = camera->isVisible(light->getDerivedPosition());
3259            const PlaneBoundedVolumeList* volList = 0;
3260            if (!lightInFrustum)
3261            {
3262                // Only worth building an external volume list if
3263                // light is outside the frustum
3264                volList = &(light->_getFrustumClipVolumes(camera));
3265            }
3266
3267            // Execute, use callback
3268            mShadowCasterQueryListener->prepare(lightInFrustum,
3269                volList, light, camera, &mShadowCasterList, mShadowFarDistSquared);
3270            mShadowCasterSphereQuery->execute(mShadowCasterQueryListener);
3271
3272        }
3273
3274    }
3275
3276
3277    return mShadowCasterList;
3278}
3279//---------------------------------------------------------------------
3280void SceneManager::initShadowVolumeMaterials(void)
3281{
3282    /* This should have been set in the SceneManager constructor, but if you
3283       created the SceneManager BEFORE the Root object, you will need to call
3284       SceneManager::_setDestinationRenderSystem manually.
3285     */
3286    assert( mDestRenderSystem );
3287
3288    if (mShadowMaterialInitDone)
3289        return;
3290
3291    if (!mShadowDebugPass)
3292    {
3293        MaterialPtr matDebug =
3294            MaterialManager::getSingleton().getByName("Ogre/Debug/ShadowVolumes");
3295        if (matDebug.isNull())
3296        {
3297            // Create
3298            matDebug = MaterialManager::getSingleton().create(
3299                "Ogre/Debug/ShadowVolumes",
3300                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3301            mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
3302            mShadowDebugPass->setSceneBlending(SBT_ADD);
3303            mShadowDebugPass->setLightingEnabled(false);
3304            mShadowDebugPass->setDepthWriteEnabled(false);
3305            TextureUnitState* t = mShadowDebugPass->createTextureUnitState();
3306            t->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
3307                ColourValue(0.7, 0.0, 0.2));
3308            mShadowDebugPass->setCullingMode(CULL_NONE);
3309
3310            if (mDestRenderSystem->getCapabilities()->hasCapability(
3311                RSC_VERTEX_PROGRAM))
3312            {
3313                ShadowVolumeExtrudeProgram::initialise();
3314
3315                // Enable the (infinite) point light extruder for now, just to get some params
3316                mShadowDebugPass->setVertexProgram(
3317                    ShadowVolumeExtrudeProgram::programNames[ShadowVolumeExtrudeProgram::POINT_LIGHT]);
3318                mInfiniteExtrusionParams =
3319                    mShadowDebugPass->getVertexProgramParameters();
3320                mInfiniteExtrusionParams->setAutoConstant(0,
3321                    GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
3322                mInfiniteExtrusionParams->setAutoConstant(4,
3323                    GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
3324            }   
3325            matDebug->compile();
3326
3327        }
3328        else
3329        {
3330            mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
3331
3332            if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
3333            {
3334                mInfiniteExtrusionParams = mShadowDebugPass->getVertexProgramParameters();
3335            }
3336        }
3337    }
3338
3339    if (!mShadowStencilPass)
3340    {
3341
3342        MaterialPtr matStencil = MaterialManager::getSingleton().getByName(
3343            "Ogre/StencilShadowVolumes");
3344        if (matStencil.isNull())
3345        {
3346            // Init
3347            matStencil = MaterialManager::getSingleton().create(
3348                "Ogre/StencilShadowVolumes",
3349                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3350            mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
3351
3352            if (mDestRenderSystem->getCapabilities()->hasCapability(
3353                RSC_VERTEX_PROGRAM))
3354            {
3355
3356                // Enable the finite point light extruder for now, just to get some params
3357                mShadowStencilPass->setVertexProgram(
3358                    ShadowVolumeExtrudeProgram::programNames[ShadowVolumeExtrudeProgram::POINT_LIGHT_FINITE]);
3359                mFiniteExtrusionParams =
3360                    mShadowStencilPass->getVertexProgramParameters();
3361                mFiniteExtrusionParams->setAutoConstant(0,
3362                    GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
3363                mFiniteExtrusionParams->setAutoConstant(4,
3364                    GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
3365                // Note extra parameter
3366                mFiniteExtrusionParams->setAutoConstant(5,
3367                    GpuProgramParameters::ACT_SHADOW_EXTRUSION_DISTANCE);
3368            }
3369            matStencil->compile();
3370            // Nothing else, we don't use this like a 'real' pass anyway,
3371            // it's more of a placeholder
3372        }
3373        else
3374        {
3375            mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
3376
3377            if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
3378            {
3379                mFiniteExtrusionParams = mShadowStencilPass->getVertexProgramParameters();
3380            }
3381        }
3382    }
3383
3384
3385
3386
3387    if (!mShadowModulativePass)
3388    {
3389
3390        MaterialPtr matModStencil = MaterialManager::getSingleton().getByName(
3391            "Ogre/StencilShadowModulationPass");
3392        if (matModStencil.isNull())
3393        {
3394            // Init
3395            matModStencil = MaterialManager::getSingleton().create(
3396                "Ogre/StencilShadowModulationPass",
3397                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3398            mShadowModulativePass = matModStencil->getTechnique(0)->getPass(0);
3399            mShadowModulativePass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
3400            mShadowModulativePass->setLightingEnabled(false);
3401            mShadowModulativePass->setDepthWriteEnabled(false);
3402            mShadowModulativePass->setDepthCheckEnabled(false);
3403            TextureUnitState* t = mShadowModulativePass->createTextureUnitState();
3404            t->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
3405                mShadowColour);
3406            mShadowModulativePass->setCullingMode(CULL_NONE);
3407        }
3408        else
3409        {
3410            mShadowModulativePass = matModStencil->getTechnique(0)->getPass(0);
3411        }
3412    }
3413
3414    // Also init full screen quad while we're at it
3415    if (!mFullScreenQuad)
3416    {
3417        mFullScreenQuad = new Rectangle2D();
3418        mFullScreenQuad->setCorners(-1,1,1,-1);
3419    }
3420
3421    // Also init shadow caster material for texture shadows
3422    if (!mShadowCasterPlainBlackPass)
3423    {
3424        MaterialPtr matPlainBlack = MaterialManager::getSingleton().getByName(
3425            "Ogre/TextureShadowCaster");
3426        if (matPlainBlack.isNull())
3427        {
3428            matPlainBlack = MaterialManager::getSingleton().create(
3429                "Ogre/TextureShadowCaster",
3430                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3431            mShadowCasterPlainBlackPass = matPlainBlack->getTechnique(0)->getPass(0);
3432            // Lighting has to be on, because we need shadow coloured objects
3433            // Note that because we can't predict vertex programs, we'll have to
3434            // bind light values to those, and so we bind White to ambient
3435            // reflectance, and we'll set the ambient colour to the shadow colour
3436            mShadowCasterPlainBlackPass->setAmbient(ColourValue::White);
3437            mShadowCasterPlainBlackPass->setDiffuse(ColourValue::Black);
3438            mShadowCasterPlainBlackPass->setSelfIllumination(ColourValue::Black);
3439            mShadowCasterPlainBlackPass->setSpecular(ColourValue::Black);
3440                        // Override fog
3441                        mShadowCasterPlainBlackPass->setFog(true, FOG_NONE);
3442            // no textures or anything else, we will bind vertex programs
3443            // every so often though
3444        }
3445        else
3446        {
3447            mShadowCasterPlainBlackPass = matPlainBlack->getTechnique(0)->getPass(0);
3448        }
3449    }
3450
3451    if (!mShadowReceiverPass)
3452    {
3453        MaterialPtr matShadRec = MaterialManager::getSingleton().getByName(
3454            "Ogre/TextureShadowReceiver");
3455        if (matShadRec.isNull())                       
3456        {
3457            matShadRec = MaterialManager::getSingleton().create(
3458                "Ogre/TextureShadowReceiver",
3459                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3460            mShadowReceiverPass = matShadRec->getTechnique(0)->getPass(0);
3461                        // Don't set lighting and blending modes here, depends on additive / modulative
3462            TextureUnitState* t = mShadowReceiverPass->createTextureUnitState();
3463            t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
3464        }
3465        else
3466        {
3467            mShadowReceiverPass = matShadRec->getTechnique(0)->getPass(0);
3468        }
3469    }
3470
3471    // Set up spot shadow fade texture (loaded from code data block)
3472    TexturePtr spotShadowFadeTex =
3473        TextureManager::getSingleton().getByName("spot_shadow_fade.png");
3474    if (spotShadowFadeTex.isNull())
3475    {
3476        // Load the manual buffer into an image (don't destroy memory!
3477        DataStreamPtr stream(
3478                        new MemoryDataStream(SPOT_SHADOW_FADE_PNG, SPOT_SHADOW_FADE_PNG_SIZE, false));
3479        Image img;
3480        img.load(stream, "png");
3481        spotShadowFadeTex =
3482            TextureManager::getSingleton().loadImage(
3483                        "spot_shadow_fade.png", ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
3484                        img, TEX_TYPE_2D);
3485    }
3486
3487    mShadowMaterialInitDone = true;
3488}
3489//---------------------------------------------------------------------
3490const Pass* SceneManager::deriveShadowCasterPass(const Pass* pass)
3491{
3492        if (isShadowTechniqueTextureBased())
3493    {
3494                Pass* retPass = mShadowTextureCustomCasterPass ?
3495                        mShadowTextureCustomCasterPass : mShadowCasterPlainBlackPass;
3496
3497               
3498                // Special case alpha-blended passes
3499                if ((pass->getSourceBlendFactor() == SBF_SOURCE_ALPHA &&
3500                        pass->getDestBlendFactor() == SBF_ONE_MINUS_SOURCE_ALPHA)
3501                        || pass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
3502                {
3503                        // Alpha blended passes must retain their transparency
3504                        retPass->setAlphaRejectSettings(pass->getAlphaRejectFunction(),
3505                                pass->getAlphaRejectValue());
3506                        retPass->setSceneBlending(pass->getSourceBlendFactor(), pass->getDestBlendFactor());
3507                        retPass->getParent()->getParent()->setTransparencyCastsShadows(true);
3508
3509                        // So we allow the texture units, but override the colour functions
3510                        // Copy texture state, shift up one since 0 is shadow texture
3511                        size_t origPassTUCount = pass->getNumTextureUnitStates();
3512                        for (size_t t = 0; t < origPassTUCount; ++t)
3513                        {
3514                                TextureUnitState* tex;
3515                                if (retPass->getNumTextureUnitStates() <= t)
3516                                {
3517                                        tex = retPass->createTextureUnitState();
3518                                }
3519                                else
3520                                {
3521                                        tex = retPass->getTextureUnitState(t);
3522                                }
3523                                // copy base state
3524                                (*tex) = *(pass->getTextureUnitState(t));
3525                                // override colour function
3526                                tex->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT,
3527                                        isShadowTechniqueAdditive()? ColourValue::Black : mShadowColour);
3528
3529                        }
3530                        // Remove any extras
3531                        while (retPass->getNumTextureUnitStates() > origPassTUCount)
3532                        {
3533                                retPass->removeTextureUnitState(origPassTUCount);
3534                        }
3535
3536                }
3537                else
3538                {
3539                        // reset
3540                        retPass->setSceneBlending(SBT_REPLACE);
3541                        retPass->setAlphaRejectFunction(CMPF_ALWAYS_PASS);
3542                        while (retPass->getNumTextureUnitStates() > 0)
3543                        {
3544                                retPass->removeTextureUnitState(0);
3545                        }
3546                }
3547
3548                // Propagate culling modes
3549                retPass->setCullingMode(pass->getCullingMode());
3550                retPass->setManualCullingMode(pass->getManualCullingMode());
3551               
3552
3553                if (!pass->getShadowCasterVertexProgramName().empty())
3554                {
3555                        // Have to merge the shadow caster vertex program in
3556                        retPass->setVertexProgram(
3557                                pass->getShadowCasterVertexProgramName());
3558                        const GpuProgramPtr& prg = retPass->getVertexProgram();
3559                        // Load this program if not done already
3560                        if (!prg->isLoaded())
3561                                prg->load();
3562                        // Copy params
3563                        retPass->setVertexProgramParameters(
3564                                pass->getShadowCasterVertexProgramParameters());
3565                        if (retPass == mShadowTextureCustomCasterPass)
3566                        {
3567                                // mark that we've overridden the standard
3568                                mShadowTextureCasterVPDirty = true;
3569                        }
3570                        // Also have to hack the light autoparams, that is done later
3571                }
3572                else
3573                {
3574                        retPass->setVertexProgram(StringUtil::BLANK);
3575                        if (mShadowTextureCasterVPDirty)
3576                        {
3577                                // reset
3578                                mShadowTextureCustomCasterPass->setVertexProgram(
3579                                        mShadowTextureCustomCasterVertexProgram);
3580                                if(mShadowTextureCustomCasterPass->hasVertexProgram())
3581                                {
3582                                        mShadowTextureCustomCasterPass->setVertexProgramParameters(
3583                                                mShadowTextureCustomCasterVPParams);
3584
3585                                }
3586                                mShadowTextureCasterVPDirty = false;
3587                        }
3588                }
3589                return retPass;
3590        }
3591        else
3592        {
3593        return pass;
3594    }
3595
3596}
3597//---------------------------------------------------------------------
3598const Pass* SceneManager::deriveShadowReceiverPass(const Pass* pass)
3599{
3600
3601    if (isShadowTechniqueTextureBased())
3602    {
3603                Pass* retPass = mShadowTextureCustomReceiverPass ?
3604                        mShadowTextureCustomReceiverPass : mShadowReceiverPass;
3605
3606                if (pass->hasVertexProgram())
3607                {
3608                        // Have to merge the receiver vertex program in
3609                        retPass->setVertexProgram(
3610                                pass->getShadowReceiverVertexProgramName());
3611                        // Did this result in a new vertex program?
3612                        if (retPass->hasVertexProgram())
3613                        {
3614                                const GpuProgramPtr& prg = retPass->getVertexProgram();
3615                                // Load this program if required
3616                                if (!prg->isLoaded())
3617                                        prg->load();
3618                                // Copy params
3619                                retPass->setVertexProgramParameters(
3620                                        pass->getShadowReceiverVertexProgramParameters());
3621
3622                                if (retPass == mShadowTextureCustomReceiverPass)
3623                                {
3624                                        // mark that we've overridden the standard
3625                                        mShadowTextureReceiverVPDirty = true;
3626                                }
3627                        }
3628                        // Also have to hack the light autoparams, that is done later
3629                }
3630                else
3631                {
3632                        retPass->setVertexProgram(StringUtil::BLANK);
3633                }
3634
3635                bool resetFragmentProgram = true;
3636        size_t keepTUCount;
3637                // If additive, need lighting parameters & standard programs
3638                if (isShadowTechniqueAdditive())
3639                {
3640                        keepTUCount = 1;
3641                        retPass->setLightingEnabled(true);
3642                        retPass->setAmbient(pass->getAmbient());
3643                        retPass->setSelfIllumination(pass->getSelfIllumination());
3644                        retPass->setDiffuse(pass->getDiffuse());
3645                        retPass->setSpecular(pass->getSpecular());
3646                        retPass->setShininess(pass->getShininess());
3647                        retPass->setIteratePerLight(pass->getIteratePerLight(),
3648                                pass->getRunOnlyForOneLightType(), pass->getOnlyLightType());
3649
3650            // We need to keep alpha rejection settings
3651            retPass->setAlphaRejectSettings(pass->getAlphaRejectFunction(),
3652                pass->getAlphaRejectValue());
3653            // Copy texture state, shift up one since 0 is shadow texture
3654            size_t origPassTUCount = pass->getNumTextureUnitStates();
3655            for (size_t t = 0; t < origPassTUCount; ++t)
3656            {
3657                size_t targetIndex = t+1;
3658                TextureUnitState* tex;
3659                if (retPass->getNumTextureUnitStates() <= targetIndex)
3660                {
3661                    tex = retPass->createTextureUnitState();
3662                }
3663                else
3664                {
3665                    tex = retPass->getTextureUnitState(targetIndex);
3666                }
3667                (*tex) = *(pass->getTextureUnitState(t));
3668            }
3669            keepTUCount = origPassTUCount + 1;
3670
3671                        // Will also need fragment programs since this is a complex light setup
3672                        if (pass->hasFragmentProgram())
3673                        {
3674                                String fragName = pass->getShadowReceiverFragmentProgramName();
3675                                GpuProgramParametersSharedPtr params;
3676                                if (!fragName.empty())
3677                                {
3678                                        resetFragmentProgram = false;
3679
3680                                        params = pass->getShadowReceiverFragmentProgramParameters();
3681
3682                                        retPass->setFragmentProgram(fragName);
3683                                        const GpuProgramPtr& prg = retPass->getFragmentProgram();
3684                                        // Load this program if required
3685                                        if (!prg->isLoaded())
3686                                                prg->load();
3687                                        // Copy params
3688                                        retPass->setFragmentProgramParameters(params);
3689
3690                                        // Did we bind a shadow vertex program?
3691                                        if (pass->hasVertexProgram() && !retPass->hasVertexProgram())
3692                                        {
3693                                                // We didn't bind a receiver-specific program, so bind the original
3694                                                retPass->setVertexProgram(pass->getVertexProgramName());
3695                                                const GpuProgramPtr& prg = retPass->getVertexProgram();
3696                                                // Load this program if required
3697                                                if (!prg->isLoaded())
3698                                                        prg->load();
3699                                                // Copy params
3700                                                retPass->setVertexProgramParameters(
3701                                                        pass->getVertexProgramParameters());
3702
3703                                                if (retPass == mShadowTextureCustomReceiverPass)
3704                                                {
3705                                                        // mark that we've overridden the standard
3706                                                        mShadowTextureReceiverVPDirty = true;
3707                                                }
3708                                        }
3709                                } // valid shadow fragment program
3710                        } // ori pass has fragment program
3711                       
3712                }// additive lighting
3713                else
3714                {
3715                        // need to keep spotlight fade etc
3716                        keepTUCount = retPass->getNumTextureUnitStates();
3717                }
3718
3719                // reset fragment program
3720                if (resetFragmentProgram)
3721                {
3722                        retPass->setFragmentProgram(StringUtil::BLANK);
3723                }
3724        // Remove any extra texture units
3725        while (retPass->getNumTextureUnitStates() > keepTUCount)
3726        {
3727            retPass->removeTextureUnitState(keepTUCount);
3728        }
3729
3730                // reset vertex program
3731                if (retPass->hasVertexProgram() && !pass->hasVertexProgram())
3732                {
3733                        // reset
3734                        retPass->setVertexProgram("");
3735
3736                        if (mShadowTextureReceiverVPDirty)
3737                        {
3738                                // reset
3739                                mShadowTextureCustomReceiverPass->setVertexProgram(
3740                                        mShadowTextureCustomReceiverVertexProgram);
3741                                if(mShadowTextureCustomReceiverPass->hasVertexProgram())
3742                                {
3743                                        mShadowTextureCustomReceiverPass->setVertexProgramParameters(
3744                                                mShadowTextureCustomReceiverVPParams);
3745
3746                                }
3747                                mShadowTextureReceiverVPDirty = false;
3748                        }
3749                }
3750
3751                retPass->_load();
3752
3753                return retPass;
3754        }
3755        else
3756        {
3757        return pass;
3758    }
3759
3760}
3761//---------------------------------------------------------------------
3762void SceneManager::renderShadowVolumesToStencil(const Light* light, const Camera* camera)
3763{
3764    // Get the shadow caster list
3765    const ShadowCasterList& casters = findShadowCastersForLight(light, camera);
3766    // Check there are some shadow casters to render
3767    if (casters.empty())
3768    {
3769        // No casters, just do nothing
3770        return;
3771    }
3772
3773    // Set up scissor test (point & spot lights only)
3774    bool scissored = false;
3775    if (light->getType() != Light::LT_DIRECTIONAL &&
3776        mDestRenderSystem->getCapabilities()->hasCapability(RSC_SCISSOR_TEST))
3777    {
3778        // Project the sphere onto the camera
3779        Real left, right, top, bottom;
3780        Sphere sphere(light->getDerivedPosition(), light->getAttenuationRange());
3781        if (camera->projectSphere(sphere, &left, &top, &right, &bottom))
3782        {
3783            scissored = true;
3784            // Turn normalised device coordinates into pixels
3785            int iLeft, iTop, iWidth, iHeight;
3786            mCurrentViewport->getActualDimensions(iLeft, iTop, iWidth, iHeight);
3787            size_t szLeft, szRight, szTop, szBottom;
3788
3789            szLeft = (size_t)(iLeft + ((left + 1) * 0.5 * iWidth));
3790            szRight = (size_t)(iLeft + ((right + 1) * 0.5 * iWidth));
3791            szTop = (size_t)(iTop + ((-top + 1) * 0.5 * iHeight));
3792            szBottom = (size_t)(iTop + ((-bottom + 1) * 0.5 * iHeight));
3793
3794            mDestRenderSystem->setScissorTest(true, szLeft, szTop, szRight, szBottom);
3795        }
3796    }
3797
3798    mDestRenderSystem->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
3799
3800    // Can we do a 2-sided stencil?
3801    bool stencil2sided = false;
3802    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_TWO_SIDED_STENCIL) &&
3803        mDestRenderSystem->getCapabilities()->hasCapability(RSC_STENCIL_WRAP))
3804    {
3805        // enable
3806        stencil2sided = true;
3807    }
3808
3809    // Do we have access to vertex programs?
3810    bool extrudeInSoftware = true;
3811    bool finiteExtrude = !mShadowUseInfiniteFarPlane ||
3812        !mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE);
3813    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
3814    {
3815        extrudeInSoftware = false;
3816        // attach the appropriate extrusion vertex program
3817        // Note we never unset it because support for vertex programs is constant
3818        mShadowStencilPass->setVertexProgram(
3819            ShadowVolumeExtrudeProgram::getProgramName(light->getType(), finiteExtrude, false)
3820            , false);
3821        // Set params
3822        if (finiteExtrude)
3823        {
3824            mShadowStencilPass->setVertexProgramParameters(mFiniteExtrusionParams);
3825        }
3826        else
3827        {
3828            mShadowStencilPass->setVertexProgramParameters(mInfiniteExtrusionParams);
3829        }
3830        if (mDebugShadows)
3831        {
3832            mShadowDebugPass->setVertexProgram(
3833                ShadowVolumeExtrudeProgram::getProgramName(light->getType(), finiteExtrude, true)
3834                , false);
3835            // Set params
3836            if (finiteExtrude)
3837            {
3838                mShadowDebugPass->setVertexProgramParameters(mFiniteExtrusionParams);
3839            }
3840            else
3841            {
3842                mShadowDebugPass->setVertexProgramParameters(mInfiniteExtrusionParams);
3843            }
3844        }
3845
3846        mDestRenderSystem->bindGpuProgram(mShadowStencilPass->getVertexProgram()->_getBindingDelegate());
3847
3848    }
3849    else
3850    {
3851        mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
3852    }
3853
3854    // Add light to internal list for use in render call
3855    LightList lightList;
3856    // const_cast is forgiveable here since we pass this const
3857    lightList.push_back(const_cast<Light*>(light));
3858
3859    // Turn off colour writing and depth writing
3860    mDestRenderSystem->_setColourBufferWriteEnabled(false, false, false, false);
3861        mDestRenderSystem->_disableTextureUnitsFrom(0);
3862    mDestRenderSystem->_setDepthBufferParams(true, false, CMPF_LESS);
3863    mDestRenderSystem->setStencilCheckEnabled(true);
3864
3865    // Calculate extrusion distance
3866    // Use direction light extrusion distance now, just form optimize code
3867    // generate a little, point/spot light will up to date later
3868    Real extrudeDist = mShadowDirLightExtrudeDist;
3869
3870    // Figure out the near clip volume
3871    const PlaneBoundedVolume& nearClipVol =
3872        light->_getNearClipVolume(camera);
3873
3874    // Now iterate over the casters and render
3875    ShadowCasterList::const_iterator si, siend;
3876    siend = casters.end();
3877
3878
3879        // Now iterate over the casters and render
3880        for (si = casters.begin(); si != siend; ++si)
3881        {
3882        ShadowCaster* caster = *si;
3883                bool zfailAlgo = camera->isCustomNearClipPlaneEnabled();
3884                unsigned long flags = 0;
3885
3886        if (light->getType() != Light::LT_DIRECTIONAL)
3887        {
3888            extrudeDist = caster->getPointExtrusionDistance(light);
3889        }
3890
3891        if (!extrudeInSoftware && !finiteExtrude)
3892        {
3893            // hardware extrusion, to infinity (and beyond!)
3894            flags |= SRF_EXTRUDE_TO_INFINITY;
3895        }
3896
3897                // Determine whether zfail is required
3898        if (nearClipVol.intersects(caster->getWorldBoundingBox()))
3899        {
3900            // We use zfail for this object only because zfail
3901                // compatible with zpass algorithm
3902                        zfailAlgo = true;
3903            // We need to include the light and / or dark cap
3904            // But only if they will be visible
3905            if(camera->isVisible(caster->getLightCapBounds()))
3906            {
3907                flags |= SRF_INCLUDE_LIGHT_CAP;
3908            }
3909                        // zfail needs dark cap
3910                        // UNLESS directional lights using hardware extrusion to infinity
3911                        // since that extrudes to a single point
3912                        if(!((flags & SRF_EXTRUDE_TO_INFINITY) &&
3913                                light->getType() == Light::LT_DIRECTIONAL) &&
3914                                camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
3915                        {
3916                                flags |= SRF_INCLUDE_DARK_CAP;
3917                        }
3918        }
3919                else
3920                {
3921                        // In zpass we need a dark cap if
3922                        // 1: infinite extrusion on point/spotlight sources in modulative shadows
3923                        //    mode, since otherwise in areas where there is no depth (skybox)
3924                        //    the infinitely projected volume will leave a dark band
3925                        // 2: finite extrusion on any light source since glancing angles
3926                        //    can peek through the end and shadow objects behind incorrectly
3927                        if ((flags & SRF_EXTRUDE_TO_INFINITY) &&
3928                                light->getType() != Light::LT_DIRECTIONAL &&
3929                                isShadowTechniqueModulative() &&
3930                                camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
3931                        {
3932                                flags |= SRF_INCLUDE_DARK_CAP;
3933                        }
3934                        else if (!(flags & SRF_EXTRUDE_TO_INFINITY) &&
3935                                camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
3936                        {
3937                                flags |= SRF_INCLUDE_DARK_CAP;
3938                        }
3939
3940                }
3941
3942        // Get shadow renderables                       
3943        ShadowCaster::ShadowRenderableListIterator iShadowRenderables =
3944            caster->getShadowVolumeRenderableIterator(mShadowTechnique,
3945            light, &mShadowIndexBuffer, extrudeInSoftware,
3946            extrudeDist, flags);
3947
3948        // Render a shadow volume here
3949        //  - if we have 2-sided stencil, one render with no culling
3950        //  - otherwise, 2 renders, one with each culling method and invert the ops
3951        setShadowVolumeStencilState(false, zfailAlgo, stencil2sided);
3952        renderShadowVolumeObjects(iShadowRenderables, mShadowStencilPass, &lightList, flags,
3953            false, zfailAlgo, stencil2sided);
3954        if (!stencil2sided)
3955        {
3956            // Second pass
3957            setShadowVolumeStencilState(true, zfailAlgo, false);
3958            renderShadowVolumeObjects(iShadowRenderables, mShadowStencilPass, &lightList, flags,
3959                true, zfailAlgo, false);
3960        }
3961
3962        // Do we need to render a debug shadow marker?
3963        if (mDebugShadows)
3964        {
3965            // reset stencil & colour ops
3966            mDestRenderSystem->setStencilBufferParams();
3967            mShadowDebugPass->getTextureUnitState(0)->
3968                setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
3969                zfailAlgo ? ColourValue(0.7, 0.0, 0.2) : ColourValue(0.0, 0.7, 0.2));
3970            _setPass(mShadowDebugPass);
3971            renderShadowVolumeObjects(iShadowRenderables, mShadowDebugPass, &lightList, flags,
3972                true, false, false);
3973            mDestRenderSystem->_setColourBufferWriteEnabled(false, false, false, false);
3974            mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
3975        }
3976    }
3977
3978    // revert colour write state
3979    mDestRenderSystem->_setColourBufferWriteEnabled(true, true, true, true);
3980    // revert depth state
3981    mDestRenderSystem->_setDepthBufferParams();
3982
3983    mDestRenderSystem->setStencilCheckEnabled(false);
3984
3985    mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
3986
3987    if (scissored)
3988    {
3989        // disable scissor test
3990        mDestRenderSystem->setScissorTest(false);
3991    }
3992
3993}
3994//---------------------------------------------------------------------
3995void SceneManager::renderShadowVolumeObjects(ShadowCaster::ShadowRenderableListIterator iShadowRenderables,
3996                                             Pass* pass,
3997                                             const LightList *manualLightList,
3998                                             unsigned long flags,
3999                                             bool secondpass, bool zfail, bool twosided)
4000{
4001    // ----- SHADOW VOLUME LOOP -----
4002    // Render all shadow renderables with same stencil operations
4003    while (iShadowRenderables.hasMoreElements())
4004    {
4005        ShadowRenderable* sr = iShadowRenderables.getNext();
4006
4007        // omit hidden renderables
4008        if (sr->isVisible())
4009        {
4010            // render volume, including dark and (maybe) light caps
4011            renderSingleObject(sr, pass, false, manualLightList);
4012
4013            // optionally render separate light cap
4014            if (sr->isLightCapSeparate() && (flags & SRF_INCLUDE_LIGHT_CAP))
4015            {
4016                ShadowRenderable* lightCap = sr->getLightCapRenderable();
4017                assert(lightCap && "Shadow renderable is missing a separate light cap renderable!");
4018
4019                // We must take care with light caps when we could 'see' the back facing
4020                // triangles directly:
4021                //   1. The front facing light caps must render as always fail depth
4022                //      check to avoid 'depth fighting'.
4023                //   2. The back facing light caps must use normal depth function to
4024                //      avoid break the standard depth check
4025                //
4026                // TODO:
4027                //   1. Separate light caps rendering doesn't need for the 'closed'
4028                //      mesh that never touch the near plane, because in this instance,
4029                //      we couldn't 'see' any back facing triangles directly. The
4030                //      'closed' mesh must determinate by edge list builder.
4031                //   2. There still exists 'depth fighting' bug with coplane triangles
4032                //      that has opposite facing. This usually occur when use two side
4033                //      material in the modeling tools and the model exporting tools
4034                //      exporting double triangles to represent this model. This bug
4035                //      can't fixed in GPU only, there must has extra work on edge list
4036                //      builder and shadow volume generater to fix it.
4037                //
4038                if (twosided)
4039                {
4040                    // select back facing light caps to render
4041                    mDestRenderSystem->_setCullingMode(CULL_ANTICLOCKWISE);
4042                    // use normal depth function for back facing light caps
4043                    renderSingleObject(lightCap, pass, false, manualLightList);
4044
4045                    // select front facing light caps to render
4046                    mDestRenderSystem->_setCullingMode(CULL_CLOCKWISE);
4047                    // must always fail depth check for front facing light caps
4048                    mDestRenderSystem->_setDepthBufferFunction(CMPF_ALWAYS_FAIL);
4049                    renderSingleObject(lightCap, pass, false, manualLightList);
4050
4051                    // reset depth function
4052                    mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
4053                    // reset culling mode
4054                    mDestRenderSystem->_setCullingMode(CULL_NONE);
4055                }
4056                else if ((secondpass || zfail) && !(secondpass && zfail))
4057                {
4058                    // use normal depth function for back facing light caps
4059                    renderSingleObject(lightCap, pass, false, manualLightList);
4060                }
4061                else
4062                {
4063                    // must always fail depth check for front facing light caps
4064                    mDestRenderSystem->_setDepthBufferFunction(CMPF_ALWAYS_FAIL);
4065                    renderSingleObject(lightCap, pass, false, manualLightList);
4066
4067                    // reset depth function
4068                    mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
4069                }
4070            }
4071        }
4072    }
4073}
4074//---------------------------------------------------------------------
4075void SceneManager::setShadowVolumeStencilState(bool secondpass, bool zfail, bool twosided)
4076{
4077    // Determinate the best stencil operation
4078    StencilOperation incrOp, decrOp;
4079    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_STENCIL_WRAP))
4080    {
4081        incrOp = SOP_INCREMENT_WRAP;
4082        decrOp = SOP_DECREMENT_WRAP;
4083    }
4084    else
4085    {
4086        incrOp = SOP_INCREMENT;
4087        decrOp = SOP_DECREMENT;
4088    }
4089
4090    // First pass, do front faces if zpass
4091    // Second pass, do back faces if zpass
4092    // Invert if zfail
4093    // this is to ensure we always increment before decrement
4094    // When two-sided stencil, always pass front face stencil
4095    // operation parameters and the inverse of them will happen
4096    // for back faces
4097    if ( !twosided && ((secondpass || zfail) && !(secondpass && zfail)) )
4098    {
4099        mDestRenderSystem->_setCullingMode(
4100            twosided? CULL_NONE : CULL_ANTICLOCKWISE);
4101        mDestRenderSystem->setStencilBufferParams(
4102            CMPF_ALWAYS_PASS, // always pass stencil check
4103            0, // no ref value (no compare)
4104            0xFFFFFFFF, // no mask
4105            SOP_KEEP, // stencil test will never fail
4106            zfail ? incrOp : SOP_KEEP, // back face depth fail
4107            zfail ? SOP_KEEP : decrOp, // back face pass
4108            twosided
4109            );
4110    }
4111    else
4112    {
4113        mDestRenderSystem->_setCullingMode(
4114            twosided? CULL_NONE : CULL_CLOCKWISE);
4115        mDestRenderSystem->setStencilBufferParams(
4116            CMPF_ALWAYS_PASS, // always pass stencil check
4117            0, // no ref value (no compare)
4118            0xFFFFFFFF, // no mask
4119            SOP_KEEP, // stencil test will never fail
4120            zfail ? decrOp : SOP_KEEP, // front face depth fail
4121            zfail ? SOP_KEEP : incrOp, // front face pass
4122            twosided
4123            );
4124    }
4125}
4126//---------------------------------------------------------------------
4127void SceneManager::setShadowColour(const ColourValue& colour)
4128{
4129    mShadowColour = colour;
4130
4131    // Change shadow material setting only when it's prepared,
4132    // otherwise, it'll set up while preparing shadow materials.
4133    if (mShadowModulativePass)
4134    {
4135        mShadowModulativePass->getTextureUnitState(0)->setColourOperationEx(
4136            LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, colour);
4137    }
4138}
4139//---------------------------------------------------------------------
4140const ColourValue& SceneManager::getShadowColour(void) const
4141{
4142    return mShadowColour;
4143}
4144//---------------------------------------------------------------------
4145void SceneManager::setShadowFarDistance(Real distance)
4146{
4147    mShadowFarDist = distance;
4148    mShadowFarDistSquared = distance * distance;
4149}
4150//---------------------------------------------------------------------
4151void SceneManager::setShadowDirectionalLightExtrusionDistance(Real dist)
4152{
4153    mShadowDirLightExtrudeDist = dist;
4154}
4155//---------------------------------------------------------------------
4156Real SceneManager::getShadowDirectionalLightExtrusionDistance(void) const
4157{
4158    return mShadowDirLightExtrudeDist;
4159}
4160//---------------------------------------------------------------------
4161void SceneManager::setShadowIndexBufferSize(size_t size)
4162{
4163    if (!mShadowIndexBuffer.isNull() && size != mShadowIndexBufferSize)
4164    {
4165        // re-create shadow buffer with new size
4166        mShadowIndexBuffer = HardwareBufferManager::getSingleton().
4167            createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
4168            mShadowIndexBufferSize,
4169            HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,
4170            false);
4171    }
4172    mShadowIndexBufferSize = size;
4173}
4174//---------------------------------------------------------------------
4175void SceneManager::setShadowTextureSize(unsigned short size)
4176{
4177    // possibly recreate
4178    createShadowTextures(size, mShadowTextureCount, mShadowTextureFormat);
4179    mShadowTextureSize = size;
4180}
4181//---------------------------------------------------------------------
4182void SceneManager::setShadowTextureCount(unsigned short count)
4183{
4184    // possibly recreate
4185    createShadowTextures(mShadowTextureSize, count, mShadowTextureFormat);
4186    mShadowTextureCount = count;
4187}
4188//---------------------------------------------------------------------
4189void SceneManager::setShadowTexturePixelFormat(PixelFormat fmt)
4190{
4191        // possibly recreate
4192        createShadowTextures(mShadowTextureSize, mShadowTextureCount, fmt);
4193        mShadowTextureFormat = fmt;
4194}
4195//---------------------------------------------------------------------
4196void SceneManager::setShadowTextureSettings(unsigned short size,
4197        unsigned short count, PixelFormat fmt)
4198{
4199    if (!mShadowTextures.empty() &&
4200        (count != mShadowTextureCount ||
4201        size != mShadowTextureSize ||
4202                fmt != mShadowTextureFormat))
4203    {
4204        // recreate
4205        createShadowTextures(size, count, fmt);
4206    }
4207    mShadowTextureCount = count;
4208    mShadowTextureSize = size;
4209        mShadowTextureFormat = fmt;
4210}
4211//---------------------------------------------------------------------
4212void SceneManager::setShadowTextureSelfShadow(bool selfShadow)
4213{
4214        mShadowTextureSelfShadow = selfShadow;
4215        if (isShadowTechniqueTextureBased())
4216                getRenderQueue()->setShadowCastersCannotBeReceivers(!selfShadow);
4217}
4218//---------------------------------------------------------------------
4219void SceneManager::setShadowTextureCasterMaterial(const String& name)
4220{
4221        if (name.empty())
4222        {
4223                mShadowTextureCustomCasterPass = 0;
4224        }
4225        else
4226        {
4227                MaterialPtr mat = MaterialManager::getSingleton().getByName(name);
4228                if (mat.isNull())
4229                {
4230                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
4231                                "Cannot locate material called '" + name + "'",
4232                                "SceneManager::setShadowTextureCasterMaterial");
4233                }
4234                mat->load();
4235                mShadowTextureCustomCasterPass = mat->getBestTechnique()->getPass(0);
4236                if (mShadowTextureCustomCasterPass->hasVertexProgram())
4237                {
4238                        // Save vertex program and params in case we have to swap them out
4239                        mShadowTextureCustomCasterVertexProgram =
4240                                mShadowTextureCustomCasterPass->getVertexProgramName();
4241                        mShadowTextureCustomCasterVPParams =
4242                                mShadowTextureCustomCasterPass->getVertexProgramParameters();
4243                        mShadowTextureCasterVPDirty = false;
4244
4245                }
4246        }
4247}
4248//---------------------------------------------------------------------
4249void SceneManager::setShadowTextureReceiverMaterial(const String& name)
4250{
4251        if (name.empty())
4252        {
4253                mShadowTextureCustomReceiverPass = 0;
4254        }
4255        else
4256        {
4257                MaterialPtr mat = MaterialManager::getSingleton().getByName(name);
4258                if (mat.isNull())
4259                {
4260                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
4261                                "Cannot locate material called '" + name + "'",
4262                                "SceneManager::setShadowTextureReceiverMaterial");
4263                }
4264                mat->load();
4265                mShadowTextureCustomReceiverPass = mat->getBestTechnique()->getPass(0);
4266                if (mShadowTextureCustomReceiverPass->hasVertexProgram())
4267                {
4268                        // Save vertex program and params in case we have to swap them out
4269                        mShadowTextureCustomReceiverVertexProgram =
4270                                mShadowTextureCustomReceiverPass->getVertexProgramName();
4271                        mShadowTextureCustomReceiverVPParams =
4272                                mShadowTextureCustomReceiverPass->getVertexProgramParameters();
4273                        mShadowTextureReceiverVPDirty = false;
4274
4275                }
4276        }
4277}
4278//---------------------------------------------------------------------
4279void SceneManager::createShadowTextures(unsigned short size,
4280        unsigned short count, PixelFormat fmt)
4281{
4282    static const String baseName = "Ogre/ShadowTexture";
4283
4284    if (!isShadowTechniqueTextureBased() ||
4285        !mShadowTextures.empty() &&
4286        count == mShadowTextureCount &&
4287        size == mShadowTextureSize &&
4288                fmt == mShadowTextureFormat)
4289    {
4290        // no change
4291        return;
4292    }
4293
4294
4295    // destroy existing
4296        destroyShadowTextures();
4297
4298    // Recreate shadow textures
4299    for (unsigned short t = 0; t < count; ++t)
4300    {
4301        String targName = baseName + StringConverter::toString(t);
4302        String camName = baseName + "Cam" + StringConverter::toString(t);
4303        String matName = baseName + "Mat" + StringConverter::toString(t);
4304
4305                // try to get existing texture first, since we share these between
4306                // potentially multiple SMs
4307                TexturePtr shadowTex = TextureManager::getSingleton().getByName(targName);
4308                if (shadowTex.isNull())
4309                {
4310                        shadowTex = TextureManager::getSingleton().createManual(
4311                                targName,
4312                                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
4313                                TEX_TYPE_2D, size, size, 0, mShadowTextureFormat,
4314                                TU_RENDERTARGET);
4315                }
4316                else if (shadowTex->getWidth() != size
4317                        || shadowTex->getHeight() != size
4318                        || shadowTex->getFormat() != mShadowTextureFormat)
4319                {
4320                        StringUtil::StrStreamType s;
4321                        s << "Warning: shadow texture #" << t << " is shared "
4322                                << "between scene managers but the sizes / formats "
4323                                << "do not agree. Consider rationalising your scene manager "
4324                                << "shadow texture settings.";
4325                        LogManager::getSingleton().logMessage(s.str());
4326                }
4327                               
4328                // Ensure texture loaded
4329                shadowTex->load();
4330
4331                RenderTexture *shadowRTT = shadowTex->getBuffer()->getRenderTarget();
4332
4333                // Create camera for this texture, but note that we have to rebind
4334                // in prepareShadowTextures to coexist with multiple SMs
4335                Camera* cam = createCamera(camName);
4336        cam->setAspectRatio(1.0f);
4337                // Don't use rendering distance for light cameras; we don't want shadows
4338                // for visible objects disappearing, especially for directional lights
4339                cam->setUseRenderingDistance(false);
4340                mShadowTextureCameras.push_back(cam);
4341               
4342        // Create a viewport, if not there already
4343                if (shadowRTT->getNumViewports() == 0)
4344                {
4345                        // Note camera assignment is transient when multiple SMs
4346                        Viewport *v = shadowRTT->addViewport(cam);
4347                        v->setClearEveryFrame(true);
4348                        // remove overlays
4349                        v->setOverlaysEnabled(false);
4350                }
4351               
4352        // Don't update automatically - we'll do it when required
4353        shadowRTT->setAutoUpdated(false);
4354       
4355        mShadowTextures.push_back(shadowTex);
4356
4357
4358        // Also create corresponding Material used for rendering this shadow
4359        MaterialPtr mat = MaterialManager::getSingleton().getByName(matName);
4360        if (mat.isNull())
4361        {
4362            mat = MaterialManager::getSingleton().create(
4363                matName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
4364        }
4365        else
4366        {
4367            mat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
4368        }
4369        // create texture unit referring to render target texture
4370        TextureUnitState* texUnit =
4371            mat->getTechnique(0)->getPass(0)->createTextureUnitState(targName);
4372        // set projective based on camera
4373        texUnit->setProjectiveTexturing(true, cam);
4374        texUnit->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
4375        mat->touch();
4376
4377    }
4378}
4379//---------------------------------------------------------------------
4380void SceneManager::destroyShadowTextures(void)
4381{
4382    ShadowTextureList::iterator i, iend;
4383    ShadowTextureCameraList::iterator ci;
4384    iend = mShadowTextures.end();
4385    ci = mShadowTextureCameras.begin();
4386    for (i = mShadowTextures.begin(); i != iend; ++i, ++ci)
4387    {
4388        TexturePtr &shadowTex = *i;
4389                // If the reference count on this texture is 1 over the resource system
4390                // overhead, then we can remove the texture
4391                if (shadowTex.useCount() ==
4392                        ResourceGroupManager::RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS + 1)
4393                {
4394                // destroy texture
4395            TextureManager::getSingleton().remove(shadowTex->getName());
4396                }
4397
4398                // Always destroy camera since they are local to this SM
4399                destroyCamera(*ci);
4400    }
4401    mShadowTextures.clear();
4402        mShadowTextureCameras.clear();
4403
4404       
4405}
4406//---------------------------------------------------------------------
4407void SceneManager::prepareShadowTextures(Camera* cam, Viewport* vp)
4408{
4409    // Set the illumination stage, prevents recursive calls
4410    IlluminationRenderStage savedStage = mIlluminationStage;
4411    mIlluminationStage = IRS_RENDER_TO_TEXTURE;
4412
4413    // Determine far shadow distance
4414    Real shadowDist = mShadowFarDist;
4415    if (!shadowDist)
4416    {
4417        // need a shadow distance, make one up
4418        shadowDist = cam->getNearClipDistance() * 300;
4419    }
4420        Real shadowOffset = shadowDist * mShadowTextureOffset;
4421    // Precalculate fading info
4422        Real shadowEnd = shadowDist + shadowOffset;
4423        Real fadeStart = shadowEnd * mShadowTextureFadeStart;
4424        Real fadeEnd = shadowEnd * mShadowTextureFadeEnd;
4425        // set fogging to hide the shadow edge
4426        // Additive lighting needs fading too (directional)
4427        mShadowReceiverPass->setFog(true, FOG_LINEAR, ColourValue::White,
4428                0, fadeStart, fadeEnd);
4429
4430    // Iterate over the lights we've found, max out at the limit of light textures
4431
4432    LightList::iterator i, iend;
4433    ShadowTextureList::iterator si, siend;
4434        ShadowTextureCameraList::iterator ci;
4435    iend = mLightsAffectingFrustum.end();
4436    siend = mShadowTextures.end();
4437        ci = mShadowTextureCameras.begin();
4438    for (i = mLightsAffectingFrustum.begin(), si = mShadowTextures.begin();
4439        i != iend && si != siend; ++i)
4440    {
4441        Light* light = *i;
4442
4443        // Skip non-shadowing lights
4444        if (!light->getCastShadows())
4445            continue;
4446
4447                TexturePtr &shadowTex = *si;
4448        RenderTarget *shadowRTT = shadowTex->getBuffer()->getRenderTarget();
4449        Viewport *shadowView = shadowRTT->getViewport(0);
4450        Camera *texCam = *ci;
4451                // rebind camera, incase another SM in use which has switched to its cam
4452                shadowView->setCamera(texCam);
4453       
4454        Vector3 pos, dir;
4455
4456        // Directional lights
4457        if (light->getType() == Light::LT_DIRECTIONAL)
4458        {
4459            // set up the shadow texture
4460            // Set ortho projection
4461            texCam->setProjectionType(PT_ORTHOGRAPHIC);
4462            // set easy FOV and near dist so that texture covers far dist
4463            texCam->setFOVy(Degree(90));
4464            texCam->setNearClipDistance(shadowDist);
4465
4466            // Calculate look at position
4467            // We want to look at a spot shadowOffset away from near plane
4468            // 0.5 is a litle too close for angles
4469            Vector3 target = cam->getDerivedPosition() +
4470                (cam->getDerivedDirection() * shadowOffset);
4471
4472            // Calculate direction, which same as directional light direction
4473            dir = - light->getDerivedDirection(); // backwards since point down -z
4474            dir.normalise();
4475
4476            // Calculate position
4477            // We want to be in the -ve direction of the light direction
4478            // far enough to project for the dir light extrusion distance
4479            pos = target + dir * mShadowDirLightExtrudeDist;
4480
4481            // Round local x/y position based on a world-space texel; this helps to reduce
4482            // jittering caused by the projection moving with the camera
4483            // Viewport is 2 * near clip distance across (90 degree fov)
4484            Real worldTexelSize = (texCam->getNearClipDistance() * 20) / mShadowTextureSize;
4485            pos.x -= fmod(pos.x, worldTexelSize);
4486            pos.y -= fmod(pos.y, worldTexelSize);
4487            pos.z -= fmod(pos.z, worldTexelSize);
4488        }
4489        // Spotlight
4490        else if (light->getType() == Light::LT_SPOTLIGHT)
4491        {
4492            // Set perspective projection
4493            texCam->setProjectionType(PT_PERSPECTIVE);
4494            // set FOV slightly larger than the spotlight range to ensure coverage
4495            texCam->setFOVy(light->getSpotlightOuterAngle()*1.2);
4496            // set near clip the same as main camera, since they are likely
4497            // to both reflect the nature of the scene
4498            texCam->setNearClipDistance(cam->getNearClipDistance());
4499
4500            // Calculate position, which same as spotlight position
4501            pos = light->getDerivedPosition();
4502
4503            // Calculate direction, which same as spotlight direction
4504            dir = - light->getDerivedDirection(); // backwards since point down -z
4505            dir.normalise();
4506        }
4507        // Point light
4508        else
4509        {
4510            // Set perspective projection
4511            texCam->setProjectionType(PT_PERSPECTIVE);
4512            // Use 120 degree FOV for point light to ensure coverage more area
4513            texCam->setFOVy(Degree(120));
4514            // set near clip the same as main camera, since they are likely
4515            // to both reflect the nature of the scene
4516            texCam->setNearClipDistance(cam->getNearClipDistance());
4517
4518            // Calculate look at position
4519            // We want to look at a spot shadowOffset away from near plane
4520            // 0.5 is a litle too close for angles
4521            Vector3 target = cam->getDerivedPosition() +
4522                (cam->getDerivedDirection() * shadowOffset);
4523
4524            // Calculate position, which same as point light position
4525            pos = light->getDerivedPosition();
4526
4527            dir = (pos - target); // backwards since point down -z
4528            dir.normalise();
4529        }
4530
4531        // Finally set position
4532        texCam->setPosition(pos);
4533
4534        // Calculate orientation based on direction calculated above
4535        /*
4536        // Next section (camera oriented shadow map) abandoned
4537        // Always point in the same direction, if we don't do this then
4538        // we get 'shadow swimming' as camera rotates
4539        // As it is, we get swimming on moving but this is less noticeable
4540
4541        // calculate up vector, we want it aligned with cam direction
4542        Vector3 up = cam->getDerivedDirection();
4543        // Check it's not coincident with dir
4544        if (up.dotProduct(dir) >= 1.0f)
4545        {
4546        // Use camera up
4547        up = cam->getUp();
4548        }
4549        */
4550        Vector3 up = Vector3::UNIT_Y;
4551        // Check it's not coincident with dir
4552        if (Math::Abs(up.dotProduct(dir)) >= 1.0f)
4553        {
4554            // Use camera up
4555            up = Vector3::UNIT_Z;
4556        }
4557        // cross twice to rederive, only direction is unaltered
4558        Vector3 left = dir.crossProduct(up);
4559        left.normalise();
4560        up = dir.crossProduct(left);
4561        up.normalise();
4562        // Derive quaternion from axes
4563        Quaternion q;
4564        q.FromAxes(left, up, dir);
4565        texCam->setOrientation(q);
4566
4567        // Setup background colour
4568        shadowView->setBackgroundColour(ColourValue::White);
4569
4570                // Fire shadow caster update, callee can alter camera settings
4571                fireShadowTexturesPreCaster(light, texCam);
4572
4573        // Update target
4574        shadowRTT->update();
4575
4576        ++si; // next shadow texture
4577                ++ci; // next camera
4578    }
4579    // Set the illumination stage, prevents recursive calls
4580    mIlluminationStage = savedStage;
4581
4582        fireShadowTexturesUpdated(
4583                std::min(mLightsAffectingFrustum.size(), mShadowTextures.size()));
4584}
4585//---------------------------------------------------------------------
4586StaticGeometry* SceneManager::createStaticGeometry(const String& name)
4587{
4588        // Check not existing
4589        if (mStaticGeometryList.find(name) != mStaticGeometryList.end())
4590        {
4591                OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
4592                        "StaticGeometry with name '" + name + "' already exists!",
4593                        "SceneManager::createStaticGeometry");
4594        }
4595        StaticGeometry* ret = new StaticGeometry(this, name);
4596        mStaticGeometryList[name] = ret;
4597        return ret;
4598}
4599//---------------------------------------------------------------------
4600StaticGeometry* SceneManager::getStaticGeometry(const String& name) const
4601{
4602        StaticGeometryList::const_iterator i = mStaticGeometryList.find(name);
4603        if (i == mStaticGeometryList.end())
4604        {
4605                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
4606                        "StaticGeometry with name '" + name + "' not found",
4607                        "SceneManager::createStaticGeometry");
4608        }
4609        return i->second;
4610}
4611//---------------------------------------------------------------------
4612void SceneManager::destroyStaticGeometry(StaticGeometry* geom)
4613{
4614        destroyStaticGeometry(geom->getName());
4615}
4616//---------------------------------------------------------------------
4617void SceneManager::destroyStaticGeometry(const String& name)
4618{
4619        StaticGeometryList::iterator i = mStaticGeometryList.find(name);
4620        if (i != mStaticGeometryList.end())
4621        {
4622                delete i->second;
4623                mStaticGeometryList.erase(i);
4624        }
4625
4626}
4627//---------------------------------------------------------------------
4628void SceneManager::destroyAllStaticGeometry(void)
4629{
4630        StaticGeometryList::iterator i, iend;
4631        iend = mStaticGeometryList.end();
4632        for (i = mStaticGeometryList.begin(); i != iend; ++i)
4633        {
4634                delete i->second;
4635        }
4636        mStaticGeometryList.clear();
4637}
4638//---------------------------------------------------------------------
4639AxisAlignedBoxSceneQuery*
4640SceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
4641{
4642    DefaultAxisAlignedBoxSceneQuery* q = new DefaultAxisAlignedBoxSceneQuery(this);
4643    q->setBox(box);
4644    q->setQueryMask(mask);
4645    return q;
4646}
4647//---------------------------------------------------------------------
4648SphereSceneQuery*
4649SceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
4650{
4651    DefaultSphereSceneQuery* q = new DefaultSphereSceneQuery(this);
4652    q->setSphere(sphere);
4653    q->setQueryMask(mask);
4654    return q;
4655}
4656//---------------------------------------------------------------------
4657PlaneBoundedVolumeListSceneQuery*
4658SceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
4659                                            unsigned long mask)
4660{
4661    DefaultPlaneBoundedVolumeListSceneQuery* q = new DefaultPlaneBoundedVolumeListSceneQuery(this);
4662    q->setVolumes(volumes);
4663    q->setQueryMask(mask);
4664    return q;
4665}
4666
4667//---------------------------------------------------------------------
4668RaySceneQuery*
4669SceneManager::createRayQuery(const Ray& ray, unsigned long mask)
4670{
4671    DefaultRaySceneQuery* q = new DefaultRaySceneQuery(this);
4672    q->setRay(ray);
4673    q->setQueryMask(mask);
4674    return q;
4675}
4676//---------------------------------------------------------------------
4677IntersectionSceneQuery*
4678SceneManager::createIntersectionQuery(unsigned long mask)
4679{
4680
4681    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
4682    q->setQueryMask(mask);
4683    return q;
4684}
4685//---------------------------------------------------------------------
4686void SceneManager::destroyQuery(SceneQuery* query)
4687{
4688    delete query;
4689}
4690//---------------------------------------------------------------------
4691SceneManager::MovableObjectMap*
4692SceneManager::getMovableObjectMap(const String& typeName)
4693{
4694        MovableObjectCollectionMap::iterator i =
4695                mMovableObjectCollectionMap.find(typeName);
4696        if (i == mMovableObjectCollectionMap.end())
4697        {
4698                // create
4699                MovableObjectMap* newMap = new MovableObjectMap();
4700                mMovableObjectCollectionMap[typeName] = newMap;
4701                return newMap;
4702        }
4703        else
4704        {
4705                return i->second;
4706        }
4707}
4708//---------------------------------------------------------------------
4709MovableObject* SceneManager::createMovableObject(const String& name,
4710        const String& typeName, const NameValuePairList* params)
4711{
4712        MovableObjectFactory* factory =
4713                Root::getSingleton().getMovableObjectFactory(typeName);
4714        // Check for duplicate names
4715        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4716
4717        if (objectMap->find(name) != objectMap->end())
4718        {
4719                OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
4720                        "An object of type '" + typeName + "' with name '" + name
4721                        + "' already exists.",
4722                        "SceneManager::createMovableObject");
4723        }
4724
4725        MovableObject* newObj = factory->createInstance(name, this, params);
4726        (*objectMap)[name] = newObj;
4727
4728        return newObj;
4729
4730}
4731//---------------------------------------------------------------------
4732void SceneManager::destroyMovableObject(const String& name, const String& typeName)
4733{
4734        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4735        MovableObjectFactory* factory =
4736                Root::getSingleton().getMovableObjectFactory(typeName);
4737
4738        MovableObjectMap::iterator mi = objectMap->find(name);
4739        if (mi != objectMap->end())
4740        {
4741                factory->destroyInstance(mi->second);
4742                objectMap->erase(mi);
4743        }
4744
4745}
4746//---------------------------------------------------------------------
4747void SceneManager::destroyAllMovableObjectsByType(const String& typeName)
4748{
4749        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4750        MovableObjectFactory* factory =
4751                Root::getSingleton().getMovableObjectFactory(typeName);
4752        MovableObjectMap::iterator i = objectMap->begin();
4753        for (; i != objectMap->end(); ++i)
4754        {
4755                // Only destroy our own
4756                if (i->second->_getManager() == this)
4757                {
4758                        factory->destroyInstance(i->second);
4759                }
4760        }
4761        objectMap->clear();
4762
4763}
4764//---------------------------------------------------------------------
4765void SceneManager::destroyAllMovableObjects(void)
4766{
4767        MovableObjectCollectionMap::iterator ci = mMovableObjectCollectionMap.begin();
4768
4769        for(;ci != mMovableObjectCollectionMap.end(); ++ci)
4770        {
4771                if (Root::getSingleton().hasMovableObjectFactory(ci->first))
4772                {
4773                        // Only destroy if we have a factory instance; otherwise must be injected
4774                        MovableObjectFactory* factory =
4775                                Root::getSingleton().getMovableObjectFactory(ci->first);
4776                        MovableObjectMap::iterator i = ci->second->begin();
4777                        for (; i != ci->second->end(); ++i)
4778                        {
4779                                if (i->second->_getManager() == this)
4780                                {
4781                                        factory->destroyInstance(i->second);
4782                                }
4783                        }
4784                }
4785                ci->second->clear();
4786        }
4787
4788}
4789//---------------------------------------------------------------------
4790MovableObject* SceneManager::getMovableObject(const String& name, const String& typeName)
4791{
4792       
4793        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4794        MovableObjectMap::iterator mi = objectMap->find(name);
4795        if (mi == objectMap->end())
4796        {
4797                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
4798                        "Object named '" + name + "' does not exist.",
4799                        "SceneManager::getMovableObject");
4800        }
4801        return mi->second;
4802       
4803}
4804//---------------------------------------------------------------------
4805SceneManager::MovableObjectIterator
4806SceneManager::getMovableObjectIterator(const String& typeName)
4807{
4808        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4809
4810        return MovableObjectIterator(objectMap->begin(), objectMap->end());
4811}
4812//---------------------------------------------------------------------
4813void SceneManager::destroyMovableObject(MovableObject* m)
4814{
4815        destroyMovableObject(m->getName(), m->getMovableType());
4816}
4817//---------------------------------------------------------------------
4818void SceneManager::injectMovableObject(MovableObject* m)
4819{
4820        MovableObjectMap* objectMap = getMovableObjectMap(m->getMovableType());
4821        (*objectMap)[m->getName()] = m;
4822}
4823//---------------------------------------------------------------------
4824void SceneManager::extractMovableObject(const String& name, const String& typeName)
4825{
4826        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4827        MovableObjectMap::iterator mi = objectMap->find(name);
4828        if (mi != objectMap->end())
4829        {
4830                // no delete
4831                objectMap->erase(mi);
4832        }
4833
4834}
4835//---------------------------------------------------------------------
4836void SceneManager::extractMovableObject(MovableObject* m)
4837{
4838        extractMovableObject(m->getName(), m->getMovableType());
4839}
4840//---------------------------------------------------------------------
4841void SceneManager::extractAllMovableObjectsByType(const String& typeName)
4842{
4843        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4844        // no deletion
4845        objectMap->clear();
4846
4847}
4848//---------------------------------------------------------------------
4849void SceneManager::_injectRenderWithPass(Pass *pass, Renderable *rend)
4850{
4851        // render something as if it came from the current queue
4852    const Pass *usedPass = _setPass(pass);
4853    renderSingleObject(rend, usedPass, false);
4854}
4855//---------------------------------------------------------------------
4856RenderSystem *SceneManager::getDestinationRenderSystem()
4857{
4858        return mDestRenderSystem;
4859}
4860
4861}
Note: See TracBrowser for help on using the repository browser.