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

Revision 921, 169.5 KB checked in by mattausch, 18 years ago (diff)

added updates for visibility

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