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

Revision 948, 169.7 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
1057    if (mFindVisibleObjects)
1058    {
1059        // Parse the scene and tag visibles
1060        _findVisibleObjects(camera,
1061            mIlluminationStage == IRS_RENDER_TO_TEXTURE? true : false);
1062    }
1063    // Add overlays, if viewport deems it
1064    if (vp->getOverlaysEnabled() && mIlluminationStage != IRS_RENDER_TO_TEXTURE)
1065    {
1066        OverlayManager::getSingleton()._queueOverlaysForRendering(camera, getRenderQueue(), vp);
1067    }
1068    // Queue skies, if viewport seems it
1069    if (vp->getSkiesEnabled() && mFindVisibleObjects && mIlluminationStage != IRS_RENDER_TO_TEXTURE)
1070    {
1071        _queueSkiesForRendering(camera);
1072    }
1073
1074
1075    mDestRenderSystem->_beginGeometryCount();
1076    // Begin the frame
1077    mDestRenderSystem->_beginFrame();
1078
1079    // Set rasterisation mode
1080    mDestRenderSystem->_setPolygonMode(camera->getPolygonMode());
1081
1082        // Set initial camera state
1083        mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrixRS());
1084        mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix(true));
1085
1086    // Render scene content
1087    _renderVisibleObjects();
1088
1089    // End frame
1090    mDestRenderSystem->_endFrame();
1091
1092    // Notify camera or vis faces
1093    camera->_notifyRenderedFaces(mDestRenderSystem->_getFaceCount());
1094
1095
1096
1097}
1098
1099
1100//-----------------------------------------------------------------------
1101void SceneManager::_setDestinationRenderSystem(RenderSystem* sys)
1102{
1103    mDestRenderSystem = sys;
1104
1105}
1106
1107
1108//-----------------------------------------------------------------------
1109void SceneManager::setWorldGeometry(const String& filename)
1110{
1111    // This default implementation cannot handle world geometry
1112    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1113        "World geometry is not supported by the generic SceneManager.",
1114        "SceneManager::setWorldGeometry");
1115}
1116//-----------------------------------------------------------------------
1117void SceneManager::setWorldGeometry(DataStreamPtr& stream,
1118        const String& typeName)
1119{
1120    // This default implementation cannot handle world geometry
1121    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1122        "World geometry is not supported by the generic SceneManager.",
1123        "SceneManager::setWorldGeometry");
1124}
1125
1126//-----------------------------------------------------------------------
1127bool SceneManager::materialLess::operator() (const Material* x, const Material* y) const
1128{
1129    // If x transparent and y not, x > y (since x has to overlap y)
1130    if (x->isTransparent() && !y->isTransparent())
1131    {
1132        return false;
1133    }
1134    // If y is transparent and x not, x < y
1135    else if (!x->isTransparent() && y->isTransparent())
1136    {
1137        return true;
1138    }
1139    else
1140    {
1141        // Otherwise don't care (both transparent or both solid)
1142        // Just arbitrarily use pointer
1143        return x < y;
1144    }
1145
1146}
1147
1148//-----------------------------------------------------------------------
1149void SceneManager::setSkyPlane(
1150                               bool enable,
1151                               const Plane& plane,
1152                               const String& materialName,
1153                               Real gscale,
1154                               Real tiling,
1155                               bool drawFirst,
1156                               Real bow,
1157                               int xsegments, int ysegments,
1158                               const String& groupName)
1159{
1160    if (enable)
1161    {
1162        String meshName = mName + "SkyPlane";
1163        mSkyPlane = plane;
1164
1165        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
1166        if (m.isNull())
1167        {
1168            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1169                "Sky plane material '" + materialName + "' not found.",
1170                "SceneManager::setSkyPlane");
1171        }
1172        // Make sure the material doesn't update the depth buffer
1173        m->setDepthWriteEnabled(false);
1174        // Ensure loaded
1175        m->load();
1176
1177        mSkyPlaneDrawFirst = drawFirst;
1178
1179        // Set up the plane
1180        MeshPtr planeMesh = MeshManager::getSingleton().getByName(meshName);
1181        if (!planeMesh.isNull())
1182        {
1183            // Destroy the old one
1184            MeshManager::getSingleton().remove(planeMesh->getHandle());
1185        }
1186
1187        // Create up vector
1188        Vector3 up = plane.normal.crossProduct(Vector3::UNIT_X);
1189        if (up == Vector3::ZERO)
1190            up = plane.normal.crossProduct(-Vector3::UNIT_Z);
1191
1192        // Create skyplane
1193        if( bow > 0 )
1194        {
1195            // Build a curved skyplane
1196            planeMesh = MeshManager::getSingleton().createCurvedPlane(
1197                meshName, groupName, plane, gscale * 100, gscale * 100, gscale * bow * 100,
1198                xsegments, ysegments, false, 1, tiling, tiling, up);
1199        }
1200        else
1201        {
1202            planeMesh = MeshManager::getSingleton().createPlane(
1203                meshName, groupName, plane, gscale * 100, gscale * 100, xsegments, ysegments, false,
1204                1, tiling, tiling, up);
1205        }
1206
1207        // Create entity
1208        if (mSkyPlaneEntity)
1209        {
1210            // destroy old one, do it by name for speed
1211            destroyEntity(meshName);
1212        }
1213        // Create, use the same name for mesh and entity
1214        mSkyPlaneEntity = createEntity(meshName, meshName);
1215        mSkyPlaneEntity->setMaterialName(materialName);
1216        mSkyPlaneEntity->setCastShadows(false);
1217
1218        // Create node and attach
1219        if (!mSkyPlaneNode)
1220        {
1221            mSkyPlaneNode = createSceneNode(meshName + "Node");
1222        }
1223        else
1224        {
1225            mSkyPlaneNode->detachAllObjects();
1226        }
1227        mSkyPlaneNode->attachObject(mSkyPlaneEntity);
1228
1229    }
1230        mSkyPlaneEnabled = enable;
1231        mSkyPlaneGenParameters.skyPlaneBow = bow;
1232        mSkyPlaneGenParameters.skyPlaneScale = gscale;
1233        mSkyPlaneGenParameters.skyPlaneTiling = tiling;
1234        mSkyPlaneGenParameters.skyPlaneXSegments = xsegments;
1235        mSkyPlaneGenParameters.skyPlaneYSegments = ysegments;
1236}
1237//-----------------------------------------------------------------------
1238void SceneManager::setSkyBox(
1239                             bool enable,
1240                             const String& materialName,
1241                             Real distance,
1242                             bool drawFirst,
1243                             const Quaternion& orientation,
1244                             const String& groupName)
1245{
1246    if (enable)
1247    {
1248        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
1249        if (m.isNull())
1250        {
1251            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1252                "Sky box material '" + materialName + "' not found.",
1253                "SceneManager::setSkyBox");
1254        }
1255        // Make sure the material doesn't update the depth buffer
1256        m->setDepthWriteEnabled(false);
1257        // Ensure loaded
1258        m->load();
1259        // Also clamp texture, don't wrap (otherwise edges can get filtered)
1260        m->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
1261
1262
1263        mSkyBoxDrawFirst = drawFirst;
1264
1265        // Create node
1266        if (!mSkyBoxNode)
1267        {
1268            mSkyBoxNode = createSceneNode("SkyBoxNode");
1269        }
1270        else
1271        {
1272            mSkyBoxNode->detachAllObjects();
1273        }
1274
1275        MaterialManager& matMgr = MaterialManager::getSingleton();
1276        // Set up the box (6 planes)
1277        for (int i = 0; i < 6; ++i)
1278        {
1279            MeshPtr planeMesh = createSkyboxPlane((BoxPlane)i, distance, orientation, groupName);
1280            String entName = mName + "SkyBoxPlane" + StringConverter::toString(i);
1281
1282            // Create entity
1283            if (mSkyBoxEntity[i])
1284            {
1285                // destroy old one, do it by name for speed
1286                destroyEntity(entName);
1287            }
1288            mSkyBoxEntity[i] = createEntity(entName, planeMesh->getName());
1289            mSkyBoxEntity[i]->setCastShadows(false);
1290            // Have to create 6 materials, one for each frame
1291            // Used to use combined material but now we're using queue we can't split to change frame
1292            // This doesn't use much memory because textures aren't duplicated
1293            MaterialPtr boxMat = matMgr.getByName(entName);
1294            if (boxMat.isNull())
1295            {
1296                // Create new by clone
1297                boxMat = m->clone(entName);
1298                boxMat->load();
1299            }
1300            else
1301            {
1302                // Copy over existing
1303                m->copyDetailsTo(boxMat);
1304                boxMat->load();
1305            }
1306            // Set active frame
1307                        Material::TechniqueIterator ti = boxMat->getSupportedTechniqueIterator();
1308                        while (ti.hasMoreElements())
1309                        {
1310                                Technique* tech = ti.getNext();
1311                                tech->getPass(0)->getTextureUnitState(0)->setCurrentFrame(i);
1312                        }
1313
1314            mSkyBoxEntity[i]->setMaterialName(boxMat->getName());
1315
1316            // Attach to node
1317            mSkyBoxNode->attachObject(mSkyBoxEntity[i]);
1318        } // for each plane
1319
1320    }
1321        mSkyBoxEnabled = enable;
1322        mSkyBoxGenParameters.skyBoxDistance = distance;
1323}
1324//-----------------------------------------------------------------------
1325void SceneManager::setSkyDome(
1326                              bool enable,
1327                              const String& materialName,
1328                              Real curvature,
1329                              Real tiling,
1330                              Real distance,
1331                              bool drawFirst,
1332                              const Quaternion& orientation,
1333                              int xsegments, int ysegments, int ySegmentsToKeep,
1334                              const String& groupName)
1335{
1336    if (enable)
1337    {
1338        MaterialPtr m = MaterialManager::getSingleton().getByName(materialName);
1339        if (m.isNull())
1340        {
1341            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1342                "Sky dome material '" + materialName + "' not found.",
1343                "SceneManager::setSkyDome");
1344        }
1345        // Make sure the material doesn't update the depth buffer
1346        m->setDepthWriteEnabled(false);
1347        // Ensure loaded
1348        m->load();
1349
1350        mSkyDomeDrawFirst = drawFirst;
1351
1352        // Create node
1353        if (!mSkyDomeNode)
1354        {
1355            mSkyDomeNode = createSceneNode("SkyDomeNode");
1356        }
1357        else
1358        {
1359            mSkyDomeNode->detachAllObjects();
1360        }
1361
1362        // Set up the dome (5 planes)
1363        for (int i = 0; i < 5; ++i)
1364        {
1365            MeshPtr planeMesh = createSkydomePlane((BoxPlane)i, curvature,
1366                tiling, distance, orientation, xsegments, ysegments,
1367                i!=BP_UP ? ySegmentsToKeep : -1, groupName);
1368
1369            String entName = "SkyDomePlane" + StringConverter::toString(i);
1370
1371            // Create entity
1372            if (mSkyDomeEntity[i])
1373            {
1374                // destroy old one, do it by name for speed
1375                destroyEntity(entName);
1376            }
1377            mSkyDomeEntity[i] = createEntity(entName, planeMesh->getName());
1378            mSkyDomeEntity[i]->setMaterialName(m->getName());
1379            mSkyDomeEntity[i]->setCastShadows(false);
1380
1381            // Attach to node
1382            mSkyDomeNode->attachObject(mSkyDomeEntity[i]);
1383        } // for each plane
1384
1385    }
1386        mSkyDomeEnabled = enable;
1387        mSkyDomeGenParameters.skyDomeCurvature = curvature;
1388        mSkyDomeGenParameters.skyDomeDistance = distance;
1389        mSkyDomeGenParameters.skyDomeTiling = tiling;
1390        mSkyDomeGenParameters.skyDomeXSegments = xsegments;
1391        mSkyDomeGenParameters.skyDomeYSegments = ysegments;
1392        mSkyDomeGenParameters.skyDomeYSegments_keep = ySegmentsToKeep;
1393}
1394//-----------------------------------------------------------------------
1395MeshPtr SceneManager::createSkyboxPlane(
1396                                      BoxPlane bp,
1397                                      Real distance,
1398                                      const Quaternion& orientation,
1399                                      const String& groupName)
1400{
1401    Plane plane;
1402    String meshName;
1403    Vector3 up;
1404
1405    meshName = mName + "SkyBoxPlane_";
1406    // Set up plane equation
1407    plane.d = distance;
1408    switch(bp)
1409    {
1410    case BP_FRONT:
1411        plane.normal = Vector3::UNIT_Z;
1412        up = Vector3::UNIT_Y;
1413        meshName += "Front";
1414        break;
1415    case BP_BACK:
1416        plane.normal = -Vector3::UNIT_Z;
1417        up = Vector3::UNIT_Y;
1418        meshName += "Back";
1419        break;
1420    case BP_LEFT:
1421        plane.normal = Vector3::UNIT_X;
1422        up = Vector3::UNIT_Y;
1423        meshName += "Left";
1424        break;
1425    case BP_RIGHT:
1426        plane.normal = -Vector3::UNIT_X;
1427        up = Vector3::UNIT_Y;
1428        meshName += "Right";
1429        break;
1430    case BP_UP:
1431        plane.normal = -Vector3::UNIT_Y;
1432        up = Vector3::UNIT_Z;
1433        meshName += "Up";
1434        break;
1435    case BP_DOWN:
1436        plane.normal = Vector3::UNIT_Y;
1437        up = -Vector3::UNIT_Z;
1438        meshName += "Down";
1439        break;
1440    }
1441    // Modify by orientation
1442    plane.normal = orientation * plane.normal;
1443    up = orientation * up;
1444
1445
1446    // Check to see if existing plane
1447    MeshManager& mm = MeshManager::getSingleton();
1448    MeshPtr planeMesh = mm.getByName(meshName);
1449    if(!planeMesh.isNull())
1450    {
1451        // destroy existing
1452        mm.remove(planeMesh->getHandle());
1453    }
1454    // Create new
1455    Real planeSize = distance * 2;
1456    const int BOX_SEGMENTS = 1;
1457    planeMesh = mm.createPlane(meshName, groupName, plane, planeSize, planeSize,
1458        BOX_SEGMENTS, BOX_SEGMENTS, false, 1, 1, 1, up);
1459
1460    //planeMesh->_dumpContents(meshName);
1461
1462    return planeMesh;
1463
1464}
1465//-----------------------------------------------------------------------
1466MeshPtr SceneManager::createSkydomePlane(
1467                                       BoxPlane bp,
1468                                       Real curvature,
1469                                       Real tiling,
1470                                       Real distance,
1471                                       const Quaternion& orientation,
1472                                       int xsegments, int ysegments, int ysegments_keep,
1473                                       const String& groupName)
1474{
1475
1476    Plane plane;
1477    String meshName;
1478    Vector3 up;
1479
1480    meshName = mName + "SkyDomePlane_";
1481    // Set up plane equation
1482    plane.d = distance;
1483    switch(bp)
1484    {
1485    case BP_FRONT:
1486        plane.normal = Vector3::UNIT_Z;
1487        up = Vector3::UNIT_Y;
1488        meshName += "Front";
1489        break;
1490    case BP_BACK:
1491        plane.normal = -Vector3::UNIT_Z;
1492        up = Vector3::UNIT_Y;
1493        meshName += "Back";
1494        break;
1495    case BP_LEFT:
1496        plane.normal = Vector3::UNIT_X;
1497        up = Vector3::UNIT_Y;
1498        meshName += "Left";
1499        break;
1500    case BP_RIGHT:
1501        plane.normal = -Vector3::UNIT_X;
1502        up = Vector3::UNIT_Y;
1503        meshName += "Right";
1504        break;
1505    case BP_UP:
1506        plane.normal = -Vector3::UNIT_Y;
1507        up = Vector3::UNIT_Z;
1508        meshName += "Up";
1509        break;
1510    case BP_DOWN:
1511        // no down
1512        return MeshPtr();
1513    }
1514    // Modify by orientation
1515    plane.normal = orientation * plane.normal;
1516    up = orientation * up;
1517
1518    // Check to see if existing plane
1519    MeshManager& mm = MeshManager::getSingleton();
1520    MeshPtr planeMesh = mm.getByName(meshName);
1521    if(!planeMesh.isNull())
1522    {
1523        // destroy existing
1524        mm.remove(planeMesh->getHandle());
1525    }
1526    // Create new
1527    Real planeSize = distance * 2;
1528    planeMesh = mm.createCurvedIllusionPlane(meshName, groupName, plane,
1529        planeSize, planeSize, curvature,
1530        xsegments, ysegments, false, 1, tiling, tiling, up,
1531        orientation, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, HardwareBuffer::HBU_STATIC_WRITE_ONLY,
1532        false, false, ysegments_keep);
1533
1534    //planeMesh->_dumpContents(meshName);
1535
1536    return planeMesh;
1537
1538}
1539
1540
1541//-----------------------------------------------------------------------
1542void SceneManager::_updateSceneGraph(Camera* cam)
1543{
1544        // Process queued needUpdate calls
1545        Node::processQueuedUpdates();
1546
1547    // Cascade down the graph updating transforms & world bounds
1548    // In this implementation, just update from the root
1549    // Smarter SceneManager subclasses may choose to update only
1550    //   certain scene graph branches
1551    mSceneRoot->_update(true, false);
1552
1553
1554}
1555//-----------------------------------------------------------------------
1556void SceneManager::_findVisibleObjects(Camera* cam, bool onlyShadowCasters)
1557{
1558    // Tell nodes to find, cascade down all nodes
1559    mSceneRoot->_findVisibleObjects(cam, getRenderQueue(), true,
1560        mDisplayNodes, onlyShadowCasters);
1561
1562}
1563//-----------------------------------------------------------------------
1564void SceneManager::_renderVisibleObjects(void)
1565{
1566        RenderQueueInvocationSequence* invocationSequence =
1567                mCurrentViewport->_getRenderQueueInvocationSequence();
1568        // Use custom sequence only if we're not doing the texture shadow render
1569        // since texture shadow render should not be interfered with by suppressing
1570        // render state changes for example
1571        if (invocationSequence && mIlluminationStage != IRS_RENDER_TO_TEXTURE)
1572        {
1573                renderVisibleObjectsCustomSequence(invocationSequence);
1574        }
1575        else
1576        {
1577                renderVisibleObjectsDefaultSequence();
1578        }
1579}
1580//-----------------------------------------------------------------------
1581void SceneManager::renderVisibleObjectsCustomSequence(RenderQueueInvocationSequence* seq)
1582{
1583        RenderQueueInvocationIterator invocationIt = seq->iterator();
1584        while (invocationIt.hasMoreElements())
1585        {
1586                RenderQueueInvocation* invocation = invocationIt.getNext();
1587                uint8 qId = invocation->getRenderQueueGroupID();
1588                // Skip this one if not to be processed
1589                if (!isRenderQueueToBeProcessed(qId))
1590                        continue;
1591
1592
1593                bool repeatQueue = false;
1594                const String& invocationName = invocation->getInvocationName();
1595                RenderQueueGroup* queueGroup = getRenderQueue()->getQueueGroup(qId);
1596                do // for repeating queues
1597                {
1598                        // Fire queue started event
1599                        if (fireRenderQueueStarted(qId, invocationName))
1600                        {
1601                                // Someone requested we skip this queue
1602                                break;
1603                        }
1604
1605                        // Invoke it
1606                        invocation->invoke(queueGroup, this);
1607
1608                        // Fire queue ended event
1609                        if (fireRenderQueueEnded(qId, invocationName))
1610                        {
1611                                // Someone requested we repeat this queue
1612                                repeatQueue = true;
1613                        }
1614                        else
1615                        {
1616                                repeatQueue = false;
1617                        }
1618                } while (repeatQueue);
1619
1620
1621        }
1622}
1623//-----------------------------------------------------------------------
1624void SceneManager::renderVisibleObjectsDefaultSequence(void)
1625{
1626    // Render each separate queue
1627    RenderQueue::QueueGroupIterator queueIt = getRenderQueue()->_getQueueGroupIterator();
1628
1629    // NB only queues which have been created are rendered, no time is wasted
1630    //   parsing through non-existent queues (even though there are 10 available)
1631
1632    while (queueIt.hasMoreElements())
1633    {
1634        // Get queue group id
1635        uint8 qId = queueIt.peekNextKey();
1636                RenderQueueGroup* pGroup = queueIt.getNext();
1637                // Skip this one if not to be processed
1638                if (!isRenderQueueToBeProcessed(qId))
1639                        continue;
1640
1641
1642        bool repeatQueue = false;
1643        do // for repeating queues
1644        {
1645            // Fire queue started event
1646                        if (fireRenderQueueStarted(qId,
1647                                mIlluminationStage == IRS_RENDER_TO_TEXTURE ?
1648                                        RenderQueueInvocation::RENDER_QUEUE_INVOCATION_SHADOWS :
1649                                        StringUtil::BLANK))
1650            {
1651                // Someone requested we skip this queue
1652                break;
1653            }
1654
1655                        _renderQueueGroupObjects(pGroup, QueuedRenderableCollection::OM_PASS_GROUP);
1656
1657            // Fire queue ended event
1658                        if (fireRenderQueueEnded(qId,
1659                                mIlluminationStage == IRS_RENDER_TO_TEXTURE ?
1660                                        RenderQueueInvocation::RENDER_QUEUE_INVOCATION_SHADOWS :
1661                                        StringUtil::BLANK))
1662            {
1663                // Someone requested we repeat this queue
1664                repeatQueue = true;
1665            }
1666            else
1667            {
1668                repeatQueue = false;
1669            }
1670        } while (repeatQueue);
1671
1672    } // for each queue group
1673
1674}
1675//-----------------------------------------------------------------------
1676void SceneManager::renderAdditiveStencilShadowedQueueGroupObjects(
1677        RenderQueueGroup* pGroup,
1678        QueuedRenderableCollection::OrganisationMode om)
1679{
1680    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1681    LightList lightList;
1682
1683    while (groupIt.hasMoreElements())
1684    {
1685        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1686
1687        // Sort the queue first
1688        pPriorityGrp->sort(mCameraInProgress);
1689
1690        // Clear light list
1691        lightList.clear();
1692
1693        // Render all the ambient passes first, no light iteration, no lights
1694        renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
1695        // Also render any objects which have receive shadows disabled
1696        renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1697
1698
1699        // Now iterate per light
1700        // Iterate over lights, render all volumes to stencil
1701        LightList::const_iterator li, liend;
1702        liend = mLightsAffectingFrustum.end();
1703
1704        for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
1705        {
1706            Light* l = *li;
1707            // Set light state
1708
1709            if (l->getCastShadows())
1710            {
1711                // Clear stencil
1712                mDestRenderSystem->clearFrameBuffer(FBT_STENCIL);
1713                renderShadowVolumesToStencil(l, mCameraInProgress);
1714                // turn stencil check on
1715                mDestRenderSystem->setStencilCheckEnabled(true);
1716                // NB we render where the stencil is equal to zero to render lit areas
1717                mDestRenderSystem->setStencilBufferParams(CMPF_EQUAL, 0);
1718            }
1719
1720            // render lighting passes for this light
1721            if (lightList.empty())
1722                lightList.push_back(l);
1723            else
1724                lightList[0] = l;
1725            renderObjects(pPriorityGrp->getSolidsDiffuseSpecular(), om, false, &lightList);
1726
1727            // Reset stencil params
1728            mDestRenderSystem->setStencilBufferParams();
1729            mDestRenderSystem->setStencilCheckEnabled(false);
1730            mDestRenderSystem->_setDepthBufferParams();
1731
1732        }// for each light
1733
1734
1735        // Now render decal passes, no need to set lights as lighting will be disabled
1736        renderObjects(pPriorityGrp->getSolidsDecal(), om, false);
1737
1738
1739    }// for each priority
1740
1741    // Iterate again - variable name changed to appease gcc.
1742    RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
1743    while (groupIt2.hasMoreElements())
1744    {
1745        RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
1746
1747        // Do transparents (always descending sort)
1748        renderObjects(pPriorityGrp->getTransparents(),
1749                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
1750
1751    }// for each priority
1752
1753
1754}
1755//-----------------------------------------------------------------------
1756void SceneManager::renderModulativeStencilShadowedQueueGroupObjects(
1757        RenderQueueGroup* pGroup,
1758        QueuedRenderableCollection::OrganisationMode om)
1759{
1760    /* For each light, we need to render all the solids from each group,
1761    then do the modulative shadows, then render the transparents from
1762    each group.
1763    Now, this means we are going to reorder things more, but that it required
1764    if the shadows are to look correct. The overall order is preserved anyway,
1765    it's just that all the transparents are at the end instead of them being
1766    interleaved as in the normal rendering loop.
1767    */
1768    // Iterate through priorities
1769    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1770
1771    while (groupIt.hasMoreElements())
1772    {
1773        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1774
1775        // Sort the queue first
1776        pPriorityGrp->sort(mCameraInProgress);
1777
1778        // Do (shadowable) solids
1779        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1780    }
1781
1782
1783    // Iterate over lights, render all volumes to stencil
1784    LightList::const_iterator li, liend;
1785    liend = mLightsAffectingFrustum.end();
1786
1787    for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
1788    {
1789        Light* l = *li;
1790        if (l->getCastShadows())
1791        {
1792            // Clear stencil
1793            mDestRenderSystem->clearFrameBuffer(FBT_STENCIL);
1794            renderShadowVolumesToStencil(l, mCameraInProgress);
1795            // render full-screen shadow modulator for all lights
1796            _setPass(mShadowModulativePass);
1797            // turn stencil check on
1798            mDestRenderSystem->setStencilCheckEnabled(true);
1799            // NB we render where the stencil is not equal to zero to render shadows, not lit areas
1800            mDestRenderSystem->setStencilBufferParams(CMPF_NOT_EQUAL, 0);
1801            renderSingleObject(mFullScreenQuad, mShadowModulativePass, false);
1802            // Reset stencil params
1803            mDestRenderSystem->setStencilBufferParams();
1804            mDestRenderSystem->setStencilCheckEnabled(false);
1805            mDestRenderSystem->_setDepthBufferParams();
1806        }
1807
1808    }// for each light
1809
1810    // Iterate again - variable name changed to appease gcc.
1811    RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
1812    while (groupIt2.hasMoreElements())
1813    {
1814        RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
1815
1816        // Do non-shadowable solids
1817        renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1818
1819    }// for each priority
1820
1821
1822    // Iterate again - variable name changed to appease gcc.
1823    RenderQueueGroup::PriorityMapIterator groupIt3 = pGroup->getIterator();
1824    while (groupIt3.hasMoreElements())
1825    {
1826        RenderPriorityGroup* pPriorityGrp = groupIt3.getNext();
1827
1828        // Do transparents (always descending sort)
1829        renderObjects(pPriorityGrp->getTransparents(),
1830                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
1831
1832    }// for each priority
1833
1834}
1835//-----------------------------------------------------------------------
1836void SceneManager::renderTextureShadowCasterQueueGroupObjects(
1837        RenderQueueGroup* pGroup,
1838        QueuedRenderableCollection::OrganisationMode om)
1839{
1840    static LightList nullLightList;
1841    // This is like the basic group render, except we skip all transparents
1842    // and we also render any non-shadowed objects
1843    // Note that non-shadow casters will have already been eliminated during
1844    // _findVisibleObjects
1845
1846    // Iterate through priorities
1847    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1848
1849    // Override auto param ambient to force vertex programs and fixed function to
1850        if (isShadowTechniqueAdditive())
1851        {
1852                // Use simple black / white mask if additive
1853                mAutoParamDataSource.setAmbientLightColour(ColourValue::Black);
1854                mDestRenderSystem->setAmbientLight(0, 0, 0);
1855        }
1856        else
1857        {
1858                // Use shadow colour as caster colour if modulative
1859                mAutoParamDataSource.setAmbientLightColour(mShadowColour);
1860                mDestRenderSystem->setAmbientLight(mShadowColour.r, mShadowColour.g, mShadowColour.b);
1861        }
1862
1863    while (groupIt.hasMoreElements())
1864    {
1865        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1866
1867        // Sort the queue first
1868        pPriorityGrp->sort(mCameraInProgress);
1869
1870        // Do solids, override light list incase any vertex programs use them
1871        renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &nullLightList);
1872        renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, false, &nullLightList);
1873                // Do transparents that cast shadows
1874                renderTransparentShadowCasterObjects(
1875                                pPriorityGrp->getTransparents(),
1876                                QueuedRenderableCollection::OM_SORT_DESCENDING,
1877                                false, &nullLightList);
1878
1879
1880    }// for each priority
1881
1882    // reset ambient light
1883    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
1884    mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
1885}
1886//-----------------------------------------------------------------------
1887void SceneManager::renderModulativeTextureShadowedQueueGroupObjects(
1888        RenderQueueGroup* pGroup,
1889        QueuedRenderableCollection::OrganisationMode om)
1890{
1891    /* For each light, we need to render all the solids from each group,
1892    then do the modulative shadows, then render the transparents from
1893    each group.
1894    Now, this means we are going to reorder things more, but that it required
1895    if the shadows are to look correct. The overall order is preserved anyway,
1896    it's just that all the transparents are at the end instead of them being
1897    interleaved as in the normal rendering loop.
1898    */
1899    // Iterate through priorities
1900    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
1901
1902    while (groupIt.hasMoreElements())
1903    {
1904        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
1905
1906        // Sort the queue first
1907        pPriorityGrp->sort(mCameraInProgress);
1908
1909        // Do solids
1910        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
1911        renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
1912    }
1913
1914
1915    // Iterate over lights, render received shadows
1916    // only perform this if we're in the 'normal' render stage, to avoid
1917    // doing it during the render to texture
1918    if (mIlluminationStage == IRS_NONE)
1919    {
1920        mIlluminationStage = IRS_RENDER_RECEIVER_PASS;
1921
1922        LightList::iterator i, iend;
1923        ShadowTextureList::iterator si, siend;
1924        iend = mLightsAffectingFrustum.end();
1925        siend = mShadowTextures.end();
1926        for (i = mLightsAffectingFrustum.begin(), si = mShadowTextures.begin();
1927            i != iend && si != siend; ++i)
1928        {
1929            Light* l = *i;
1930
1931            if (!l->getCastShadows())
1932                continue;
1933
1934                        // Store current shadow texture
1935            mCurrentShadowTexture = si->getPointer();
1936                        // Get camera for current shadow texture
1937            Camera *cam = mCurrentShadowTexture->getBuffer()->getRenderTarget()->getViewport(0)->getCamera();
1938            // Hook up receiver texture
1939                        Pass* targetPass = mShadowTextureCustomReceiverPass ?
1940                                mShadowTextureCustomReceiverPass : mShadowReceiverPass;
1941            targetPass->getTextureUnitState(0)->setTextureName(
1942                mCurrentShadowTexture->getName());
1943            // Hook up projection frustum
1944            targetPass->getTextureUnitState(0)->setProjectiveTexturing(true, cam);
1945            mAutoParamDataSource.setTextureProjector(cam);
1946            // if this light is a spotlight, we need to add the spot fader layer
1947            if (l->getType() == Light::LT_SPOTLIGHT)
1948            {
1949                                // remove all TUs except 0 & 1
1950                                // (only an issue if additive shadows have been used)
1951                                while(targetPass->getNumTextureUnitStates() > 2)
1952                                        targetPass->removeTextureUnitState(2);
1953
1954                // Add spot fader if not present already
1955                if (targetPass->getNumTextureUnitStates() == 2 &&
1956                                        targetPass->getTextureUnitState(1)->getTextureName() ==
1957                                                "spot_shadow_fade.png")
1958                                {
1959                                        // Just set
1960                                        TextureUnitState* t =
1961                                                targetPass->getTextureUnitState(1);
1962                                        t->setProjectiveTexturing(true, cam);
1963                                }
1964                else
1965                                {
1966                                        // Remove any non-conforming spot layers
1967                                        while(targetPass->getNumTextureUnitStates() > 1)
1968                                                targetPass->removeTextureUnitState(1);
1969
1970                    TextureUnitState* t =
1971                        mShadowReceiverPass->createTextureUnitState("spot_shadow_fade.png");
1972                    t->setProjectiveTexturing(true, cam);
1973                    t->setColourOperation(LBO_ADD);
1974                    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
1975                }
1976            }
1977            else
1978            {
1979                                // remove all TUs except 0 including spot
1980                                while(targetPass->getNumTextureUnitStates() > 1)
1981                        targetPass->removeTextureUnitState(1);
1982
1983            }
1984                        // Set lighting / blending modes
1985                        targetPass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
1986                        targetPass->setLightingEnabled(false);
1987
1988            targetPass->_load();
1989
1990                        // Fire pre-receiver event
1991                        fireShadowTexturesPreReceiver(l, cam);
1992
1993            renderTextureShadowReceiverQueueGroupObjects(pGroup, om);
1994
1995            ++si;
1996
1997        }// for each light
1998
1999        mIlluminationStage = IRS_NONE;
2000
2001    }
2002
2003    // Iterate again - variable name changed to appease gcc.
2004    RenderQueueGroup::PriorityMapIterator groupIt3 = pGroup->getIterator();
2005    while (groupIt3.hasMoreElements())
2006    {
2007        RenderPriorityGroup* pPriorityGrp = groupIt3.getNext();
2008
2009        // Do transparents (always descending)
2010        renderObjects(pPriorityGrp->getTransparents(),
2011                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
2012
2013    }// for each priority
2014
2015}
2016//-----------------------------------------------------------------------
2017void SceneManager::renderAdditiveTextureShadowedQueueGroupObjects(
2018        RenderQueueGroup* pGroup,
2019        QueuedRenderableCollection::OrganisationMode om)
2020{
2021        RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
2022        LightList lightList;
2023
2024        while (groupIt.hasMoreElements())
2025        {
2026                RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
2027
2028                // Sort the queue first
2029                pPriorityGrp->sort(mCameraInProgress);
2030
2031                // Clear light list
2032                lightList.clear();
2033
2034                // Render all the ambient passes first, no light iteration, no lights
2035                renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &lightList);
2036                // Also render any objects which have receive shadows disabled
2037                renderObjects(pPriorityGrp->getSolidsNoShadowReceive(), om, true);
2038
2039
2040                // only perform this next part if we're in the 'normal' render stage, to avoid
2041                // doing it during the render to texture
2042                if (mIlluminationStage == IRS_NONE)
2043                {
2044                        // Iterate over lights, render masked
2045                        LightList::const_iterator li, liend;
2046                        ShadowTextureList::iterator si, siend;
2047                        liend = mLightsAffectingFrustum.end();
2048                        siend = mShadowTextures.end();
2049            si = mShadowTextures.begin();
2050
2051                        for (li = mLightsAffectingFrustum.begin(); li != liend; ++li)
2052                        {
2053                                Light* l = *li;
2054
2055                                if (l->getCastShadows() && si != siend)
2056                                {
2057                                        // Store current shadow texture
2058                                        mCurrentShadowTexture = si->getPointer();
2059                                        // Get camera for current shadow texture
2060                                        Camera *cam = mCurrentShadowTexture->getBuffer()->getRenderTarget()->getViewport(0)->getCamera();
2061                                        // Hook up receiver texture
2062                                        Pass* targetPass = mShadowTextureCustomReceiverPass ?
2063                                                mShadowTextureCustomReceiverPass : mShadowReceiverPass;
2064                                        targetPass->getTextureUnitState(0)->setTextureName(
2065                                                mCurrentShadowTexture->getName());
2066                                        // Hook up projection frustum
2067                                        targetPass->getTextureUnitState(0)->setProjectiveTexturing(true, cam);
2068                                        mAutoParamDataSource.setTextureProjector(cam);
2069                                        // Remove any spot fader layer
2070                                        if (targetPass->getNumTextureUnitStates() > 1 &&
2071                                                targetPass->getTextureUnitState(1)->getTextureName()
2072                                                        == "spot_shadow_fade.png")
2073                                        {
2074                                                // remove spot fader layer (should only be there if
2075                                                // we previously used modulative shadows)
2076                                                targetPass->removeTextureUnitState(1);
2077                                        }
2078                                        // Set lighting / blending modes
2079                                        targetPass->setSceneBlending(SBF_ONE, SBF_ONE);
2080                                        targetPass->setLightingEnabled(true);
2081                                        targetPass->_load();
2082
2083                                        // increment shadow texture since used
2084                                        ++si;
2085
2086                                        mIlluminationStage = IRS_RENDER_RECEIVER_PASS;
2087
2088                                }
2089                                else
2090                                {
2091                                        mIlluminationStage = IRS_NONE;
2092
2093                                }
2094
2095                // render lighting passes for this light
2096                if (lightList.empty())
2097                    lightList.push_back(l);
2098                else
2099                    lightList[0] = l;
2100                                renderObjects(pPriorityGrp->getSolidsDiffuseSpecular(), om, false, &lightList);
2101
2102                        }// for each light
2103
2104                        mIlluminationStage = IRS_NONE;
2105
2106                        // Now render decal passes, no need to set lights as lighting will be disabled
2107                        renderObjects(pPriorityGrp->getSolidsDecal(), om, false);
2108
2109                }
2110
2111
2112        }// for each priority
2113
2114        // Iterate again - variable name changed to appease gcc.
2115        RenderQueueGroup::PriorityMapIterator groupIt2 = pGroup->getIterator();
2116        while (groupIt2.hasMoreElements())
2117        {
2118                RenderPriorityGroup* pPriorityGrp = groupIt2.getNext();
2119
2120                // Do transparents (always descending sort)
2121                renderObjects(pPriorityGrp->getTransparents(),
2122                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
2123
2124        }// for each priority
2125
2126}
2127//-----------------------------------------------------------------------
2128void SceneManager::renderTextureShadowReceiverQueueGroupObjects(
2129        RenderQueueGroup* pGroup,
2130        QueuedRenderableCollection::OrganisationMode om)
2131{
2132    static LightList nullLightList;
2133
2134    // Iterate through priorities
2135    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
2136
2137    // Override auto param ambient to force vertex programs to go full-bright
2138    mAutoParamDataSource.setAmbientLightColour(ColourValue::White);
2139    mDestRenderSystem->setAmbientLight(1, 1, 1);
2140
2141    while (groupIt.hasMoreElements())
2142    {
2143        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
2144
2145        // Do solids, override light list incase any vertex programs use them
2146        renderObjects(pPriorityGrp->getSolidsBasic(), om, false, &nullLightList);
2147
2148        // Don't render transparents or passes which have shadow receipt disabled
2149
2150    }// for each priority
2151
2152    // reset ambient
2153    mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
2154    mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b);
2155
2156}
2157//-----------------------------------------------------------------------
2158void SceneManager::SceneMgrQueuedRenderableVisitor::visit(const Renderable* r)
2159{
2160        // Give SM a chance to eliminate
2161        if (targetSceneMgr->validateRenderableForRendering(mUsedPass, r))
2162        {
2163                // Render a single object, this will set up auto params if required
2164                targetSceneMgr->renderSingleObject(r, mUsedPass, autoLights, manualLightList);
2165        }
2166}
2167//-----------------------------------------------------------------------
2168bool SceneManager::SceneMgrQueuedRenderableVisitor::visit(const Pass* p)
2169{
2170        // Give SM a chance to eliminate this pass
2171        if (!targetSceneMgr->validatePassForRendering(p))
2172                return false;
2173
2174        // Set pass, store the actual one used
2175        mUsedPass = targetSceneMgr->_setPass(p);
2176
2177
2178        return true;
2179}
2180//-----------------------------------------------------------------------
2181void SceneManager::SceneMgrQueuedRenderableVisitor::visit(const RenderablePass* rp)
2182{
2183        // Skip this one if we're in transparency cast shadows mode & it doesn't
2184        // Don't need to implement this one in the other visit methods since
2185        // transparents are never grouped, always sorted
2186        if (transparentShadowCastersMode &&
2187                !rp->pass->getParent()->getParent()->getTransparencyCastsShadows())
2188                return;
2189
2190        // Give SM a chance to eliminate
2191        if (targetSceneMgr->validateRenderableForRendering(rp->pass, rp->renderable))
2192        {
2193                targetSceneMgr->_setPass(rp->pass);
2194                targetSceneMgr->renderSingleObject(rp->renderable, rp->pass, autoLights,
2195                        manualLightList);
2196        }
2197}
2198//-----------------------------------------------------------------------
2199bool SceneManager::validatePassForRendering(const Pass* pass)
2200{
2201    // Bypass if we're doing a texture shadow render and
2202    // this pass is after the first (only 1 pass needed for modulative shadow texture)
2203        // Also bypass if passes above the first if render state changes are
2204        // suppressed since we're not actually using this pass data anyway
2205    if (!mSuppressShadows && mCurrentViewport->getShadowsEnabled() &&
2206                isShadowTechniqueModulative() &&
2207                (mIlluminationStage == IRS_RENDER_TO_TEXTURE ||
2208        mIlluminationStage == IRS_RENDER_RECEIVER_PASS ||
2209                mSuppressRenderStateChanges) &&
2210        pass->getIndex() > 0)
2211    {
2212        return false;
2213    }
2214
2215#ifdef GAMETOOLS_ILLUMINATION_MODULE
2216        if(!pass->isActive())
2217                return false;
2218#endif
2219
2220
2221
2222    return true;
2223}
2224//-----------------------------------------------------------------------
2225bool SceneManager::validateRenderableForRendering(const Pass* pass, const Renderable* rend)
2226{
2227    // Skip this renderable if we're doing modulative texture shadows, it casts shadows
2228    // and we're doing the render receivers pass and we're not self-shadowing
2229    if (!mSuppressShadows && mCurrentViewport->getShadowsEnabled() &&
2230                isShadowTechniqueTextureBased() &&
2231        mIlluminationStage == IRS_RENDER_RECEIVER_PASS &&
2232        rend->getCastsShadows() && !mShadowTextureSelfShadow &&
2233                isShadowTechniqueModulative())
2234    {
2235        return false;
2236    }
2237
2238    return true;
2239
2240}
2241//-----------------------------------------------------------------------
2242void SceneManager::renderObjects(const QueuedRenderableCollection& objs,
2243                                                                 QueuedRenderableCollection::OrganisationMode om,
2244                                                                 bool doLightIteration,
2245                                 const LightList* manualLightList)
2246{
2247        mActiveQueuedRenderableVisitor->autoLights = doLightIteration;
2248        mActiveQueuedRenderableVisitor->manualLightList = manualLightList;
2249        mActiveQueuedRenderableVisitor->transparentShadowCastersMode = false;
2250        // Use visitor
2251        objs.acceptVisitor(mActiveQueuedRenderableVisitor, om);
2252}
2253//-----------------------------------------------------------------------
2254void SceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup,
2255                                                                                   QueuedRenderableCollection::OrganisationMode om)
2256{
2257        bool doShadows =
2258                pGroup->getShadowsEnabled() &&
2259                mCurrentViewport->getShadowsEnabled() &&
2260                !mSuppressShadows && !mSuppressRenderStateChanges;
2261       
2262    if (doShadows && mShadowTechnique == SHADOWTYPE_STENCIL_ADDITIVE)
2263    {
2264        // Additive stencil shadows in use
2265        renderAdditiveStencilShadowedQueueGroupObjects(pGroup, om);
2266    }
2267    else if (doShadows && mShadowTechnique == SHADOWTYPE_STENCIL_MODULATIVE)
2268    {
2269        // Modulative stencil shadows in use
2270        renderModulativeStencilShadowedQueueGroupObjects(pGroup, om);
2271    }
2272    else if (isShadowTechniqueTextureBased())
2273    {
2274        // Modulative texture shadows in use
2275        if (mIlluminationStage == IRS_RENDER_TO_TEXTURE)
2276        {
2277            // Shadow caster pass
2278            if (mCurrentViewport->getShadowsEnabled() &&
2279                !mSuppressShadows && !mSuppressRenderStateChanges)
2280            {
2281                renderTextureShadowCasterQueueGroupObjects(pGroup, om);
2282            }
2283        }
2284        else
2285        {
2286            // Ordinary + receiver pass
2287            if (doShadows)
2288                        {
2289                                // Receiver pass(es)
2290                                if (isShadowTechniqueAdditive())
2291                                {
2292                                        // Additive
2293                                        renderAdditiveTextureShadowedQueueGroupObjects(pGroup, om);
2294                                }
2295                                else
2296                                {
2297                                        // Modulative
2298                        renderModulativeTextureShadowedQueueGroupObjects(pGroup, om);
2299                                }
2300                        }
2301                        else
2302                                renderBasicQueueGroupObjects(pGroup, om);
2303        }
2304    }
2305    else
2306    {
2307        // No shadows, ordinary pass
2308        renderBasicQueueGroupObjects(pGroup, om);
2309    }
2310
2311
2312}
2313//-----------------------------------------------------------------------
2314void SceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
2315                                                                                                QueuedRenderableCollection::OrganisationMode om)
2316{
2317    // Basic render loop
2318    // Iterate through priorities
2319    RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
2320
2321    while (groupIt.hasMoreElements())
2322    {
2323        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
2324
2325        // Sort the queue first
2326        pPriorityGrp->sort(mCameraInProgress);
2327
2328        // Do solids
2329        renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
2330        // Do transparents (always descending)
2331        renderObjects(pPriorityGrp->getTransparents(),
2332                        QueuedRenderableCollection::OM_SORT_DESCENDING, true);
2333
2334
2335    }// for each priority
2336}
2337//-----------------------------------------------------------------------
2338void SceneManager::renderTransparentShadowCasterObjects(
2339        const QueuedRenderableCollection& objs,
2340        QueuedRenderableCollection::OrganisationMode om, bool doLightIteration,
2341        const LightList* manualLightList)
2342{
2343        mActiveQueuedRenderableVisitor->transparentShadowCastersMode = true;
2344        mActiveQueuedRenderableVisitor->autoLights = doLightIteration;
2345        mActiveQueuedRenderableVisitor->manualLightList = manualLightList;
2346       
2347        // Sort descending (transparency)
2348        objs.acceptVisitor(mActiveQueuedRenderableVisitor,
2349                QueuedRenderableCollection::OM_SORT_DESCENDING);
2350
2351        mActiveQueuedRenderableVisitor->transparentShadowCastersMode = false;
2352}
2353//-----------------------------------------------------------------------
2354void SceneManager::renderSingleObject(const Renderable* rend, const Pass* pass,
2355                                      bool doLightIteration, const LightList* manualLightList)
2356{
2357    unsigned short numMatrices;
2358    static RenderOperation ro;
2359    static LightList localLightList;
2360
2361    // Set up rendering operation
2362    // I know, I know, const_cast is nasty but otherwise it requires all internal
2363    // state of the Renderable assigned to the rop to be mutable
2364    const_cast<Renderable*>(rend)->getRenderOperation(ro);
2365    ro.srcRenderable = rend;
2366
2367    // Set world transformation
2368    rend->getWorldTransforms(mTempXform);
2369    numMatrices = rend->getNumWorldTransforms();
2370    if (numMatrices > 1)
2371    {
2372        mDestRenderSystem->_setWorldMatrices(mTempXform, numMatrices);
2373    }
2374    else
2375    {
2376        mDestRenderSystem->_setWorldMatrix(*mTempXform);
2377    }
2378
2379    // Issue view / projection changes if any
2380    useRenderableViewProjMode(rend);
2381
2382    if (!mSuppressRenderStateChanges)
2383    {
2384        bool passSurfaceAndLightParams = true;
2385
2386        if (pass->isProgrammable())
2387        {
2388            // Tell auto params object about the renderable change
2389            mAutoParamDataSource.setCurrentRenderable(rend);
2390            pass->_updateAutoParamsNoLights(mAutoParamDataSource);
2391            if (pass->hasVertexProgram())
2392            {
2393                passSurfaceAndLightParams = pass->getVertexProgram()->getPassSurfaceAndLightStates();
2394            }
2395        }
2396
2397        // Reissue any texture gen settings which are dependent on view matrix
2398        Pass::ConstTextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
2399        size_t unit = 0;
2400        while(texIter.hasMoreElements())
2401        {
2402            TextureUnitState* pTex = texIter.getNext();
2403            if (pTex->hasViewRelativeTextureCoordinateGeneration())
2404            {
2405                mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
2406            }
2407            ++unit;
2408        }
2409
2410        // Sort out normalisation
2411        mDestRenderSystem->setNormaliseNormals(rend->getNormaliseNormals());
2412
2413        // Set up the solid / wireframe override
2414                // Precedence is Camera, Object, Material
2415                // Camera might not override object if not overrideable
2416                PolygonMode reqMode = pass->getPolygonMode();
2417                if (rend->getPolygonModeOverrideable())
2418                {
2419            PolygonMode camPolyMode = mCameraInProgress->getPolygonMode();
2420                        // check camera detial only when render detail is overridable
2421                        if (reqMode > camPolyMode)
2422                        {
2423                                // only downgrade detail; if cam says wireframe we don't go up to solid
2424                                reqMode = camPolyMode;
2425                        }
2426                }
2427                mDestRenderSystem->_setPolygonMode(reqMode);
2428
2429                mDestRenderSystem->setClipPlanes(rend->getClipPlanes());
2430
2431                if (doLightIteration)
2432                {
2433                        // Here's where we issue the rendering operation to the render system
2434                        // Note that we may do this once per light, therefore it's in a loop
2435                        // and the light parameters are updated once per traversal through the
2436                        // loop
2437                        const LightList& rendLightList = rend->getLights();
2438                        bool iteratePerLight = pass->getIteratePerLight();
2439                        size_t numIterations = iteratePerLight ? rendLightList.size() : 1;
2440                        const LightList* pLightListToUse;
2441                        for (size_t i = 0; i < numIterations; ++i)
2442                        {
2443                                // Determine light list to use
2444                                if (iteratePerLight)
2445                                {
2446                                        // Change the only element of local light list to be
2447                                        // the light at index i
2448                                        localLightList.clear();
2449                                        // Check whether we need to filter this one out
2450                                        if (pass->getRunOnlyForOneLightType() &&
2451                                                pass->getOnlyLightType() != rendLightList[i]->getType())
2452                                        {
2453                                                // Skip
2454                                                continue;
2455                                        }
2456
2457                                        localLightList.push_back(rendLightList[i]);
2458                                        pLightListToUse = &localLightList;
2459                                }
2460                                else
2461                                {
2462                                        // Use complete light list
2463                                        pLightListToUse = &rendLightList;
2464                                }
2465
2466
2467                                // Do we need to update GPU program parameters?
2468                                if (pass->isProgrammable())
2469                                {
2470                                        // Update any automatic gpu params for lights
2471                                        // Other bits of information will have to be looked up
2472                                        mAutoParamDataSource.setCurrentLightList(pLightListToUse);
2473                                        pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
2474                                        // NOTE: We MUST bind parameters AFTER updating the autos
2475                                        // TEST
2476                                        if (pass->hasVertexProgram())
2477                                        {
2478                                                mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM,
2479                                                        pass->getVertexProgramParameters());
2480                                        }
2481                                        if (pass->hasFragmentProgram())
2482                                        {
2483                                                mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM,
2484                                                        pass->getFragmentProgramParameters());
2485                                        }
2486                                }
2487                                // Do we need to update light states?
2488                                // Only do this if fixed-function vertex lighting applies
2489                                if (pass->getLightingEnabled() && passSurfaceAndLightParams)
2490                                {
2491                                        mDestRenderSystem->_useLights(*pLightListToUse, pass->getMaxSimultaneousLights());
2492                                }
2493                                // issue the render op         
2494                                // nfz: check for gpu_multipass
2495                                mDestRenderSystem->setCurrentPassIterationCount(pass->getPassIterationCount());
2496                                mDestRenderSystem->_render(ro);
2497                        } // possibly iterate per light
2498                }
2499                else // no automatic light processing
2500                {
2501                        // Do we need to update GPU program parameters?
2502                        if (pass->isProgrammable())
2503                        {
2504                                // Do we have a manual light list?
2505                                if (manualLightList)
2506                                {
2507                                        // Update any automatic gpu params for lights
2508                                        mAutoParamDataSource.setCurrentLightList(manualLightList);
2509                                        pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
2510                                }
2511
2512                                if (pass->hasVertexProgram())
2513                                {
2514                                        mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM,
2515                                                pass->getVertexProgramParameters());
2516                                }
2517                                if (pass->hasFragmentProgram())
2518                                {
2519                                        mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM,
2520                                                pass->getFragmentProgramParameters());
2521                                }
2522                        }
2523
2524                        // Use manual lights if present, and not using vertex programs that don't use fixed pipeline
2525                        if (manualLightList &&
2526                                pass->getLightingEnabled() && passSurfaceAndLightParams)
2527                        {
2528                                mDestRenderSystem->_useLights(*manualLightList, pass->getMaxSimultaneousLights());
2529                        }
2530                        // issue the render op         
2531                        // nfz: set up multipass rendering
2532                        mDestRenderSystem->setCurrentPassIterationCount(pass->getPassIterationCount());
2533                        mDestRenderSystem->_render(ro);
2534                }
2535
2536        }
2537        else // mSuppressRenderStateChanges
2538        {
2539                // Just render
2540                mDestRenderSystem->setCurrentPassIterationCount(1);
2541                mDestRenderSystem->_render(ro);
2542        }
2543       
2544    // Reset view / projection changes if any
2545    resetViewProjMode();
2546
2547}
2548//-----------------------------------------------------------------------
2549void SceneManager::setAmbientLight(const ColourValue& colour)
2550{
2551    mAmbientLight = colour;
2552}
2553//-----------------------------------------------------------------------
2554const ColourValue& SceneManager::getAmbientLight(void) const
2555{
2556    return mAmbientLight;
2557}
2558//-----------------------------------------------------------------------
2559ViewPoint SceneManager::getSuggestedViewpoint(bool random)
2560{
2561    // By default return the origin
2562    ViewPoint vp;
2563    vp.position = Vector3::ZERO;
2564    vp.orientation = Quaternion::IDENTITY;
2565    return vp;
2566}
2567//-----------------------------------------------------------------------
2568void SceneManager::setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
2569{
2570    mFogMode = mode;
2571    mFogColour = colour;
2572    mFogStart = start;
2573    mFogEnd = end;
2574    mFogDensity = density;
2575}
2576//-----------------------------------------------------------------------
2577FogMode SceneManager::getFogMode(void) const
2578{
2579    return mFogMode;
2580}
2581//-----------------------------------------------------------------------
2582const ColourValue& SceneManager::getFogColour(void) const
2583{
2584    return mFogColour;
2585}
2586//-----------------------------------------------------------------------
2587Real SceneManager::getFogStart(void) const
2588{
2589    return mFogStart;
2590}
2591//-----------------------------------------------------------------------
2592Real SceneManager::getFogEnd(void) const
2593{
2594    return mFogEnd;
2595}
2596//-----------------------------------------------------------------------
2597Real SceneManager::getFogDensity(void) const
2598{
2599    return mFogDensity;
2600}
2601//-----------------------------------------------------------------------
2602BillboardSet* SceneManager::createBillboardSet(const String& name, unsigned int poolSize)
2603{
2604        NameValuePairList params;
2605        params["poolSize"] = StringConverter::toString(poolSize);
2606        return static_cast<BillboardSet*>(
2607                createMovableObject(name, BillboardSetFactory::FACTORY_TYPE_NAME, &params));
2608}
2609//-----------------------------------------------------------------------
2610BillboardSet* SceneManager::getBillboardSet(const String& name)
2611{
2612        return static_cast<BillboardSet*>(
2613                getMovableObject(name, BillboardSetFactory::FACTORY_TYPE_NAME));
2614}
2615//-----------------------------------------------------------------------
2616void SceneManager::destroyBillboardSet(BillboardSet* set)
2617{
2618        destroyMovableObject(set);
2619}
2620//-----------------------------------------------------------------------
2621void SceneManager::destroyBillboardSet(const String& name)
2622{
2623        destroyMovableObject(name, BillboardSetFactory::FACTORY_TYPE_NAME);
2624}
2625//-----------------------------------------------------------------------
2626void SceneManager::setDisplaySceneNodes(bool display)
2627{
2628    mDisplayNodes = display;
2629}
2630//-----------------------------------------------------------------------
2631Animation* SceneManager::createAnimation(const String& name, Real length)
2632{
2633    // Check name not used
2634    if (mAnimationsList.find(name) != mAnimationsList.end())
2635    {
2636        OGRE_EXCEPT(
2637            Exception::ERR_DUPLICATE_ITEM,
2638            "An animation with the name " + name + " already exists",
2639            "SceneManager::createAnimation" );
2640    }
2641
2642    Animation* pAnim = new Animation(name, length);
2643    mAnimationsList[name] = pAnim;
2644    return pAnim;
2645}
2646//-----------------------------------------------------------------------
2647Animation* SceneManager::getAnimation(const String& name) const
2648{
2649    AnimationList::const_iterator i = mAnimationsList.find(name);
2650    if (i == mAnimationsList.end())
2651    {
2652        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
2653            "Cannot find animation with name " + name,
2654            "SceneManager::getAnimation");
2655    }
2656    return i->second;
2657}
2658//-----------------------------------------------------------------------
2659void SceneManager::destroyAnimation(const String& name)
2660{
2661    // Also destroy any animation states referencing this animation
2662        mAnimationStates.removeAnimationState(name);
2663
2664    AnimationList::iterator i = mAnimationsList.find(name);
2665    if (i == mAnimationsList.end())
2666    {
2667        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
2668            "Cannot find animation with name " + name,
2669            "SceneManager::getAnimation");
2670    }
2671
2672    // Free memory
2673    delete i->second;
2674
2675    mAnimationsList.erase(i);
2676
2677
2678}
2679//-----------------------------------------------------------------------
2680void SceneManager::destroyAllAnimations(void)
2681{
2682    // Destroy all states too, since they cannot reference destroyed animations
2683    destroyAllAnimationStates();
2684
2685    AnimationList::iterator i;
2686    for (i = mAnimationsList.begin(); i != mAnimationsList.end(); ++i)
2687    {
2688        // destroy
2689        delete i->second;
2690    }
2691    mAnimationsList.clear();
2692}
2693//-----------------------------------------------------------------------
2694AnimationState* SceneManager::createAnimationState(const String& animName)
2695{
2696
2697    // Get animation, this will throw an exception if not found
2698    Animation* anim = getAnimation(animName);
2699
2700    // Create new state
2701        return mAnimationStates.createAnimationState(animName, 0, anim->getLength());
2702
2703}
2704//-----------------------------------------------------------------------
2705AnimationState* SceneManager::getAnimationState(const String& animName)
2706{
2707        return mAnimationStates.getAnimationState(animName);
2708
2709}
2710//-----------------------------------------------------------------------
2711void SceneManager::destroyAnimationState(const String& name)
2712{
2713        mAnimationStates.removeAnimationState(name);
2714}
2715//-----------------------------------------------------------------------
2716void SceneManager::destroyAllAnimationStates(void)
2717{
2718    mAnimationStates.removeAllAnimationStates();
2719}
2720//-----------------------------------------------------------------------
2721void SceneManager::_applySceneAnimations(void)
2722{
2723    ConstEnabledAnimationStateIterator stateIt = mAnimationStates.getEnabledAnimationStateIterator();
2724
2725    while (stateIt.hasMoreElements())
2726    {
2727        const AnimationState* state = stateIt.getNext();
2728        Animation* anim = getAnimation(state->getAnimationName());
2729
2730        // Reset any nodes involved
2731        // NB this excludes blended animations
2732        Animation::NodeTrackIterator nodeTrackIt = anim->getNodeTrackIterator();
2733        while(nodeTrackIt.hasMoreElements())
2734        {
2735            Node* nd = nodeTrackIt.getNext()->getAssociatedNode();
2736            nd->resetToInitialState();
2737        }
2738
2739        Animation::NumericTrackIterator numTrackIt = anim->getNumericTrackIterator();
2740        while(numTrackIt.hasMoreElements())
2741        {
2742            numTrackIt.getNext()->getAssociatedAnimable()->resetToBaseValue();
2743        }
2744
2745        // Apply the animation
2746        anim->apply(state->getTimePosition(), state->getWeight());
2747    }
2748
2749
2750}
2751//---------------------------------------------------------------------
2752void SceneManager::manualRender(RenderOperation* rend,
2753                                Pass* pass, Viewport* vp, const Matrix4& worldMatrix,
2754                                const Matrix4& viewMatrix, const Matrix4& projMatrix,
2755                                bool doBeginEndFrame)
2756{
2757    mDestRenderSystem->_setViewport(vp);
2758    mDestRenderSystem->_setWorldMatrix(worldMatrix);
2759    mDestRenderSystem->_setViewMatrix(viewMatrix);
2760    mDestRenderSystem->_setProjectionMatrix(projMatrix);
2761
2762    if (doBeginEndFrame)
2763        mDestRenderSystem->_beginFrame();
2764
2765    _setPass(pass);
2766    mDestRenderSystem->_render(*rend);
2767
2768    if (doBeginEndFrame)
2769        mDestRenderSystem->_endFrame();
2770
2771}
2772//---------------------------------------------------------------------
2773void SceneManager::useRenderableViewProjMode(const Renderable* pRend)
2774{
2775    // Check view matrix
2776    bool useIdentityView = pRend->useIdentityView();
2777    if (useIdentityView)
2778    {
2779        // Using identity view now, change it
2780        mDestRenderSystem->_setViewMatrix(Matrix4::IDENTITY);
2781        mResetIdentityView = true;
2782    }
2783
2784    bool useIdentityProj = pRend->useIdentityProjection();
2785    if (useIdentityProj)
2786    {
2787        // Use identity projection matrix, still need to take RS depth into account.
2788        Matrix4 mat;
2789        mDestRenderSystem->_convertProjectionMatrix(Matrix4::IDENTITY, mat);
2790        mDestRenderSystem->_setProjectionMatrix(mat);
2791
2792        mResetIdentityProj = true;
2793    }
2794
2795   
2796}
2797//---------------------------------------------------------------------
2798void SceneManager::resetViewProjMode(void)
2799{
2800    if (mResetIdentityView)
2801    {
2802        // Coming back to normal from identity view
2803        mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix(true));
2804        mResetIdentityView = false;
2805    }
2806   
2807    if (mResetIdentityProj)
2808    {
2809        // Coming back from flat projection
2810        mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrixRS());
2811        mResetIdentityProj = false;
2812    }
2813   
2814
2815}
2816//---------------------------------------------------------------------
2817void SceneManager::_queueSkiesForRendering(Camera* cam)
2818{
2819    // Update nodes
2820    // Translate the box by the camera position (constant distance)
2821    if (mSkyPlaneNode)
2822    {
2823        // The plane position relative to the camera has already been set up
2824        mSkyPlaneNode->setPosition(cam->getDerivedPosition());
2825    }
2826
2827    if (mSkyBoxNode)
2828    {
2829        mSkyBoxNode->setPosition(cam->getDerivedPosition());
2830    }
2831
2832    if (mSkyDomeNode)
2833    {
2834        mSkyDomeNode->setPosition(cam->getDerivedPosition());
2835    }
2836
2837    uint8 qid;
2838    if (mSkyPlaneEnabled)
2839    {
2840        qid = mSkyPlaneDrawFirst?
2841RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
2842        getRenderQueue()->addRenderable(mSkyPlaneEntity->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
2843    }
2844
2845    uint plane;
2846    if (mSkyBoxEnabled)
2847    {
2848        qid = mSkyBoxDrawFirst?
2849RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
2850
2851        for (plane = 0; plane < 6; ++plane)
2852        {
2853            getRenderQueue()->addRenderable(
2854                mSkyBoxEntity[plane]->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
2855        }
2856    }
2857
2858    if (mSkyDomeEnabled)
2859    {
2860        qid = mSkyDomeDrawFirst?
2861RENDER_QUEUE_SKIES_EARLY : RENDER_QUEUE_SKIES_LATE;
2862
2863        for (plane = 0; plane < 5; ++plane)
2864        {
2865            getRenderQueue()->addRenderable(
2866                mSkyDomeEntity[plane]->getSubEntity(0), qid, OGRE_RENDERABLE_DEFAULT_PRIORITY);
2867        }
2868    }
2869}
2870//---------------------------------------------------------------------
2871void SceneManager::addRenderQueueListener(RenderQueueListener* newListener)
2872{
2873    mRenderQueueListeners.push_back(newListener);
2874}
2875//---------------------------------------------------------------------
2876void SceneManager::removeRenderQueueListener(RenderQueueListener* delListener)
2877{
2878    RenderQueueListenerList::iterator i, iend;
2879    iend = mRenderQueueListeners.end();
2880    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
2881    {
2882        if (*i == delListener)
2883        {
2884            mRenderQueueListeners.erase(i);
2885            break;
2886        }
2887    }
2888
2889}
2890//---------------------------------------------------------------------
2891void SceneManager::addShadowListener(ShadowListener* newListener)
2892{
2893    mShadowListeners.push_back(newListener);
2894}
2895//---------------------------------------------------------------------
2896void SceneManager::removeShadowListener(ShadowListener* delListener)
2897{
2898    ShadowListenerList::iterator i, iend;
2899    iend = mShadowListeners.end();
2900    for (i = mShadowListeners.begin(); i != iend; ++i)
2901    {
2902        if (*i == delListener)
2903        {
2904            mShadowListeners.erase(i);
2905            break;
2906        }
2907    }
2908
2909}
2910//---------------------------------------------------------------------
2911bool SceneManager::fireRenderQueueStarted(uint8 id, const String& invocation)
2912{
2913    RenderQueueListenerList::iterator i, iend;
2914    bool skip = false;
2915
2916    iend = mRenderQueueListeners.end();
2917    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
2918    {
2919        (*i)->renderQueueStarted(id, invocation, skip);
2920    }
2921    return skip;
2922}
2923//---------------------------------------------------------------------
2924bool SceneManager::fireRenderQueueEnded(uint8 id, const String& invocation)
2925{
2926    RenderQueueListenerList::iterator i, iend;
2927    bool repeat = false;
2928
2929    iend = mRenderQueueListeners.end();
2930    for (i = mRenderQueueListeners.begin(); i != iend; ++i)
2931    {
2932        (*i)->renderQueueEnded(id, invocation, repeat);
2933    }
2934    return repeat;
2935}
2936//---------------------------------------------------------------------
2937void SceneManager::fireShadowTexturesUpdated(size_t numberOfShadowTextures)
2938{
2939    ShadowListenerList::iterator i, iend;
2940
2941    iend = mShadowListeners.end();
2942    for (i = mShadowListeners.begin(); i != iend; ++i)
2943    {
2944        (*i)->shadowTexturesUpdated(numberOfShadowTextures);
2945    }
2946}
2947//---------------------------------------------------------------------
2948void SceneManager::fireShadowTexturesPreCaster(Light* light, Camera* camera)
2949{
2950    ShadowListenerList::iterator i, iend;
2951
2952    iend = mShadowListeners.end();
2953    for (i = mShadowListeners.begin(); i != iend; ++i)
2954    {
2955        (*i)->shadowTextureCasterPreViewProj(light, camera);
2956    }
2957}
2958//---------------------------------------------------------------------
2959void SceneManager::fireShadowTexturesPreReceiver(Light* light, Frustum* f)
2960{
2961    ShadowListenerList::iterator i, iend;
2962
2963    iend = mShadowListeners.end();
2964    for (i = mShadowListeners.begin(); i != iend; ++i)
2965    {
2966        (*i)->shadowTextureReceiverPreViewProj(light, f);
2967    }
2968}
2969//---------------------------------------------------------------------
2970void SceneManager::setViewport(Viewport* vp)
2971{
2972    mCurrentViewport = vp;
2973    // Set viewport in render system
2974    mDestRenderSystem->_setViewport(vp);
2975        // Set the active material scheme for this viewport
2976        MaterialManager::getSingleton().setActiveScheme(vp->getMaterialScheme());
2977}
2978//---------------------------------------------------------------------
2979void SceneManager::showBoundingBoxes(bool bShow)
2980{
2981    mShowBoundingBoxes = bShow;
2982}
2983//---------------------------------------------------------------------
2984bool SceneManager::getShowBoundingBoxes() const
2985{
2986    return mShowBoundingBoxes;
2987}
2988//---------------------------------------------------------------------
2989void SceneManager::_notifyAutotrackingSceneNode(SceneNode* node, bool autoTrack)
2990{
2991    if (autoTrack)
2992    {
2993        mAutoTrackingSceneNodes.insert(node);
2994    }
2995    else
2996    {
2997        mAutoTrackingSceneNodes.erase(node);
2998    }
2999}
3000//---------------------------------------------------------------------
3001void SceneManager::setShadowTechnique(ShadowTechnique technique)
3002{
3003    mShadowTechnique = technique;
3004    if (isShadowTechniqueStencilBased())
3005    {
3006        // Firstly check that we  have a stencil
3007        // Otherwise forget it
3008        if (!mDestRenderSystem->getCapabilities()->hasCapability(RSC_HWSTENCIL))
3009        {
3010            LogManager::getSingleton().logMessage(
3011                "WARNING: Stencil shadows were requested, but this device does not "
3012                "have a hardware stencil. Shadows disabled.");
3013            mShadowTechnique = SHADOWTYPE_NONE;
3014        }
3015        else if (mShadowIndexBuffer.isNull())
3016        {
3017            // Create an estimated sized shadow index buffer
3018            mShadowIndexBuffer = HardwareBufferManager::getSingleton().
3019                createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
3020                mShadowIndexBufferSize,
3021                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,
3022                false);
3023            // tell all meshes to prepare shadow volumes
3024            MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(true);
3025        }
3026        }
3027
3028    if (isShadowTechniqueTextureBased())
3029    {
3030        createShadowTextures(mShadowTextureSize, mShadowTextureCount, mShadowTextureFormat);
3031    }
3032    else
3033    {
3034        // Destroy shadow textures to optimise resource usage
3035        destroyShadowTextures();
3036    }
3037
3038}
3039//---------------------------------------------------------------------
3040void SceneManager::_suppressShadows(bool suppress)
3041{
3042        mSuppressShadows = suppress;
3043}
3044//---------------------------------------------------------------------
3045void SceneManager::_suppressRenderStateChanges(bool suppress)
3046{
3047        mSuppressRenderStateChanges = suppress;
3048}
3049//---------------------------------------------------------------------
3050void SceneManager::updateRenderQueueSplitOptions(void)
3051{
3052        if (isShadowTechniqueStencilBased())
3053        {
3054                // Casters can always be receivers
3055                getRenderQueue()->setShadowCastersCannotBeReceivers(false);
3056        }
3057        else // texture based
3058        {
3059                getRenderQueue()->setShadowCastersCannotBeReceivers(!mShadowTextureSelfShadow);
3060        }
3061
3062        if (isShadowTechniqueAdditive() && mCurrentViewport->getShadowsEnabled())
3063        {
3064                // Additive lighting, we need to split everything by illumination stage
3065                getRenderQueue()->setSplitPassesByLightingType(true);
3066        }
3067        else
3068        {
3069                getRenderQueue()->setSplitPassesByLightingType(false);
3070        }
3071
3072        if (isShadowTechniqueInUse() && mCurrentViewport->getShadowsEnabled())
3073        {
3074                // Tell render queue to split off non-shadowable materials
3075                getRenderQueue()->setSplitNoShadowPasses(true);
3076        }
3077        else
3078        {
3079                getRenderQueue()->setSplitNoShadowPasses(false);
3080        }
3081
3082
3083}
3084//---------------------------------------------------------------------
3085void SceneManager::updateRenderQueueGroupSplitOptions(RenderQueueGroup* group,
3086        bool suppressShadows, bool suppressRenderState)
3087{
3088        if (isShadowTechniqueStencilBased())
3089        {
3090                // Casters can always be receivers
3091                group->setShadowCastersCannotBeReceivers(false);
3092        }
3093        else if (isShadowTechniqueTextureBased())
3094        {
3095                group->setShadowCastersCannotBeReceivers(!mShadowTextureSelfShadow);
3096        }
3097
3098        if (!suppressShadows && mCurrentViewport->getShadowsEnabled() &&
3099                isShadowTechniqueAdditive())
3100        {
3101                // Additive lighting, we need to split everything by illumination stage
3102                group->setSplitPassesByLightingType(true);
3103        }
3104        else
3105        {
3106                group->setSplitPassesByLightingType(false);
3107        }
3108
3109        if (!suppressShadows && mCurrentViewport->getShadowsEnabled()
3110                && isShadowTechniqueInUse())
3111        {
3112                // Tell render queue to split off non-shadowable materials
3113                group->setSplitNoShadowPasses(true);
3114        }
3115        else
3116        {
3117                group->setSplitNoShadowPasses(false);
3118        }
3119
3120
3121}
3122//---------------------------------------------------------------------
3123void SceneManager::findLightsAffectingFrustum(const Camera* camera)
3124{
3125    // Basic iteration for this SM
3126    mLightsAffectingFrustum.clear();
3127    Sphere sphere;
3128        MovableObjectIterator it =
3129                getMovableObjectIterator(LightFactory::FACTORY_TYPE_NAME);
3130    while(it.hasMoreElements())
3131    {
3132        Light* l = static_cast<Light*>(it.getNext());
3133                if (l->isVisible())
3134                {
3135                        if (l->getType() == Light::LT_DIRECTIONAL)
3136                        {
3137                                // Always visible
3138                                mLightsAffectingFrustum.push_back(l);
3139                        }
3140                        else
3141                        {
3142                                // NB treating spotlight as point for simplicity
3143                                // Just see if the lights attenuation range is within the frustum
3144                                sphere.setCenter(l->getDerivedPosition());
3145                                sphere.setRadius(l->getAttenuationRange());
3146                                if (camera->isVisible(sphere))
3147                                {
3148                                        mLightsAffectingFrustum.push_back(l);
3149                                }
3150
3151                        }
3152                }
3153    }
3154
3155}
3156//---------------------------------------------------------------------
3157bool SceneManager::ShadowCasterSceneQueryListener::queryResult(
3158    MovableObject* object)
3159{
3160    if (object->getCastShadows() && object->isVisible() &&
3161                mSceneMgr->isRenderQueueToBeProcessed(object->getRenderQueueGroup()))
3162    {
3163        if (mFarDistSquared)
3164        {
3165            // Check object is within the shadow far distance
3166            Vector3 toObj = object->getParentNode()->_getDerivedPosition()
3167                - mCamera->getDerivedPosition();
3168            Real radius = object->getWorldBoundingSphere().getRadius();
3169            Real dist =  toObj.squaredLength();               
3170            if (dist - (radius * radius) > mFarDistSquared)
3171            {
3172                // skip, beyond max range
3173                return true;
3174            }
3175        }
3176
3177        // If the object is in the frustum, we can always see the shadow
3178        if (mCamera->isVisible(object->getWorldBoundingBox()))
3179        {
3180            mCasterList->push_back(object);
3181            return true;
3182        }
3183
3184        // Otherwise, object can only be casting a shadow into our view if
3185        // the light is outside the frustum (or it's a directional light,
3186        // which are always outside), and the object is intersecting
3187        // on of the volumes formed between the edges of the frustum and the
3188        // light
3189        if (!mIsLightInFrustum || mLight->getType() == Light::LT_DIRECTIONAL)
3190        {
3191            // Iterate over volumes
3192            PlaneBoundedVolumeList::const_iterator i, iend;
3193            iend = mLightClipVolumeList->end();
3194            for (i = mLightClipVolumeList->begin(); i != iend; ++i)
3195            {
3196                if (i->intersects(object->getWorldBoundingBox()))
3197                {
3198                    mCasterList->push_back(object);
3199                    return true;
3200                }
3201
3202            }
3203
3204        }
3205    }
3206    return true;
3207}
3208//---------------------------------------------------------------------
3209bool SceneManager::ShadowCasterSceneQueryListener::queryResult(
3210    SceneQuery::WorldFragment* fragment)
3211{
3212    // don't deal with world geometry
3213    return true;
3214}
3215//---------------------------------------------------------------------
3216const SceneManager::ShadowCasterList& SceneManager::findShadowCastersForLight(
3217    const Light* light, const Camera* camera)
3218{
3219    mShadowCasterList.clear();
3220
3221    if (light->getType() == Light::LT_DIRECTIONAL)
3222    {
3223        // Basic AABB query encompassing the frustum and the extrusion of it
3224        AxisAlignedBox aabb;
3225        const Vector3* corners = camera->getWorldSpaceCorners();
3226        Vector3 min, max;
3227        Vector3 extrude = light->getDerivedDirection() * -mShadowDirLightExtrudeDist;
3228        // do first corner
3229        min = max = corners[0];
3230        min.makeFloor(corners[0] + extrude);
3231        max.makeCeil(corners[0] + extrude);
3232        for (size_t c = 1; c < 8; ++c)
3233        {
3234            min.makeFloor(corners[c]);
3235            max.makeCeil(corners[c]);
3236            min.makeFloor(corners[c] + extrude);
3237            max.makeCeil(corners[c] + extrude);
3238        }
3239        aabb.setExtents(min, max);
3240
3241        if (!mShadowCasterAABBQuery)
3242            mShadowCasterAABBQuery = createAABBQuery(aabb);
3243        else
3244            mShadowCasterAABBQuery->setBox(aabb);
3245        // Execute, use callback
3246        mShadowCasterQueryListener->prepare(false,
3247            &(light->_getFrustumClipVolumes(camera)),
3248            light, camera, &mShadowCasterList, mShadowFarDistSquared);
3249        mShadowCasterAABBQuery->execute(mShadowCasterQueryListener);
3250
3251
3252    }
3253    else
3254    {
3255        Sphere s(light->getDerivedPosition(), light->getAttenuationRange());
3256        // eliminate early if camera cannot see light sphere
3257        if (camera->isVisible(s))
3258        {
3259            if (!mShadowCasterSphereQuery)
3260                mShadowCasterSphereQuery = createSphereQuery(s);
3261            else
3262                mShadowCasterSphereQuery->setSphere(s);
3263
3264            // Determine if light is inside or outside the frustum
3265            bool lightInFrustum = camera->isVisible(light->getDerivedPosition());
3266            const PlaneBoundedVolumeList* volList = 0;
3267            if (!lightInFrustum)
3268            {
3269                // Only worth building an external volume list if
3270                // light is outside the frustum
3271                volList = &(light->_getFrustumClipVolumes(camera));
3272            }
3273
3274            // Execute, use callback
3275            mShadowCasterQueryListener->prepare(lightInFrustum,
3276                volList, light, camera, &mShadowCasterList, mShadowFarDistSquared);
3277            mShadowCasterSphereQuery->execute(mShadowCasterQueryListener);
3278
3279        }
3280
3281    }
3282
3283
3284    return mShadowCasterList;
3285}
3286//---------------------------------------------------------------------
3287void SceneManager::initShadowVolumeMaterials(void)
3288{
3289    /* This should have been set in the SceneManager constructor, but if you
3290       created the SceneManager BEFORE the Root object, you will need to call
3291       SceneManager::_setDestinationRenderSystem manually.
3292     */
3293    assert( mDestRenderSystem );
3294
3295    if (mShadowMaterialInitDone)
3296        return;
3297
3298    if (!mShadowDebugPass)
3299    {
3300        MaterialPtr matDebug =
3301            MaterialManager::getSingleton().getByName("Ogre/Debug/ShadowVolumes");
3302        if (matDebug.isNull())
3303        {
3304            // Create
3305            matDebug = MaterialManager::getSingleton().create(
3306                "Ogre/Debug/ShadowVolumes",
3307                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3308            mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
3309            mShadowDebugPass->setSceneBlending(SBT_ADD);
3310            mShadowDebugPass->setLightingEnabled(false);
3311            mShadowDebugPass->setDepthWriteEnabled(false);
3312            TextureUnitState* t = mShadowDebugPass->createTextureUnitState();
3313            t->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
3314                ColourValue(0.7, 0.0, 0.2));
3315            mShadowDebugPass->setCullingMode(CULL_NONE);
3316
3317            if (mDestRenderSystem->getCapabilities()->hasCapability(
3318                RSC_VERTEX_PROGRAM))
3319            {
3320                ShadowVolumeExtrudeProgram::initialise();
3321
3322                // Enable the (infinite) point light extruder for now, just to get some params
3323                mShadowDebugPass->setVertexProgram(
3324                    ShadowVolumeExtrudeProgram::programNames[ShadowVolumeExtrudeProgram::POINT_LIGHT]);
3325                mInfiniteExtrusionParams =
3326                    mShadowDebugPass->getVertexProgramParameters();
3327                mInfiniteExtrusionParams->setAutoConstant(0,
3328                    GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
3329                mInfiniteExtrusionParams->setAutoConstant(4,
3330                    GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
3331            }   
3332            matDebug->compile();
3333
3334        }
3335        else
3336        {
3337            mShadowDebugPass = matDebug->getTechnique(0)->getPass(0);
3338
3339            if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
3340            {
3341                mInfiniteExtrusionParams = mShadowDebugPass->getVertexProgramParameters();
3342            }
3343        }
3344    }
3345
3346    if (!mShadowStencilPass)
3347    {
3348
3349        MaterialPtr matStencil = MaterialManager::getSingleton().getByName(
3350            "Ogre/StencilShadowVolumes");
3351        if (matStencil.isNull())
3352        {
3353            // Init
3354            matStencil = MaterialManager::getSingleton().create(
3355                "Ogre/StencilShadowVolumes",
3356                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3357            mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
3358
3359            if (mDestRenderSystem->getCapabilities()->hasCapability(
3360                RSC_VERTEX_PROGRAM))
3361            {
3362
3363                // Enable the finite point light extruder for now, just to get some params
3364                mShadowStencilPass->setVertexProgram(
3365                    ShadowVolumeExtrudeProgram::programNames[ShadowVolumeExtrudeProgram::POINT_LIGHT_FINITE]);
3366                mFiniteExtrusionParams =
3367                    mShadowStencilPass->getVertexProgramParameters();
3368                mFiniteExtrusionParams->setAutoConstant(0,
3369                    GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
3370                mFiniteExtrusionParams->setAutoConstant(4,
3371                    GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
3372                // Note extra parameter
3373                mFiniteExtrusionParams->setAutoConstant(5,
3374                    GpuProgramParameters::ACT_SHADOW_EXTRUSION_DISTANCE);
3375            }
3376            matStencil->compile();
3377            // Nothing else, we don't use this like a 'real' pass anyway,
3378            // it's more of a placeholder
3379        }
3380        else
3381        {
3382            mShadowStencilPass = matStencil->getTechnique(0)->getPass(0);
3383
3384            if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
3385            {
3386                mFiniteExtrusionParams = mShadowStencilPass->getVertexProgramParameters();
3387            }
3388        }
3389    }
3390
3391
3392
3393
3394    if (!mShadowModulativePass)
3395    {
3396
3397        MaterialPtr matModStencil = MaterialManager::getSingleton().getByName(
3398            "Ogre/StencilShadowModulationPass");
3399        if (matModStencil.isNull())
3400        {
3401            // Init
3402            matModStencil = MaterialManager::getSingleton().create(
3403                "Ogre/StencilShadowModulationPass",
3404                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3405            mShadowModulativePass = matModStencil->getTechnique(0)->getPass(0);
3406            mShadowModulativePass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);
3407            mShadowModulativePass->setLightingEnabled(false);
3408            mShadowModulativePass->setDepthWriteEnabled(false);
3409            mShadowModulativePass->setDepthCheckEnabled(false);
3410            TextureUnitState* t = mShadowModulativePass->createTextureUnitState();
3411            t->setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
3412                mShadowColour);
3413            mShadowModulativePass->setCullingMode(CULL_NONE);
3414        }
3415        else
3416        {
3417            mShadowModulativePass = matModStencil->getTechnique(0)->getPass(0);
3418        }
3419    }
3420
3421    // Also init full screen quad while we're at it
3422    if (!mFullScreenQuad)
3423    {
3424        mFullScreenQuad = new Rectangle2D();
3425        mFullScreenQuad->setCorners(-1,1,1,-1);
3426    }
3427
3428    // Also init shadow caster material for texture shadows
3429    if (!mShadowCasterPlainBlackPass)
3430    {
3431        MaterialPtr matPlainBlack = MaterialManager::getSingleton().getByName(
3432            "Ogre/TextureShadowCaster");
3433        if (matPlainBlack.isNull())
3434        {
3435            matPlainBlack = MaterialManager::getSingleton().create(
3436                "Ogre/TextureShadowCaster",
3437                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3438            mShadowCasterPlainBlackPass = matPlainBlack->getTechnique(0)->getPass(0);
3439            // Lighting has to be on, because we need shadow coloured objects
3440            // Note that because we can't predict vertex programs, we'll have to
3441            // bind light values to those, and so we bind White to ambient
3442            // reflectance, and we'll set the ambient colour to the shadow colour
3443            mShadowCasterPlainBlackPass->setAmbient(ColourValue::White);
3444            mShadowCasterPlainBlackPass->setDiffuse(ColourValue::Black);
3445            mShadowCasterPlainBlackPass->setSelfIllumination(ColourValue::Black);
3446            mShadowCasterPlainBlackPass->setSpecular(ColourValue::Black);
3447                        // Override fog
3448                        mShadowCasterPlainBlackPass->setFog(true, FOG_NONE);
3449            // no textures or anything else, we will bind vertex programs
3450            // every so often though
3451        }
3452        else
3453        {
3454            mShadowCasterPlainBlackPass = matPlainBlack->getTechnique(0)->getPass(0);
3455        }
3456    }
3457
3458    if (!mShadowReceiverPass)
3459    {
3460        MaterialPtr matShadRec = MaterialManager::getSingleton().getByName(
3461            "Ogre/TextureShadowReceiver");
3462        if (matShadRec.isNull())                       
3463        {
3464            matShadRec = MaterialManager::getSingleton().create(
3465                "Ogre/TextureShadowReceiver",
3466                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
3467            mShadowReceiverPass = matShadRec->getTechnique(0)->getPass(0);
3468                        // Don't set lighting and blending modes here, depends on additive / modulative
3469            TextureUnitState* t = mShadowReceiverPass->createTextureUnitState();
3470            t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
3471        }
3472        else
3473        {
3474            mShadowReceiverPass = matShadRec->getTechnique(0)->getPass(0);
3475        }
3476    }
3477
3478    // Set up spot shadow fade texture (loaded from code data block)
3479    TexturePtr spotShadowFadeTex =
3480        TextureManager::getSingleton().getByName("spot_shadow_fade.png");
3481    if (spotShadowFadeTex.isNull())
3482    {
3483        // Load the manual buffer into an image (don't destroy memory!
3484        DataStreamPtr stream(
3485                        new MemoryDataStream(SPOT_SHADOW_FADE_PNG, SPOT_SHADOW_FADE_PNG_SIZE, false));
3486        Image img;
3487        img.load(stream, "png");
3488        spotShadowFadeTex =
3489            TextureManager::getSingleton().loadImage(
3490                        "spot_shadow_fade.png", ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
3491                        img, TEX_TYPE_2D);
3492    }
3493
3494    mShadowMaterialInitDone = true;
3495}
3496//---------------------------------------------------------------------
3497const Pass* SceneManager::deriveShadowCasterPass(const Pass* pass)
3498{
3499        if (isShadowTechniqueTextureBased())
3500    {
3501                Pass* retPass = mShadowTextureCustomCasterPass ?
3502                        mShadowTextureCustomCasterPass : mShadowCasterPlainBlackPass;
3503
3504               
3505                // Special case alpha-blended passes
3506                if ((pass->getSourceBlendFactor() == SBF_SOURCE_ALPHA &&
3507                        pass->getDestBlendFactor() == SBF_ONE_MINUS_SOURCE_ALPHA)
3508                        || pass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
3509                {
3510                        // Alpha blended passes must retain their transparency
3511                        retPass->setAlphaRejectSettings(pass->getAlphaRejectFunction(),
3512                                pass->getAlphaRejectValue());
3513                        retPass->setSceneBlending(pass->getSourceBlendFactor(), pass->getDestBlendFactor());
3514                        retPass->getParent()->getParent()->setTransparencyCastsShadows(true);
3515
3516                        // So we allow the texture units, but override the colour functions
3517                        // Copy texture state, shift up one since 0 is shadow texture
3518                        size_t origPassTUCount = pass->getNumTextureUnitStates();
3519                        for (size_t t = 0; t < origPassTUCount; ++t)
3520                        {
3521                                TextureUnitState* tex;
3522                                if (retPass->getNumTextureUnitStates() <= t)
3523                                {
3524                                        tex = retPass->createTextureUnitState();
3525                                }
3526                                else
3527                                {
3528                                        tex = retPass->getTextureUnitState(t);
3529                                }
3530                                // copy base state
3531                                (*tex) = *(pass->getTextureUnitState(t));
3532                                // override colour function
3533                                tex->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT,
3534                                        isShadowTechniqueAdditive()? ColourValue::Black : mShadowColour);
3535
3536                        }
3537                        // Remove any extras
3538                        while (retPass->getNumTextureUnitStates() > origPassTUCount)
3539                        {
3540                                retPass->removeTextureUnitState(origPassTUCount);
3541                        }
3542
3543                }
3544                else
3545                {
3546                        // reset
3547                        retPass->setSceneBlending(SBT_REPLACE);
3548                        retPass->setAlphaRejectFunction(CMPF_ALWAYS_PASS);
3549                        while (retPass->getNumTextureUnitStates() > 0)
3550                        {
3551                                retPass->removeTextureUnitState(0);
3552                        }
3553                }
3554
3555                // Propagate culling modes
3556                retPass->setCullingMode(pass->getCullingMode());
3557                retPass->setManualCullingMode(pass->getManualCullingMode());
3558               
3559
3560                if (!pass->getShadowCasterVertexProgramName().empty())
3561                {
3562                        // Have to merge the shadow caster vertex program in
3563                        retPass->setVertexProgram(
3564                                pass->getShadowCasterVertexProgramName());
3565                        const GpuProgramPtr& prg = retPass->getVertexProgram();
3566                        // Load this program if not done already
3567                        if (!prg->isLoaded())
3568                                prg->load();
3569                        // Copy params
3570                        retPass->setVertexProgramParameters(
3571                                pass->getShadowCasterVertexProgramParameters());
3572                        if (retPass == mShadowTextureCustomCasterPass)
3573                        {
3574                                // mark that we've overridden the standard
3575                                mShadowTextureCasterVPDirty = true;
3576                        }
3577                        // Also have to hack the light autoparams, that is done later
3578                }
3579                else
3580                {
3581                        retPass->setVertexProgram(StringUtil::BLANK);
3582                        if (mShadowTextureCasterVPDirty)
3583                        {
3584                                // reset
3585                                mShadowTextureCustomCasterPass->setVertexProgram(
3586                                        mShadowTextureCustomCasterVertexProgram);
3587                                if(mShadowTextureCustomCasterPass->hasVertexProgram())
3588                                {
3589                                        mShadowTextureCustomCasterPass->setVertexProgramParameters(
3590                                                mShadowTextureCustomCasterVPParams);
3591
3592                                }
3593                                mShadowTextureCasterVPDirty = false;
3594                        }
3595                }
3596                return retPass;
3597        }
3598        else
3599        {
3600        return pass;
3601    }
3602
3603}
3604//---------------------------------------------------------------------
3605const Pass* SceneManager::deriveShadowReceiverPass(const Pass* pass)
3606{
3607
3608    if (isShadowTechniqueTextureBased())
3609    {
3610                Pass* retPass = mShadowTextureCustomReceiverPass ?
3611                        mShadowTextureCustomReceiverPass : mShadowReceiverPass;
3612
3613                if (pass->hasVertexProgram())
3614                {
3615                        // Have to merge the receiver vertex program in
3616                        retPass->setVertexProgram(
3617                                pass->getShadowReceiverVertexProgramName());
3618                        // Did this result in a new vertex program?
3619                        if (retPass->hasVertexProgram())
3620                        {
3621                                const GpuProgramPtr& prg = retPass->getVertexProgram();
3622                                // Load this program if required
3623                                if (!prg->isLoaded())
3624                                        prg->load();
3625                                // Copy params
3626                                retPass->setVertexProgramParameters(
3627                                        pass->getShadowReceiverVertexProgramParameters());
3628
3629                                if (retPass == mShadowTextureCustomReceiverPass)
3630                                {
3631                                        // mark that we've overridden the standard
3632                                        mShadowTextureReceiverVPDirty = true;
3633                                }
3634                        }
3635                        // Also have to hack the light autoparams, that is done later
3636                }
3637                else
3638                {
3639                        retPass->setVertexProgram(StringUtil::BLANK);
3640                }
3641
3642                bool resetFragmentProgram = true;
3643        size_t keepTUCount;
3644                // If additive, need lighting parameters & standard programs
3645                if (isShadowTechniqueAdditive())
3646                {
3647                        keepTUCount = 1;
3648                        retPass->setLightingEnabled(true);
3649                        retPass->setAmbient(pass->getAmbient());
3650                        retPass->setSelfIllumination(pass->getSelfIllumination());
3651                        retPass->setDiffuse(pass->getDiffuse());
3652                        retPass->setSpecular(pass->getSpecular());
3653                        retPass->setShininess(pass->getShininess());
3654                        retPass->setIteratePerLight(pass->getIteratePerLight(),
3655                                pass->getRunOnlyForOneLightType(), pass->getOnlyLightType());
3656
3657            // We need to keep alpha rejection settings
3658            retPass->setAlphaRejectSettings(pass->getAlphaRejectFunction(),
3659                pass->getAlphaRejectValue());
3660            // Copy texture state, shift up one since 0 is shadow texture
3661            size_t origPassTUCount = pass->getNumTextureUnitStates();
3662            for (size_t t = 0; t < origPassTUCount; ++t)
3663            {
3664                size_t targetIndex = t+1;
3665                TextureUnitState* tex;
3666                if (retPass->getNumTextureUnitStates() <= targetIndex)
3667                {
3668                    tex = retPass->createTextureUnitState();
3669                }
3670                else
3671                {
3672                    tex = retPass->getTextureUnitState(targetIndex);
3673                }
3674                (*tex) = *(pass->getTextureUnitState(t));
3675            }
3676            keepTUCount = origPassTUCount + 1;
3677
3678                        // Will also need fragment programs since this is a complex light setup
3679                        if (pass->hasFragmentProgram())
3680                        {
3681                                String fragName = pass->getShadowReceiverFragmentProgramName();
3682                                GpuProgramParametersSharedPtr params;
3683                                if (!fragName.empty())
3684                                {
3685                                        resetFragmentProgram = false;
3686
3687                                        params = pass->getShadowReceiverFragmentProgramParameters();
3688
3689                                        retPass->setFragmentProgram(fragName);
3690                                        const GpuProgramPtr& prg = retPass->getFragmentProgram();
3691                                        // Load this program if required
3692                                        if (!prg->isLoaded())
3693                                                prg->load();
3694                                        // Copy params
3695                                        retPass->setFragmentProgramParameters(params);
3696
3697                                        // Did we bind a shadow vertex program?
3698                                        if (pass->hasVertexProgram() && !retPass->hasVertexProgram())
3699                                        {
3700                                                // We didn't bind a receiver-specific program, so bind the original
3701                                                retPass->setVertexProgram(pass->getVertexProgramName());
3702                                                const GpuProgramPtr& prg = retPass->getVertexProgram();
3703                                                // Load this program if required
3704                                                if (!prg->isLoaded())
3705                                                        prg->load();
3706                                                // Copy params
3707                                                retPass->setVertexProgramParameters(
3708                                                        pass->getVertexProgramParameters());
3709
3710                                                if (retPass == mShadowTextureCustomReceiverPass)
3711                                                {
3712                                                        // mark that we've overridden the standard
3713                                                        mShadowTextureReceiverVPDirty = true;
3714                                                }
3715                                        }
3716                                } // valid shadow fragment program
3717                        } // ori pass has fragment program
3718                       
3719                }// additive lighting
3720                else
3721                {
3722                        // need to keep spotlight fade etc
3723                        keepTUCount = retPass->getNumTextureUnitStates();
3724                }
3725
3726                // reset fragment program
3727                if (resetFragmentProgram)
3728                {
3729                        retPass->setFragmentProgram(StringUtil::BLANK);
3730                }
3731        // Remove any extra texture units
3732        while (retPass->getNumTextureUnitStates() > keepTUCount)
3733        {
3734            retPass->removeTextureUnitState(keepTUCount);
3735        }
3736
3737                // reset vertex program
3738                if (retPass->hasVertexProgram() && !pass->hasVertexProgram())
3739                {
3740                        // reset
3741                        retPass->setVertexProgram("");
3742
3743                        if (mShadowTextureReceiverVPDirty)
3744                        {
3745                                // reset
3746                                mShadowTextureCustomReceiverPass->setVertexProgram(
3747                                        mShadowTextureCustomReceiverVertexProgram);
3748                                if(mShadowTextureCustomReceiverPass->hasVertexProgram())
3749                                {
3750                                        mShadowTextureCustomReceiverPass->setVertexProgramParameters(
3751                                                mShadowTextureCustomReceiverVPParams);
3752
3753                                }
3754                                mShadowTextureReceiverVPDirty = false;
3755                        }
3756                }
3757
3758                retPass->_load();
3759
3760                return retPass;
3761        }
3762        else
3763        {
3764        return pass;
3765    }
3766
3767}
3768//---------------------------------------------------------------------
3769void SceneManager::renderShadowVolumesToStencil(const Light* light, const Camera* camera)
3770{
3771    // Get the shadow caster list
3772    const ShadowCasterList& casters = findShadowCastersForLight(light, camera);
3773    // Check there are some shadow casters to render
3774    if (casters.empty())
3775    {
3776        // No casters, just do nothing
3777        return;
3778    }
3779
3780    // Set up scissor test (point & spot lights only)
3781    bool scissored = false;
3782    if (light->getType() != Light::LT_DIRECTIONAL &&
3783        mDestRenderSystem->getCapabilities()->hasCapability(RSC_SCISSOR_TEST))
3784    {
3785        // Project the sphere onto the camera
3786        Real left, right, top, bottom;
3787        Sphere sphere(light->getDerivedPosition(), light->getAttenuationRange());
3788        if (camera->projectSphere(sphere, &left, &top, &right, &bottom))
3789        {
3790            scissored = true;
3791            // Turn normalised device coordinates into pixels
3792            int iLeft, iTop, iWidth, iHeight;
3793            mCurrentViewport->getActualDimensions(iLeft, iTop, iWidth, iHeight);
3794            size_t szLeft, szRight, szTop, szBottom;
3795
3796            szLeft = (size_t)(iLeft + ((left + 1) * 0.5 * iWidth));
3797            szRight = (size_t)(iLeft + ((right + 1) * 0.5 * iWidth));
3798            szTop = (size_t)(iTop + ((-top + 1) * 0.5 * iHeight));
3799            szBottom = (size_t)(iTop + ((-bottom + 1) * 0.5 * iHeight));
3800
3801            mDestRenderSystem->setScissorTest(true, szLeft, szTop, szRight, szBottom);
3802        }
3803    }
3804
3805    mDestRenderSystem->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
3806
3807    // Can we do a 2-sided stencil?
3808    bool stencil2sided = false;
3809    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_TWO_SIDED_STENCIL) &&
3810        mDestRenderSystem->getCapabilities()->hasCapability(RSC_STENCIL_WRAP))
3811    {
3812        // enable
3813        stencil2sided = true;
3814    }
3815
3816    // Do we have access to vertex programs?
3817    bool extrudeInSoftware = true;
3818    bool finiteExtrude = !mShadowUseInfiniteFarPlane ||
3819        !mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE);
3820    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
3821    {
3822        extrudeInSoftware = false;
3823        // attach the appropriate extrusion vertex program
3824        // Note we never unset it because support for vertex programs is constant
3825        mShadowStencilPass->setVertexProgram(
3826            ShadowVolumeExtrudeProgram::getProgramName(light->getType(), finiteExtrude, false)
3827            , false);
3828        // Set params
3829        if (finiteExtrude)
3830        {
3831            mShadowStencilPass->setVertexProgramParameters(mFiniteExtrusionParams);
3832        }
3833        else
3834        {
3835            mShadowStencilPass->setVertexProgramParameters(mInfiniteExtrusionParams);
3836        }
3837        if (mDebugShadows)
3838        {
3839            mShadowDebugPass->setVertexProgram(
3840                ShadowVolumeExtrudeProgram::getProgramName(light->getType(), finiteExtrude, true)
3841                , false);
3842            // Set params
3843            if (finiteExtrude)
3844            {
3845                mShadowDebugPass->setVertexProgramParameters(mFiniteExtrusionParams);
3846            }
3847            else
3848            {
3849                mShadowDebugPass->setVertexProgramParameters(mInfiniteExtrusionParams);
3850            }
3851        }
3852
3853        mDestRenderSystem->bindGpuProgram(mShadowStencilPass->getVertexProgram()->_getBindingDelegate());
3854
3855    }
3856    else
3857    {
3858        mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
3859    }
3860
3861    // Add light to internal list for use in render call
3862    LightList lightList;
3863    // const_cast is forgiveable here since we pass this const
3864    lightList.push_back(const_cast<Light*>(light));
3865
3866    // Turn off colour writing and depth writing
3867    mDestRenderSystem->_setColourBufferWriteEnabled(false, false, false, false);
3868        mDestRenderSystem->_disableTextureUnitsFrom(0);
3869    mDestRenderSystem->_setDepthBufferParams(true, false, CMPF_LESS);
3870    mDestRenderSystem->setStencilCheckEnabled(true);
3871
3872    // Calculate extrusion distance
3873    // Use direction light extrusion distance now, just form optimize code
3874    // generate a little, point/spot light will up to date later
3875    Real extrudeDist = mShadowDirLightExtrudeDist;
3876
3877    // Figure out the near clip volume
3878    const PlaneBoundedVolume& nearClipVol =
3879        light->_getNearClipVolume(camera);
3880
3881    // Now iterate over the casters and render
3882    ShadowCasterList::const_iterator si, siend;
3883    siend = casters.end();
3884
3885
3886        // Now iterate over the casters and render
3887        for (si = casters.begin(); si != siend; ++si)
3888        {
3889        ShadowCaster* caster = *si;
3890                bool zfailAlgo = camera->isCustomNearClipPlaneEnabled();
3891                unsigned long flags = 0;
3892
3893        if (light->getType() != Light::LT_DIRECTIONAL)
3894        {
3895            extrudeDist = caster->getPointExtrusionDistance(light);
3896        }
3897
3898        if (!extrudeInSoftware && !finiteExtrude)
3899        {
3900            // hardware extrusion, to infinity (and beyond!)
3901            flags |= SRF_EXTRUDE_TO_INFINITY;
3902        }
3903
3904                // Determine whether zfail is required
3905        if (nearClipVol.intersects(caster->getWorldBoundingBox()))
3906        {
3907            // We use zfail for this object only because zfail
3908                // compatible with zpass algorithm
3909                        zfailAlgo = true;
3910            // We need to include the light and / or dark cap
3911            // But only if they will be visible
3912            if(camera->isVisible(caster->getLightCapBounds()))
3913            {
3914                flags |= SRF_INCLUDE_LIGHT_CAP;
3915            }
3916                        // zfail needs dark cap
3917                        // UNLESS directional lights using hardware extrusion to infinity
3918                        // since that extrudes to a single point
3919                        if(!((flags & SRF_EXTRUDE_TO_INFINITY) &&
3920                                light->getType() == Light::LT_DIRECTIONAL) &&
3921                                camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
3922                        {
3923                                flags |= SRF_INCLUDE_DARK_CAP;
3924                        }
3925        }
3926                else
3927                {
3928                        // In zpass we need a dark cap if
3929                        // 1: infinite extrusion on point/spotlight sources in modulative shadows
3930                        //    mode, since otherwise in areas where there is no depth (skybox)
3931                        //    the infinitely projected volume will leave a dark band
3932                        // 2: finite extrusion on any light source since glancing angles
3933                        //    can peek through the end and shadow objects behind incorrectly
3934                        if ((flags & SRF_EXTRUDE_TO_INFINITY) &&
3935                                light->getType() != Light::LT_DIRECTIONAL &&
3936                                isShadowTechniqueModulative() &&
3937                                camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
3938                        {
3939                                flags |= SRF_INCLUDE_DARK_CAP;
3940                        }
3941                        else if (!(flags & SRF_EXTRUDE_TO_INFINITY) &&
3942                                camera->isVisible(caster->getDarkCapBounds(*light, extrudeDist)))
3943                        {
3944                                flags |= SRF_INCLUDE_DARK_CAP;
3945                        }
3946
3947                }
3948
3949        // Get shadow renderables                       
3950        ShadowCaster::ShadowRenderableListIterator iShadowRenderables =
3951            caster->getShadowVolumeRenderableIterator(mShadowTechnique,
3952            light, &mShadowIndexBuffer, extrudeInSoftware,
3953            extrudeDist, flags);
3954
3955        // Render a shadow volume here
3956        //  - if we have 2-sided stencil, one render with no culling
3957        //  - otherwise, 2 renders, one with each culling method and invert the ops
3958        setShadowVolumeStencilState(false, zfailAlgo, stencil2sided);
3959        renderShadowVolumeObjects(iShadowRenderables, mShadowStencilPass, &lightList, flags,
3960            false, zfailAlgo, stencil2sided);
3961        if (!stencil2sided)
3962        {
3963            // Second pass
3964            setShadowVolumeStencilState(true, zfailAlgo, false);
3965            renderShadowVolumeObjects(iShadowRenderables, mShadowStencilPass, &lightList, flags,
3966                true, zfailAlgo, false);
3967        }
3968
3969        // Do we need to render a debug shadow marker?
3970        if (mDebugShadows)
3971        {
3972            // reset stencil & colour ops
3973            mDestRenderSystem->setStencilBufferParams();
3974            mShadowDebugPass->getTextureUnitState(0)->
3975                setColourOperationEx(LBX_MODULATE, LBS_MANUAL, LBS_CURRENT,
3976                zfailAlgo ? ColourValue(0.7, 0.0, 0.2) : ColourValue(0.0, 0.7, 0.2));
3977            _setPass(mShadowDebugPass);
3978            renderShadowVolumeObjects(iShadowRenderables, mShadowDebugPass, &lightList, flags,
3979                true, false, false);
3980            mDestRenderSystem->_setColourBufferWriteEnabled(false, false, false, false);
3981            mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
3982        }
3983    }
3984
3985    // revert colour write state
3986    mDestRenderSystem->_setColourBufferWriteEnabled(true, true, true, true);
3987    // revert depth state
3988    mDestRenderSystem->_setDepthBufferParams();
3989
3990    mDestRenderSystem->setStencilCheckEnabled(false);
3991
3992    mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
3993
3994    if (scissored)
3995    {
3996        // disable scissor test
3997        mDestRenderSystem->setScissorTest(false);
3998    }
3999
4000}
4001//---------------------------------------------------------------------
4002void SceneManager::renderShadowVolumeObjects(ShadowCaster::ShadowRenderableListIterator iShadowRenderables,
4003                                             Pass* pass,
4004                                             const LightList *manualLightList,
4005                                             unsigned long flags,
4006                                             bool secondpass, bool zfail, bool twosided)
4007{
4008    // ----- SHADOW VOLUME LOOP -----
4009    // Render all shadow renderables with same stencil operations
4010    while (iShadowRenderables.hasMoreElements())
4011    {
4012        ShadowRenderable* sr = iShadowRenderables.getNext();
4013
4014        // omit hidden renderables
4015        if (sr->isVisible())
4016        {
4017            // render volume, including dark and (maybe) light caps
4018            renderSingleObject(sr, pass, false, manualLightList);
4019
4020            // optionally render separate light cap
4021            if (sr->isLightCapSeparate() && (flags & SRF_INCLUDE_LIGHT_CAP))
4022            {
4023                ShadowRenderable* lightCap = sr->getLightCapRenderable();
4024                assert(lightCap && "Shadow renderable is missing a separate light cap renderable!");
4025
4026                // We must take care with light caps when we could 'see' the back facing
4027                // triangles directly:
4028                //   1. The front facing light caps must render as always fail depth
4029                //      check to avoid 'depth fighting'.
4030                //   2. The back facing light caps must use normal depth function to
4031                //      avoid break the standard depth check
4032                //
4033                // TODO:
4034                //   1. Separate light caps rendering doesn't need for the 'closed'
4035                //      mesh that never touch the near plane, because in this instance,
4036                //      we couldn't 'see' any back facing triangles directly. The
4037                //      'closed' mesh must determinate by edge list builder.
4038                //   2. There still exists 'depth fighting' bug with coplane triangles
4039                //      that has opposite facing. This usually occur when use two side
4040                //      material in the modeling tools and the model exporting tools
4041                //      exporting double triangles to represent this model. This bug
4042                //      can't fixed in GPU only, there must has extra work on edge list
4043                //      builder and shadow volume generater to fix it.
4044                //
4045                if (twosided)
4046                {
4047                    // select back facing light caps to render
4048                    mDestRenderSystem->_setCullingMode(CULL_ANTICLOCKWISE);
4049                    // use normal depth function for back facing light caps
4050                    renderSingleObject(lightCap, pass, false, manualLightList);
4051
4052                    // select front facing light caps to render
4053                    mDestRenderSystem->_setCullingMode(CULL_CLOCKWISE);
4054                    // must always fail depth check for front facing light caps
4055                    mDestRenderSystem->_setDepthBufferFunction(CMPF_ALWAYS_FAIL);
4056                    renderSingleObject(lightCap, pass, false, manualLightList);
4057
4058                    // reset depth function
4059                    mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
4060                    // reset culling mode
4061                    mDestRenderSystem->_setCullingMode(CULL_NONE);
4062                }
4063                else if ((secondpass || zfail) && !(secondpass && zfail))
4064                {
4065                    // use normal depth function for back facing light caps
4066                    renderSingleObject(lightCap, pass, false, manualLightList);
4067                }
4068                else
4069                {
4070                    // must always fail depth check for front facing light caps
4071                    mDestRenderSystem->_setDepthBufferFunction(CMPF_ALWAYS_FAIL);
4072                    renderSingleObject(lightCap, pass, false, manualLightList);
4073
4074                    // reset depth function
4075                    mDestRenderSystem->_setDepthBufferFunction(CMPF_LESS);
4076                }
4077            }
4078        }
4079    }
4080}
4081//---------------------------------------------------------------------
4082void SceneManager::setShadowVolumeStencilState(bool secondpass, bool zfail, bool twosided)
4083{
4084    // Determinate the best stencil operation
4085    StencilOperation incrOp, decrOp;
4086    if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_STENCIL_WRAP))
4087    {
4088        incrOp = SOP_INCREMENT_WRAP;
4089        decrOp = SOP_DECREMENT_WRAP;
4090    }
4091    else
4092    {
4093        incrOp = SOP_INCREMENT;
4094        decrOp = SOP_DECREMENT;
4095    }
4096
4097    // First pass, do front faces if zpass
4098    // Second pass, do back faces if zpass
4099    // Invert if zfail
4100    // this is to ensure we always increment before decrement
4101    // When two-sided stencil, always pass front face stencil
4102    // operation parameters and the inverse of them will happen
4103    // for back faces
4104    if ( !twosided && ((secondpass || zfail) && !(secondpass && zfail)) )
4105    {
4106        mDestRenderSystem->_setCullingMode(
4107            twosided? CULL_NONE : CULL_ANTICLOCKWISE);
4108        mDestRenderSystem->setStencilBufferParams(
4109            CMPF_ALWAYS_PASS, // always pass stencil check
4110            0, // no ref value (no compare)
4111            0xFFFFFFFF, // no mask
4112            SOP_KEEP, // stencil test will never fail
4113            zfail ? incrOp : SOP_KEEP, // back face depth fail
4114            zfail ? SOP_KEEP : decrOp, // back face pass
4115            twosided
4116            );
4117    }
4118    else
4119    {
4120        mDestRenderSystem->_setCullingMode(
4121            twosided? CULL_NONE : CULL_CLOCKWISE);
4122        mDestRenderSystem->setStencilBufferParams(
4123            CMPF_ALWAYS_PASS, // always pass stencil check
4124            0, // no ref value (no compare)
4125            0xFFFFFFFF, // no mask
4126            SOP_KEEP, // stencil test will never fail
4127            zfail ? decrOp : SOP_KEEP, // front face depth fail
4128            zfail ? SOP_KEEP : incrOp, // front face pass
4129            twosided
4130            );
4131    }
4132}
4133//---------------------------------------------------------------------
4134void SceneManager::setShadowColour(const ColourValue& colour)
4135{
4136    mShadowColour = colour;
4137
4138    // Change shadow material setting only when it's prepared,
4139    // otherwise, it'll set up while preparing shadow materials.
4140    if (mShadowModulativePass)
4141    {
4142        mShadowModulativePass->getTextureUnitState(0)->setColourOperationEx(
4143            LBX_MODULATE, LBS_MANUAL, LBS_CURRENT, colour);
4144    }
4145}
4146//---------------------------------------------------------------------
4147const ColourValue& SceneManager::getShadowColour(void) const
4148{
4149    return mShadowColour;
4150}
4151//---------------------------------------------------------------------
4152void SceneManager::setShadowFarDistance(Real distance)
4153{
4154    mShadowFarDist = distance;
4155    mShadowFarDistSquared = distance * distance;
4156}
4157//---------------------------------------------------------------------
4158void SceneManager::setShadowDirectionalLightExtrusionDistance(Real dist)
4159{
4160    mShadowDirLightExtrudeDist = dist;
4161}
4162//---------------------------------------------------------------------
4163Real SceneManager::getShadowDirectionalLightExtrusionDistance(void) const
4164{
4165    return mShadowDirLightExtrudeDist;
4166}
4167//---------------------------------------------------------------------
4168void SceneManager::setShadowIndexBufferSize(size_t size)
4169{
4170    if (!mShadowIndexBuffer.isNull() && size != mShadowIndexBufferSize)
4171    {
4172        // re-create shadow buffer with new size
4173        mShadowIndexBuffer = HardwareBufferManager::getSingleton().
4174            createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
4175            size,
4176            HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,
4177            false);
4178    }
4179    mShadowIndexBufferSize = size;
4180}
4181//---------------------------------------------------------------------
4182void SceneManager::setShadowTextureSize(unsigned short size)
4183{
4184    // possibly recreate
4185    createShadowTextures(size, mShadowTextureCount, mShadowTextureFormat);
4186    mShadowTextureSize = size;
4187}
4188//---------------------------------------------------------------------
4189void SceneManager::setShadowTextureCount(unsigned short count)
4190{
4191    // possibly recreate
4192    createShadowTextures(mShadowTextureSize, count, mShadowTextureFormat);
4193    mShadowTextureCount = count;
4194}
4195//---------------------------------------------------------------------
4196void SceneManager::setShadowTexturePixelFormat(PixelFormat fmt)
4197{
4198        // possibly recreate
4199        createShadowTextures(mShadowTextureSize, mShadowTextureCount, fmt);
4200        mShadowTextureFormat = fmt;
4201}
4202//---------------------------------------------------------------------
4203void SceneManager::setShadowTextureSettings(unsigned short size,
4204        unsigned short count, PixelFormat fmt)
4205{
4206    if (!mShadowTextures.empty() &&
4207        (count != mShadowTextureCount ||
4208        size != mShadowTextureSize ||
4209                fmt != mShadowTextureFormat))
4210    {
4211        // recreate
4212        createShadowTextures(size, count, fmt);
4213    }
4214    mShadowTextureCount = count;
4215    mShadowTextureSize = size;
4216        mShadowTextureFormat = fmt;
4217}
4218//---------------------------------------------------------------------
4219void SceneManager::setShadowTextureSelfShadow(bool selfShadow)
4220{
4221        mShadowTextureSelfShadow = selfShadow;
4222        if (isShadowTechniqueTextureBased())
4223                getRenderQueue()->setShadowCastersCannotBeReceivers(!selfShadow);
4224}
4225//---------------------------------------------------------------------
4226void SceneManager::setShadowTextureCasterMaterial(const String& name)
4227{
4228        if (name.empty())
4229        {
4230                mShadowTextureCustomCasterPass = 0;
4231        }
4232        else
4233        {
4234                MaterialPtr mat = MaterialManager::getSingleton().getByName(name);
4235                if (mat.isNull())
4236                {
4237                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
4238                                "Cannot locate material called '" + name + "'",
4239                                "SceneManager::setShadowTextureCasterMaterial");
4240                }
4241                mat->load();
4242                mShadowTextureCustomCasterPass = mat->getBestTechnique()->getPass(0);
4243                if (mShadowTextureCustomCasterPass->hasVertexProgram())
4244                {
4245                        // Save vertex program and params in case we have to swap them out
4246                        mShadowTextureCustomCasterVertexProgram =
4247                                mShadowTextureCustomCasterPass->getVertexProgramName();
4248                        mShadowTextureCustomCasterVPParams =
4249                                mShadowTextureCustomCasterPass->getVertexProgramParameters();
4250                        mShadowTextureCasterVPDirty = false;
4251
4252                }
4253        }
4254}
4255//---------------------------------------------------------------------
4256void SceneManager::setShadowTextureReceiverMaterial(const String& name)
4257{
4258        if (name.empty())
4259        {
4260                mShadowTextureCustomReceiverPass = 0;
4261        }
4262        else
4263        {
4264                MaterialPtr mat = MaterialManager::getSingleton().getByName(name);
4265                if (mat.isNull())
4266                {
4267                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
4268                                "Cannot locate material called '" + name + "'",
4269                                "SceneManager::setShadowTextureReceiverMaterial");
4270                }
4271                mat->load();
4272                mShadowTextureCustomReceiverPass = mat->getBestTechnique()->getPass(0);
4273                if (mShadowTextureCustomReceiverPass->hasVertexProgram())
4274                {
4275                        // Save vertex program and params in case we have to swap them out
4276                        mShadowTextureCustomReceiverVertexProgram =
4277                                mShadowTextureCustomReceiverPass->getVertexProgramName();
4278                        mShadowTextureCustomReceiverVPParams =
4279                                mShadowTextureCustomReceiverPass->getVertexProgramParameters();
4280                        mShadowTextureReceiverVPDirty = false;
4281
4282                }
4283        }
4284}
4285//---------------------------------------------------------------------
4286void SceneManager::createShadowTextures(unsigned short size,
4287        unsigned short count, PixelFormat fmt)
4288{
4289    static const String baseName = "Ogre/ShadowTexture";
4290
4291    if (!isShadowTechniqueTextureBased() ||
4292        !mShadowTextures.empty() &&
4293        count == mShadowTextureCount &&
4294        size == mShadowTextureSize &&
4295                fmt == mShadowTextureFormat)
4296    {
4297        // no change
4298        return;
4299    }
4300
4301
4302    // destroy existing
4303        destroyShadowTextures();
4304
4305    // Recreate shadow textures
4306    for (unsigned short t = 0; t < count; ++t)
4307    {
4308        String targName = baseName + StringConverter::toString(t);
4309        String camName = baseName + "Cam" + StringConverter::toString(t);
4310        String matName = baseName + "Mat" + StringConverter::toString(t);
4311
4312                // try to get existing texture first, since we share these between
4313                // potentially multiple SMs
4314                TexturePtr shadowTex = TextureManager::getSingleton().getByName(targName);
4315                if (shadowTex.isNull())
4316                {
4317                        shadowTex = TextureManager::getSingleton().createManual(
4318                                targName,
4319                                ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
4320                                TEX_TYPE_2D, size, size, 0, mShadowTextureFormat,
4321                                TU_RENDERTARGET);
4322                }
4323                else if (shadowTex->getWidth() != size
4324                        || shadowTex->getHeight() != size
4325                        || shadowTex->getFormat() != mShadowTextureFormat)
4326                {
4327                        StringUtil::StrStreamType s;
4328                        s << "Warning: shadow texture #" << t << " is shared "
4329                                << "between scene managers but the sizes / formats "
4330                                << "do not agree. Consider rationalising your scene manager "
4331                                << "shadow texture settings.";
4332                        LogManager::getSingleton().logMessage(s.str());
4333                }
4334                               
4335                // Ensure texture loaded
4336                shadowTex->load();
4337
4338                RenderTexture *shadowRTT = shadowTex->getBuffer()->getRenderTarget();
4339
4340                // Create camera for this texture, but note that we have to rebind
4341                // in prepareShadowTextures to coexist with multiple SMs
4342                Camera* cam = createCamera(camName);
4343        cam->setAspectRatio(1.0f);
4344                // Don't use rendering distance for light cameras; we don't want shadows
4345                // for visible objects disappearing, especially for directional lights
4346                cam->setUseRenderingDistance(false);
4347                mShadowTextureCameras.push_back(cam);
4348               
4349        // Create a viewport, if not there already
4350                if (shadowRTT->getNumViewports() == 0)
4351                {
4352                        // Note camera assignment is transient when multiple SMs
4353                        Viewport *v = shadowRTT->addViewport(cam);
4354                        v->setClearEveryFrame(true);
4355                        // remove overlays
4356                        v->setOverlaysEnabled(false);
4357                }
4358               
4359        // Don't update automatically - we'll do it when required
4360        shadowRTT->setAutoUpdated(false);
4361       
4362        mShadowTextures.push_back(shadowTex);
4363
4364
4365        // Also create corresponding Material used for rendering this shadow
4366        MaterialPtr mat = MaterialManager::getSingleton().getByName(matName);
4367        if (mat.isNull())
4368        {
4369            mat = MaterialManager::getSingleton().create(
4370                matName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
4371        }
4372        else
4373        {
4374            mat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
4375        }
4376        // create texture unit referring to render target texture
4377        TextureUnitState* texUnit =
4378            mat->getTechnique(0)->getPass(0)->createTextureUnitState(targName);
4379        // set projective based on camera
4380        texUnit->setProjectiveTexturing(true, cam);
4381        texUnit->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
4382        mat->touch();
4383
4384    }
4385}
4386//---------------------------------------------------------------------
4387void SceneManager::destroyShadowTextures(void)
4388{
4389    ShadowTextureList::iterator i, iend;
4390    ShadowTextureCameraList::iterator ci;
4391    iend = mShadowTextures.end();
4392    ci = mShadowTextureCameras.begin();
4393    for (i = mShadowTextures.begin(); i != iend; ++i, ++ci)
4394    {
4395        TexturePtr &shadowTex = *i;
4396                // If the reference count on this texture is 1 over the resource system
4397                // overhead, then we can remove the texture
4398                if (shadowTex.useCount() ==
4399                        ResourceGroupManager::RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS + 1)
4400                {
4401                // destroy texture
4402            TextureManager::getSingleton().remove(shadowTex->getName());
4403                }
4404
4405                // Always destroy camera since they are local to this SM
4406                destroyCamera(*ci);
4407    }
4408    mShadowTextures.clear();
4409        mShadowTextureCameras.clear();
4410
4411       
4412}
4413//---------------------------------------------------------------------
4414void SceneManager::prepareShadowTextures(Camera* cam, Viewport* vp)
4415{
4416    // Set the illumination stage, prevents recursive calls
4417    IlluminationRenderStage savedStage = mIlluminationStage;
4418    mIlluminationStage = IRS_RENDER_TO_TEXTURE;
4419
4420    // Determine far shadow distance
4421    Real shadowDist = mShadowFarDist;
4422    if (!shadowDist)
4423    {
4424        // need a shadow distance, make one up
4425        shadowDist = cam->getNearClipDistance() * 300;
4426    }
4427        Real shadowOffset = shadowDist * mShadowTextureOffset;
4428    // Precalculate fading info
4429        Real shadowEnd = shadowDist + shadowOffset;
4430        Real fadeStart = shadowEnd * mShadowTextureFadeStart;
4431        Real fadeEnd = shadowEnd * mShadowTextureFadeEnd;
4432        // set fogging to hide the shadow edge
4433        // Additive lighting needs fading too (directional)
4434        mShadowReceiverPass->setFog(true, FOG_LINEAR, ColourValue::White,
4435                0, fadeStart, fadeEnd);
4436
4437    // Iterate over the lights we've found, max out at the limit of light textures
4438
4439    LightList::iterator i, iend;
4440    ShadowTextureList::iterator si, siend;
4441        ShadowTextureCameraList::iterator ci;
4442    iend = mLightsAffectingFrustum.end();
4443    siend = mShadowTextures.end();
4444        ci = mShadowTextureCameras.begin();
4445    for (i = mLightsAffectingFrustum.begin(), si = mShadowTextures.begin();
4446        i != iend && si != siend; ++i)
4447    {
4448        Light* light = *i;
4449
4450        // Skip non-shadowing lights
4451        if (!light->getCastShadows())
4452            continue;
4453
4454                TexturePtr &shadowTex = *si;
4455        RenderTarget *shadowRTT = shadowTex->getBuffer()->getRenderTarget();
4456        Viewport *shadowView = shadowRTT->getViewport(0);
4457        Camera *texCam = *ci;
4458                // rebind camera, incase another SM in use which has switched to its cam
4459                shadowView->setCamera(texCam);
4460       
4461        Vector3 pos, dir;
4462
4463        // Directional lights
4464        if (light->getType() == Light::LT_DIRECTIONAL)
4465        {
4466            // set up the shadow texture
4467            // Set ortho projection
4468            texCam->setProjectionType(PT_ORTHOGRAPHIC);
4469            // set easy FOV and near dist so that texture covers far dist
4470            texCam->setFOVy(Degree(90));
4471            texCam->setNearClipDistance(shadowDist);
4472
4473            // Calculate look at position
4474            // We want to look at a spot shadowOffset away from near plane
4475            // 0.5 is a litle too close for angles
4476            Vector3 target = cam->getDerivedPosition() +
4477                (cam->getDerivedDirection() * shadowOffset);
4478
4479            // Calculate direction, which same as directional light direction
4480            dir = - light->getDerivedDirection(); // backwards since point down -z
4481            dir.normalise();
4482
4483            // Calculate position
4484            // We want to be in the -ve direction of the light direction
4485            // far enough to project for the dir light extrusion distance
4486            pos = target + dir * mShadowDirLightExtrudeDist;
4487
4488            // Round local x/y position based on a world-space texel; this helps to reduce
4489            // jittering caused by the projection moving with the camera
4490            // Viewport is 2 * near clip distance across (90 degree fov)
4491            Real worldTexelSize = (texCam->getNearClipDistance() * 20) / mShadowTextureSize;
4492            pos.x -= fmod(pos.x, worldTexelSize);
4493            pos.y -= fmod(pos.y, worldTexelSize);
4494            pos.z -= fmod(pos.z, worldTexelSize);
4495        }
4496        // Spotlight
4497        else if (light->getType() == Light::LT_SPOTLIGHT)
4498        {
4499            // Set perspective projection
4500            texCam->setProjectionType(PT_PERSPECTIVE);
4501            // set FOV slightly larger than the spotlight range to ensure coverage
4502            texCam->setFOVy(light->getSpotlightOuterAngle()*1.2);
4503            // set near clip the same as main camera, since they are likely
4504            // to both reflect the nature of the scene
4505            texCam->setNearClipDistance(cam->getNearClipDistance());
4506
4507            // Calculate position, which same as spotlight position
4508            pos = light->getDerivedPosition();
4509
4510            // Calculate direction, which same as spotlight direction
4511            dir = - light->getDerivedDirection(); // backwards since point down -z
4512            dir.normalise();
4513        }
4514        // Point light
4515        else
4516        {
4517            // Set perspective projection
4518            texCam->setProjectionType(PT_PERSPECTIVE);
4519            // Use 120 degree FOV for point light to ensure coverage more area
4520            texCam->setFOVy(Degree(120));
4521            // set near clip the same as main camera, since they are likely
4522            // to both reflect the nature of the scene
4523            texCam->setNearClipDistance(cam->getNearClipDistance());
4524
4525            // Calculate look at position
4526            // We want to look at a spot shadowOffset away from near plane
4527            // 0.5 is a litle too close for angles
4528            Vector3 target = cam->getDerivedPosition() +
4529                (cam->getDerivedDirection() * shadowOffset);
4530
4531            // Calculate position, which same as point light position
4532            pos = light->getDerivedPosition();
4533
4534            dir = (pos - target); // backwards since point down -z
4535            dir.normalise();
4536        }
4537
4538        // Finally set position
4539        texCam->setPosition(pos);
4540
4541        // Calculate orientation based on direction calculated above
4542        /*
4543        // Next section (camera oriented shadow map) abandoned
4544        // Always point in the same direction, if we don't do this then
4545        // we get 'shadow swimming' as camera rotates
4546        // As it is, we get swimming on moving but this is less noticeable
4547
4548        // calculate up vector, we want it aligned with cam direction
4549        Vector3 up = cam->getDerivedDirection();
4550        // Check it's not coincident with dir
4551        if (up.dotProduct(dir) >= 1.0f)
4552        {
4553        // Use camera up
4554        up = cam->getUp();
4555        }
4556        */
4557        Vector3 up = Vector3::UNIT_Y;
4558        // Check it's not coincident with dir
4559        if (Math::Abs(up.dotProduct(dir)) >= 1.0f)
4560        {
4561            // Use camera up
4562            up = Vector3::UNIT_Z;
4563        }
4564        // cross twice to rederive, only direction is unaltered
4565        Vector3 left = dir.crossProduct(up);
4566        left.normalise();
4567        up = dir.crossProduct(left);
4568        up.normalise();
4569        // Derive quaternion from axes
4570        Quaternion q;
4571        q.FromAxes(left, up, dir);
4572        texCam->setOrientation(q);
4573
4574        // Setup background colour
4575        shadowView->setBackgroundColour(ColourValue::White);
4576
4577                // Fire shadow caster update, callee can alter camera settings
4578                fireShadowTexturesPreCaster(light, texCam);
4579
4580        // Update target
4581        shadowRTT->update();
4582
4583        ++si; // next shadow texture
4584                ++ci; // next camera
4585    }
4586    // Set the illumination stage, prevents recursive calls
4587    mIlluminationStage = savedStage;
4588
4589        fireShadowTexturesUpdated(
4590                std::min(mLightsAffectingFrustum.size(), mShadowTextures.size()));
4591}
4592//---------------------------------------------------------------------
4593StaticGeometry* SceneManager::createStaticGeometry(const String& name)
4594{
4595        // Check not existing
4596        if (mStaticGeometryList.find(name) != mStaticGeometryList.end())
4597        {
4598                OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
4599                        "StaticGeometry with name '" + name + "' already exists!",
4600                        "SceneManager::createStaticGeometry");
4601        }
4602        StaticGeometry* ret = new StaticGeometry(this, name);
4603        mStaticGeometryList[name] = ret;
4604        return ret;
4605}
4606//---------------------------------------------------------------------
4607StaticGeometry* SceneManager::getStaticGeometry(const String& name) const
4608{
4609        StaticGeometryList::const_iterator i = mStaticGeometryList.find(name);
4610        if (i == mStaticGeometryList.end())
4611        {
4612                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
4613                        "StaticGeometry with name '" + name + "' not found",
4614                        "SceneManager::createStaticGeometry");
4615        }
4616        return i->second;
4617}
4618//---------------------------------------------------------------------
4619void SceneManager::destroyStaticGeometry(StaticGeometry* geom)
4620{
4621        destroyStaticGeometry(geom->getName());
4622}
4623//---------------------------------------------------------------------
4624void SceneManager::destroyStaticGeometry(const String& name)
4625{
4626        StaticGeometryList::iterator i = mStaticGeometryList.find(name);
4627        if (i != mStaticGeometryList.end())
4628        {
4629                delete i->second;
4630                mStaticGeometryList.erase(i);
4631        }
4632
4633}
4634//---------------------------------------------------------------------
4635void SceneManager::destroyAllStaticGeometry(void)
4636{
4637        StaticGeometryList::iterator i, iend;
4638        iend = mStaticGeometryList.end();
4639        for (i = mStaticGeometryList.begin(); i != iend; ++i)
4640        {
4641                delete i->second;
4642        }
4643        mStaticGeometryList.clear();
4644}
4645//---------------------------------------------------------------------
4646AxisAlignedBoxSceneQuery*
4647SceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
4648{
4649    DefaultAxisAlignedBoxSceneQuery* q = new DefaultAxisAlignedBoxSceneQuery(this);
4650    q->setBox(box);
4651    q->setQueryMask(mask);
4652    return q;
4653}
4654//---------------------------------------------------------------------
4655SphereSceneQuery*
4656SceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
4657{
4658    DefaultSphereSceneQuery* q = new DefaultSphereSceneQuery(this);
4659    q->setSphere(sphere);
4660    q->setQueryMask(mask);
4661    return q;
4662}
4663//---------------------------------------------------------------------
4664PlaneBoundedVolumeListSceneQuery*
4665SceneManager::createPlaneBoundedVolumeQuery(const PlaneBoundedVolumeList& volumes,
4666                                            unsigned long mask)
4667{
4668    DefaultPlaneBoundedVolumeListSceneQuery* q = new DefaultPlaneBoundedVolumeListSceneQuery(this);
4669    q->setVolumes(volumes);
4670    q->setQueryMask(mask);
4671    return q;
4672}
4673
4674//---------------------------------------------------------------------
4675RaySceneQuery*
4676SceneManager::createRayQuery(const Ray& ray, unsigned long mask)
4677{
4678    DefaultRaySceneQuery* q = new DefaultRaySceneQuery(this);
4679    q->setRay(ray);
4680    q->setQueryMask(mask);
4681    return q;
4682}
4683//---------------------------------------------------------------------
4684IntersectionSceneQuery*
4685SceneManager::createIntersectionQuery(unsigned long mask)
4686{
4687
4688    DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
4689    q->setQueryMask(mask);
4690    return q;
4691}
4692//---------------------------------------------------------------------
4693void SceneManager::destroyQuery(SceneQuery* query)
4694{
4695    delete query;
4696}
4697//---------------------------------------------------------------------
4698SceneManager::MovableObjectMap*
4699SceneManager::getMovableObjectMap(const String& typeName)
4700{
4701        MovableObjectCollectionMap::iterator i =
4702                mMovableObjectCollectionMap.find(typeName);
4703        if (i == mMovableObjectCollectionMap.end())
4704        {
4705                // create
4706                MovableObjectMap* newMap = new MovableObjectMap();
4707                mMovableObjectCollectionMap[typeName] = newMap;
4708                return newMap;
4709        }
4710        else
4711        {
4712                return i->second;
4713        }
4714}
4715//---------------------------------------------------------------------
4716MovableObject* SceneManager::createMovableObject(const String& name,
4717        const String& typeName, const NameValuePairList* params)
4718{
4719        MovableObjectFactory* factory =
4720                Root::getSingleton().getMovableObjectFactory(typeName);
4721        // Check for duplicate names
4722        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4723
4724        if (objectMap->find(name) != objectMap->end())
4725        {
4726                OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
4727                        "An object of type '" + typeName + "' with name '" + name
4728                        + "' already exists.",
4729                        "SceneManager::createMovableObject");
4730        }
4731
4732        MovableObject* newObj = factory->createInstance(name, this, params);
4733        (*objectMap)[name] = newObj;
4734
4735        return newObj;
4736
4737}
4738//---------------------------------------------------------------------
4739void SceneManager::destroyMovableObject(const String& name, const String& typeName)
4740{
4741        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4742        MovableObjectFactory* factory =
4743                Root::getSingleton().getMovableObjectFactory(typeName);
4744
4745        MovableObjectMap::iterator mi = objectMap->find(name);
4746        if (mi != objectMap->end())
4747        {
4748                factory->destroyInstance(mi->second);
4749                objectMap->erase(mi);
4750        }
4751
4752}
4753//---------------------------------------------------------------------
4754void SceneManager::destroyAllMovableObjectsByType(const String& typeName)
4755{
4756        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4757        MovableObjectFactory* factory =
4758                Root::getSingleton().getMovableObjectFactory(typeName);
4759        MovableObjectMap::iterator i = objectMap->begin();
4760        for (; i != objectMap->end(); ++i)
4761        {
4762                // Only destroy our own
4763                if (i->second->_getManager() == this)
4764                {
4765                        factory->destroyInstance(i->second);
4766                }
4767        }
4768        objectMap->clear();
4769
4770}
4771//---------------------------------------------------------------------
4772void SceneManager::destroyAllMovableObjects(void)
4773{
4774        MovableObjectCollectionMap::iterator ci = mMovableObjectCollectionMap.begin();
4775
4776        for(;ci != mMovableObjectCollectionMap.end(); ++ci)
4777        {
4778                if (Root::getSingleton().hasMovableObjectFactory(ci->first))
4779                {
4780                        // Only destroy if we have a factory instance; otherwise must be injected
4781                        MovableObjectFactory* factory =
4782                                Root::getSingleton().getMovableObjectFactory(ci->first);
4783                        MovableObjectMap::iterator i = ci->second->begin();
4784                        for (; i != ci->second->end(); ++i)
4785                        {
4786                                if (i->second->_getManager() == this)
4787                                {
4788                                        factory->destroyInstance(i->second);
4789                                }
4790                        }
4791                }
4792                ci->second->clear();
4793        }
4794
4795}
4796//---------------------------------------------------------------------
4797MovableObject* SceneManager::getMovableObject(const String& name, const String& typeName)
4798{
4799       
4800        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4801        MovableObjectMap::iterator mi = objectMap->find(name);
4802        if (mi == objectMap->end())
4803        {
4804                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
4805                        "Object named '" + name + "' does not exist.",
4806                        "SceneManager::getMovableObject");
4807        }
4808        return mi->second;
4809       
4810}
4811//---------------------------------------------------------------------
4812SceneManager::MovableObjectIterator
4813SceneManager::getMovableObjectIterator(const String& typeName)
4814{
4815        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4816
4817        return MovableObjectIterator(objectMap->begin(), objectMap->end());
4818}
4819//---------------------------------------------------------------------
4820void SceneManager::destroyMovableObject(MovableObject* m)
4821{
4822        destroyMovableObject(m->getName(), m->getMovableType());
4823}
4824//---------------------------------------------------------------------
4825void SceneManager::injectMovableObject(MovableObject* m)
4826{
4827        MovableObjectMap* objectMap = getMovableObjectMap(m->getMovableType());
4828        (*objectMap)[m->getName()] = m;
4829}
4830//---------------------------------------------------------------------
4831void SceneManager::extractMovableObject(const String& name, const String& typeName)
4832{
4833        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4834        MovableObjectMap::iterator mi = objectMap->find(name);
4835        if (mi != objectMap->end())
4836        {
4837                // no delete
4838                objectMap->erase(mi);
4839        }
4840
4841}
4842//---------------------------------------------------------------------
4843void SceneManager::extractMovableObject(MovableObject* m)
4844{
4845        extractMovableObject(m->getName(), m->getMovableType());
4846}
4847//---------------------------------------------------------------------
4848void SceneManager::extractAllMovableObjectsByType(const String& typeName)
4849{
4850        MovableObjectMap* objectMap = getMovableObjectMap(typeName);
4851        // no deletion
4852        objectMap->clear();
4853
4854}
4855//---------------------------------------------------------------------
4856void SceneManager::_injectRenderWithPass(Pass *pass, Renderable *rend)
4857{
4858        // render something as if it came from the current queue
4859    const Pass *usedPass = _setPass(pass);
4860    renderSingleObject(rend, usedPass, false);
4861}
4862//---------------------------------------------------------------------
4863RenderSystem *SceneManager::getDestinationRenderSystem()
4864{
4865        return mDestRenderSystem;
4866}
4867
4868#ifdef GTP_VISIBILITY_MODIFIED_OGRE
4869//-----------------------------------------------------------------------
4870const Pass* SceneManager::setPassWrapper(Pass* pass)
4871{
4872        return _setPass(pass);
4873}
4874//-----------------------------------------------------------------------
4875void SceneManager::_renderSceneNode(Camera *cam, SceneNode *node, const int leavePassesInQueue)
4876{
4877        // delete previously rendered objects from renderqueue
4878        _deleteRenderedQueueGroups(leavePassesInQueue);
4879
4880        node->_findVisibleObjects(cam, getRenderQueue(), false, mDisplayNodes, false);
4881        SceneManager::_renderVisibleObjects();
4882}
4883//-----------------------------------------------------------------------
4884void SceneManager::_deleteRenderedQueueGroups(const int leavePassesInQueue)
4885{       
4886        RenderQueue::QueueGroupIterator queueIt =
4887                getRenderQueue()->_getQueueGroupIterator();
4888
4889        //-- find currently processed queue groups and delelete them from render queue
4890        while (queueIt.hasMoreElements())
4891        {
4892                RenderQueueGroupID qId = static_cast<RenderQueueGroupID>(queueIt.peekNextKey());
4893                RenderQueueGroup* pGroup = queueIt.getNext();
4894
4895                if (isRenderQueueToBeProcessed(qId))
4896                {
4897                        pGroup->clear(leavePassesInQueue);
4898                }
4899        }       
4900
4901        // Now trigger the pending pass updates
4902        // Pass::processPendingPassUpdates();
4903}
4904
4905//-----------------------------------------------------------------------
4906/*void SceneManager::renderEntity(Entity *ent)
4907{
4908        int n = (int)ent->getNumSubEntities();
4909
4910        for (int i = 0; i < n; ++i)
4911        {
4912                Pass *pass = setPass(ent->getSubEntity(i)->getTechnique()->getPass(0));
4913
4914                _renderSingleObject(ent->getSubEntity(i), pass, false);
4915        }
4916}*/
4917//-----------------------------------------------------------------------
4918void SceneManager::_renderMovableObject(MovableObject *mov, const int leavePassesInQueue)
4919{
4920        // delete previously rendered objects from renderqueue
4921        _deleteRenderedQueueGroups(leavePassesInQueue);
4922
4923        mov->_updateRenderQueue(getRenderQueue());
4924        SceneManager::_renderVisibleObjects();
4925}
4926//-----------------------------------------------------------------------
4927void SceneManager::_renderSingleRenderable(Renderable *rend)
4928{
4929        Pass *pass = rend->getTechnique()->getPass(0);
4930        _setPass(pass);
4931        renderSingleObject(rend, pass, false);
4932}
4933//-----------------------------------------------------------------------
4934void SceneManager::useRenderableViewProjModeWrapper(Renderable* pRend)
4935{
4936        useRenderableViewProjMode(pRend);
4937}
4938#endif //GTP_VISIBILITY_MODIFIED_OGRE
4939
4940}
Note: See TracBrowser for help on using the repository browser.