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

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