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

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

adding ogre 1.2 and dependencies

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