source: GTP/trunk/Lib/Illum/IllumModule/OgreIllumModule/src/OgreIlluminationManager.cpp @ 2200

Revision 2200, 18.2 KB checked in by szirmay, 17 years ago (diff)
Line 
1#include "OgreIlluminationManager.h"
2#include "OgreParticleSystemRenderer.h"
3#include "OgreBillboardParticleRenderer.h"
4#include "SpriteParticleRenderer.h"
5#include "OgrePMEntryPointMapRenderingRun.h"
6#include "OgrePMWeightComputeRenderingRun.h"
7
8OgreIlluminationManager* OgreIlluminationManager::instance = NULL;
9
10Vector3 sortfrom;
11RenderingRunType sortType;
12
13class sortFromVector
14{
15public:
16   bool operator()(OgreSharedRuns* a, OgreSharedRuns* b)
17   {
18           float dist1 = (a->getRootPosition() - sortfrom).length();
19           float dist2 = (b->getRootPosition() - sortfrom).length();
20
21           return dist1 > dist2;
22   }
23};
24
25class sortFromVectorWithRunType
26{
27public:
28   bool operator()(OgreSharedRuns* a, OgreSharedRuns* b)
29   {
30           float dist1 = (a->getRootPosition(sortType) - sortfrom).length();
31           float dist2 = (b->getRootPosition(sortType) - sortfrom).length();
32
33           return dist1 > dist2;
34   }
35};
36
37
38class VisibleFinderVisitor : public QueuedRenderableVisitor
39{
40private:
41        std::vector<const Renderable*>* visibleObjects;
42public:
43   
44        VisibleFinderVisitor(std::vector<const Renderable*>* visibleObjectsVector)
45        {
46                this->visibleObjects = visibleObjectsVector;
47        }
48
49        void visit(const Renderable* r)
50        {               
51                OgreTechniqueGroup* tg = (OgreTechniqueGroup*) r->getRenderTechniqueGroup();
52               
53                if(tg != 0)
54                {
55                        tg->validateSharedRuns();
56                        visibleObjects->push_back(r);
57                }
58        }
59        bool visit(const Pass* p)       
60        {
61                return true;
62        }
63        void visit(const RenderablePass* rp)
64        {
65                Renderable* r = rp->renderable;
66
67                OgreTechniqueGroup* tg = (OgreTechniqueGroup*) r->getRenderTechniqueGroup();
68               
69                if(tg != 0)
70                {
71                        tg->validateSharedRuns();
72                        visibleObjects->push_back(r);
73                }       
74        }
75
76};
77
78OgreIlluminationManager::OgreIlluminationManager()
79{
80        visitor = new VisibleFinderVisitor(&visibleObjects);
81        maxRad = 400;
82        focusingMapSize = 32;
83        shadowMapSize = 512;
84        phaseTextureSize = 256;
85        useLISPSM = false;
86        useVSM = false;
87        blurSM = false;
88        focusingSM = true;
89        shadowMapMaterialName = "GTP/Basic/Distance_NormalizedCCW";
90        areaLightRadius = 0.1;
91
92        for(int i = 0; i < RUN_TYPE_COUNT; i++)
93        {
94                maxRads[(RenderingRunType)i] = (float) maxRad;
95        }
96
97        //register rendertechnique factories
98        OgreColorCubeMapRenderTechniqueFactory* colorcube = new OgreColorCubeMapRenderTechniqueFactory();
99                addRenderTechniqueFactory(colorcube);
100        OgreDistanceCubeMapRenderTechniqueFactory* distcube = new OgreDistanceCubeMapRenderTechniqueFactory();
101                addRenderTechniqueFactory(distcube);
102        OgreConvoledCubeMapRenderTechniqueFactory* convcube = new OgreConvoledCubeMapRenderTechniqueFactory();
103                addRenderTechniqueFactory(convcube);
104        OgreCausticCasterRenderTechniqueFactory* caucast = new OgreCausticCasterRenderTechniqueFactory();
105                addRenderTechniqueFactory(caucast);
106        OgreCausticRecieverRenderTechniqueFactory* caurec = new OgreCausticRecieverRenderTechniqueFactory();
107                addRenderTechniqueFactory(caurec);
108        OgreDepthShadowRecieverRenderTechniqueFactory* dsrec = new OgreDepthShadowRecieverRenderTechniqueFactory();
109                addRenderTechniqueFactory(dsrec);
110        OgreSBBRenderTechniqueFactory* sbb = new OgreSBBRenderTechniqueFactory();
111                addRenderTechniqueFactory(sbb);
112        OgreFireRenderTechniqueFactory* fire = new OgreFireRenderTechniqueFactory();
113                addRenderTechniqueFactory(fire);
114        OgreHierarchicalParticleSystemTechniqueFactory* HPSF = new OgreHierarchicalParticleSystemTechniqueFactory();
115                addRenderTechniqueFactory(HPSF);
116        OgreIllumVolumeRenderTechniqueFactory* illumVolume = new OgreIllumVolumeRenderTechniqueFactory();
117                addRenderTechniqueFactory(illumVolume);
118        OgrePathMapRenderTechniqueFactory* pathmap = new OgrePathMapRenderTechniqueFactory();
119        addRenderTechniqueFactory(pathmap);
120}
121
122OgreIlluminationManager::~OgreIlluminationManager()
123{
124       
125}
126
127OgreIlluminationManager& OgreIlluminationManager::getSingleton()
128{
129        if(instance == NULL)
130                instance= new OgreIlluminationManager();
131
132        return *instance;
133}
134
135void OgreIlluminationManager::fillVisibleList(  RenderQueue * rq )
136{
137        visibleObjects.clear();
138
139        RenderQueue::QueueGroupIterator queueIt = rq->_getQueueGroupIterator();
140   
141    while (queueIt.hasMoreElements())
142    {
143        RenderQueueGroup* pGroup = queueIt.getNext();
144               
145        RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
146
147                while (groupIt.hasMoreElements())
148                {
149                        RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
150                        const QueuedRenderableCollection& solids = pPriorityGrp->getSolidsBasic();
151                        const QueuedRenderableCollection& transparents = pPriorityGrp->getTransparents();
152                                                                       
153                        solids.acceptVisitor(visitor, QueuedRenderableCollection::OM_PASS_GROUP);
154                        transparents.acceptVisitor(visitor, QueuedRenderableCollection::OM_SORT_ASCENDING);             
155                }                       
156    }
157
158        rq->clear();   
159}
160
161BillboardSet* OgreIlluminationManager::findRenderableInParticleSystem(ParticleSystem* system)
162{
163        ParticleSystemRenderer* renderer = system->getRenderer();
164       
165        const String rendererType = renderer->getType();
166        if(rendererType == "billboard")
167        {
168                BillboardSet* bbSet = ((BillboardParticleRenderer*) renderer)->getBillboardSet();
169                return bbSet;
170        }
171
172        if(rendererType == "sprite")
173        {
174                BillboardSet* bbSet = ((SpriteParticleRenderer*) renderer)->getSpriteSet();
175                return bbSet;
176        }
177       
178        OGRE_EXCEPT(0, "Unsupported particle renderable type", "OgreIlluminationManager::findRenderableInParticleSystem");
179
180        return NULL;
181}
182
183void OgreIlluminationManager::initTechniques(Entity* e)
184{
185        if( e->getParentSceneNode() == 0 )//Entity not attached
186                return;
187
188        OgreSharedRuns* sharedruns = 0;
189       
190        for(unsigned int s = 0; s < e->getNumSubEntities(); s++)
191        {
192                SubEntity* sube = e->getSubEntity(s);
193
194                Material* mat = sube->getMaterial().getPointer();
195               
196                OgreRenderable* rend = 0;       
197                OgreTechniqueGroup* group = 0;
198
199                for(unsigned int t = 0 ; t < mat->getNumTechniques() ; t++)
200                {
201                        Technique* tech = mat->getTechnique(t);
202
203                        for(unsigned int p = 0; p< tech->getNumPasses(); p++)
204                        {
205                                Pass* pass = tech->getPass(p);
206
207                                std::vector<IllumTechniqueParams*>& techniques = pass->getIllumTechniques();
208                                if( techniques.size() > 0)
209                                {
210                                        if(rend == 0)
211                                        {
212                                                rend = new OgreRenderable(e, s);
213                                                group = new OgreTechniqueGroup();
214                                                sube->setRenderTechniqueGroup(group);                                                   
215                                               
216                                                if( sharedruns == 0)
217                                                {                                                                       
218                                                        sharedruns  = new OgreSharedRuns();
219                                                        addSharedRuns(sharedruns);
220                                                }
221
222                                                group->addSharedRun(sharedruns);
223                                                sharedruns->addRenderable(rend);
224                                                sharedruns->updateBounds();
225                                        }
226                                        String newMaterialName = mat->getName() + "_clone_" + rend->getName();
227                                        Material* newMat = mat->clone(newMaterialName).getPointer();
228                                        rend->setMaterialName(newMaterialName);
229                                        mat = sube->getMaterial().getPointer();
230                                        break;
231                                }
232                        }
233                }
234
235       
236                for(unsigned int t = 0 ; t < mat->getNumTechniques() ; t++)
237                {
238                        Technique* tech = mat->getTechnique(t);
239
240                        for(unsigned int p = 0; p< tech->getNumPasses(); p++)
241                        {
242                                Pass* pass = tech->getPass(p);
243
244                                std::vector<IllumTechniqueParams*>& techniques = pass->getIllumTechniques();
245                                std::vector<IllumTechniqueParams*>::iterator i = techniques.begin();
246                                std::vector<IllumTechniqueParams*>::iterator iend = techniques.end();
247                               
248                                while( i != iend)
249                                {
250                                        IllumTechniqueParams* params = *i;
251                                        createTechnique(params, pass, rend, sharedruns);
252
253                                        i++;
254                                }
255                        }
256                }
257        }
258
259               
260}
261
262
263void OgreIlluminationManager::initTechniques(BillboardSet* bbs, ParticleSystem* sys)
264{
265        if( bbs->getParentSceneNode() == 0 )//billboardset not attached
266                return;
267
268        OgreSharedRuns* sharedruns = 0;
269
270        Material* mat = bbs->getMaterial().getPointer();
271       
272        OgreRenderable* rend = 0;       
273        OgreTechniqueGroup* group = 0;
274
275        for(unsigned int t = 0 ; t < mat->getNumTechniques() ; t++)
276        {
277                Technique* tech = mat->getTechnique(t);
278
279                for(unsigned int p = 0; p< tech->getNumPasses(); p++)
280                {
281                        Pass* pass = tech->getPass(p);
282
283                        std::vector<IllumTechniqueParams*>& techniques = pass->getIllumTechniques();
284                        std::vector<IllumTechniqueParams*>::iterator i = techniques.begin();
285                        std::vector<IllumTechniqueParams*>::iterator iend = techniques.end();
286                       
287                        while( i != iend)
288                        {
289                                IllumTechniqueParams* params = *i;
290                               
291                                if(rend == 0)
292                                {
293                                        rend = new OgreRenderable(bbs, sys);
294                                        group = new OgreTechniqueGroup();
295                                        bbs->setRenderTechniqueGroup(group);                                                   
296                                       
297                                        if( sharedruns == 0)
298                                        {                                                                       
299                                                sharedruns  = new OgreSharedRuns();
300                                                addSharedRuns(sharedruns);
301                                        }
302
303                                        group->addSharedRun(sharedruns);
304                                        sharedruns->addRenderable(rend);
305                                        sharedruns->updateBounds();
306                                }
307                               
308                                createTechnique(params, pass, rend, sharedruns);
309
310                                i++;
311                        }
312                }
313        }
314                       
315}
316
317void OgreIlluminationManager::initTechniques()
318{
319        {
320                //Entities
321                SceneManager::MovableObjectIterator it = Root::getSingleton()._getCurrentSceneManager()
322                                                                                                        ->getMovableObjectIterator("Entity");
323                while(it.hasMoreElements())
324                {
325                        MovableObject* o = it.getNext();
326                        Entity* e = (Entity*) o;
327               
328                        initTechniques(e);
329                }
330        }
331        {
332                //ParticleSystems
333                SceneManager::MovableObjectIterator it = Root::getSingleton()._getCurrentSceneManager()
334                                                                                                        ->getMovableObjectIterator("ParticleSystem");
335                while(it.hasMoreElements())
336                {
337                        MovableObject* o = it.getNext();
338                        ParticleSystem* psys = (ParticleSystem*) o;
339                       
340                        try
341                        {
342                         BillboardSet* bbset = findRenderableInParticleSystem(psys);
343                         bbset->setMaterialName(psys->getMaterialName());
344                         initTechniques(bbset, psys);
345                        }
346                        catch( ... )
347                        {
348                                //unsupported particle renderer, skip init
349                        }
350                }
351        }
352}
353
354void OgreIlluminationManager::createTechnique(IllumTechniqueParams* params, Pass* pass, OgreRenderable* rend, OgreSharedRuns* sRuns)
355{
356        std::list<RenderTechniqueFactory*>::iterator it = techniqueFactories.begin();
357        std::list<RenderTechniqueFactory*>::iterator itend = techniqueFactories.end();
358
359        OgreTechniqueGroup* group = (OgreTechniqueGroup*) rend->getRenderable()->getRenderTechniqueGroup();     
360       
361                       
362        while(it != itend)
363        {
364                RenderTechniqueFactory* factory = *it;
365               
366               
367                if(factory->isType(params->getTypeName()))
368                {
369                       
370                        RenderTechnique* newTechnique = factory->createInstance(params,
371                                                                                                                                        pass,
372                                                                                                                                        rend,
373                                                                                                                                        group );
374
375                        group->addRenderTechnique(newTechnique);
376                       
377                }
378
379                it++;
380        }
381}
382void OgreIlluminationManager::preAllUpdates()
383{
384        std::vector<UpdateListener*>::iterator it = updateListeners.begin();
385        std::vector<UpdateListener*>::iterator itend = updateListeners.end();
386
387        while(it != itend)
388        {
389                UpdateListener* l = *it;
390                l->preAllUpdates();
391                it++;
392        }
393}
394
395void OgreIlluminationManager::postAllUpdates()
396{
397        std::vector<UpdateListener*>::iterator it = updateListeners.begin();
398        std::vector<UpdateListener*>::iterator itend = updateListeners.end();
399
400        while(it != itend)
401        {
402                UpdateListener* l = *it;
403                l->postAllUpdates();
404                it++;
405        }
406}
407
408void OgreIlluminationManager::update(unsigned long frameNumber, RenderTarget* rt)
409{
410
411        RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
412        SceneManager* sceneManager = Root::getSingleton()._getCurrentSceneManager();
413       
414        for(unsigned short i = 0; i<rt->getNumViewports();i++)
415        {
416                //find visible objects from the camera
417                RenderQueue* rq = sceneManager->getRenderQueue();
418                rq->clear();
419                RenderQueue::QueueGroupIterator groupIter = rq->_getQueueGroupIterator();
420                while (groupIter.hasMoreElements())
421                {
422                        RenderQueueGroup* g = groupIter.getNext();
423                        //g->addOrganisationMode(QueuedRenderableCollection::OM_SORT_ASCENDING);
424                        g->defaultOrganisationMode();
425                }
426               
427                //sceneManager->_findVisibleObjectsOC(rt->getViewport(i)->getCamera(), rt->getViewport(i), false, false, false);
428                sceneManager->_findVisibleObjects(rt->getViewport(i)->getCamera(), false);
429               
430                fillVisibleList(rq);   
431
432//              int l = visibleObjects.size(); //debug
433               
434                joinSharedRuns();
435
436//              int ll = sharedRunRoots.size(); //debug
437
438                //update precomputings                         
439                std::vector<const Renderable*>::iterator iter = visibleObjects.begin();
440                const std::vector<const Renderable*>::iterator iend = visibleObjects.end();
441
442                preAllUpdates();
443
444                while(iter != iend)
445                {
446                        const Renderable* rend = *iter;
447                        OgreTechniqueGroup* techniqueGroup = (OgreTechniqueGroup*) rend->getRenderTechniqueGroup();
448                        if(techniqueGroup != 0)
449                        {
450                                techniqueGroup->update(frameNumber);
451                        }
452                        iter++;
453                }
454
455                postAllUpdates();
456        }
457}
458
459void OgreIlluminationManager::sharedRunSplit(SharedRuns* old, SharedRuns* new1, SharedRuns* new2)
460{
461        sharedRunRoots.remove(old);
462        sharedRunRoots.push_back(new1);
463        sharedRunRoots.push_back(new2);
464}
465
466void OgreIlluminationManager::sharedRunJoin(SharedRuns* old1, SharedRuns* old2, SharedRuns* newsr)
467{
468        sharedRunRoots.remove(old1);
469        sharedRunRoots.remove(old2);
470        sharedRunRoots.push_back(newsr);
471}
472
473void OgreIlluminationManager::joinSharedRuns()
474{
475        std::list<SharedRuns*>::iterator it1 = sharedRunRoots.begin();
476        std::list<SharedRuns*>::iterator itend = sharedRunRoots.end();
477
478        bool again = false;
479
480        while(it1 != itend)
481        {
482                std::list<SharedRuns*>::iterator it2 = sharedRunRoots.begin();         
483               
484                while(it2 != itend)
485                {
486                        if( it1 != it2 && OgreSharedRuns::canJoin(*it1, *it2))
487                        {
488                                SharedRuns* newruns = (*it1)->joinRuns(*it2);
489                                sharedRunJoin(*it1, *it2, newruns);
490                                again = true;
491                                break;
492                        }
493                        it2++;
494                }
495
496                if(again)
497                        break;         
498
499                it1++;
500        }
501        if(again)
502        joinSharedRuns();
503
504}
505
506void OgreIlluminationManager::addSharedRuns(SharedRuns* runs)
507{
508        sharedRunRoots.push_back(runs);
509}
510
511void OgreIlluminationManager::getNearestCausticCasters(Vector3 position, std::vector<OgreSharedRuns*>* nearestcasters, unsigned int maxCount)
512{
513        sortfrom = position;
514        std::vector<OgreSharedRuns*> allcasters;
515        //fill casters
516        std::list<SharedRuns*>::iterator it = sharedRunRoots.begin();
517        std::list<SharedRuns*>::iterator itend = sharedRunRoots.end();
518        while(it != itend)
519        {
520                OgreSharedRuns* sr = (OgreSharedRuns*) (*it);
521               
522                sr->findSharedRootsForType(ILLUMRUN_CAUSTIC_CUBEMAP, allcasters);
523               
524                it++;
525        }
526
527        //sort
528        std::stable_sort(allcasters.begin(), allcasters.end(), sortFromVector());
529
530        for(unsigned int i = 0; i < maxCount && i < allcasters.size(); i++)
531        {
532                nearestcasters->push_back(allcasters.at(i));
533        }
534}
535
536void OgreIlluminationManager::createGlobalRun(RenderingRunType runType)
537{
538        switch(runType)
539        {
540                case ILLUMRUN_SCENE_CAMERA_DEPTH:
541                if(globalSharedRuns.getRun(ILLUMRUN_SCENE_CAMERA_DEPTH) == 0)
542                {
543                        OgreSceneCameraDepthRenderingRun* run = new OgreSceneCameraDepthRenderingRun
544                                (&globalSharedRuns, "ILLUMMODULE_SCENE_CAMERA_DEPTH", mainViewport);
545                        globalSharedRuns.addRun(ILLUMRUN_SCENE_CAMERA_DEPTH, run);
546                }
547                case ILLUMRUN_FOCUSING_MAP:
548                if(globalSharedRuns.getRun(ILLUMRUN_FOCUSING_MAP) == 0)
549                {
550                        OgreFocusingMapRenderingRun* run  = new OgreFocusingMapRenderingRun(
551                                "LIGHT_FOCUSING_MAP",                           
552                                Matrix4::IDENTITY,
553                                focusingMapSize
554                                );
555                        globalSharedRuns.addRun(ILLUMRUN_FOCUSING_MAP, run);
556                       
557                }
558                case ILLUMRUN_PHASE_TEXTURE:
559                if(globalSharedRuns.getRun(ILLUMRUN_PHASE_TEXTURE) == 0)
560                {
561                        OgrePhaseTextureRenderingRun* run  = new OgrePhaseTextureRenderingRun(
562                                "PHASE_TEXTURE",                               
563                                phaseTextureSize,
564                                phaseTextureSize,
565                                "Phase_HenyeyGreenStein");
566                        globalSharedRuns.addRun(ILLUMRUN_PHASE_TEXTURE, run);                   
567                }
568                break;
569                case ILLUMRUN_PM_ENTRYPOINTMAP:
570                if(globalSharedRuns.getRun(ILLUMRUN_PM_ENTRYPOINTMAP) == 0)
571                {
572                        OgrePMEntryPointMapRenderingRun* run  = new OgrePMEntryPointMapRenderingRun(
573                                "PM_ENTRYPOINT_MAP");
574                        globalSharedRuns.addRun(ILLUMRUN_PM_ENTRYPOINTMAP, run);                       
575                }
576                break;
577        }
578}
579
580void OgreIlluminationManager::savePhaseTextureToFile(String filename)
581{
582        OgrePhaseTextureRenderingRun* r = (OgrePhaseTextureRenderingRun*)
583                globalSharedRuns.getRun(ILLUMRUN_PHASE_TEXTURE)->asOgreRenderingRun();
584        Texture* t = (Texture*) TextureManager::getSingleton().getByName(r->getPhaseTextureName()).getPointer();
585       
586        t->getBuffer()->getRenderTarget()->writeContentsToFile(filename);       
587}
588
589RenderingRun* OgreIlluminationManager::getGlobalRun(RenderingRunType runType)
590{
591        if(globalSharedRuns.getRun(runType) == 0)
592                createGlobalRun(runType);
593        return globalSharedRuns.getRun(runType);
594}
595
596GlobalUseRenderTarget* OgreIlluminationManager::getGlobalTarget(GlobalTargetType type)
597{
598        std::map<GlobalTargetType, GlobalUseRenderTarget*>::iterator it = globalTargets.find(type);
599       
600        if( it != globalTargets.end())
601                return (*it).second;
602
603        return 0;
604}
605
606void OgreIlluminationManager::addGlobalTarget(GlobalTargetType type, GlobalUseRenderTarget* target)
607{
608        globalTargets[type] = target; 
609}
610
611void OgreIlluminationManager::updateGlobalRun(RenderingRunType runType, unsigned long frameNum)
612{
613        globalSharedRuns.updateRun(runType, frameNum);
614}
615
616void OgreIlluminationManager::createPerLightRun(String lightName, RenderingRunType runType)
617{
618        OgreSharedRuns* runs = 0;
619       
620        if(perLightRuns.find(lightName) == perLightRuns.end())
621        {///create sharedruns
622                OgreSharedRuns* newruns = new OgreSharedRuns();
623                perLightRuns[lightName] = newruns;
624        }
625
626        runs = perLightRuns[lightName];
627
628    switch(runType)
629        {
630                case ILLUMRUN_DEPTH_SHADOWMAP:
631                if(runs->getRun(ILLUMRUN_DEPTH_SHADOWMAP) == 0)
632                {
633                        SceneManager* sm = Root::getSingleton()._getCurrentSceneManager();
634                        OgreDepthShadowMapRenderingRun* run  = new OgreDepthShadowMapRenderingRun(
635                                runs,
636                                lightName + "DEPTH_SHADOW_MAP",
637                                sm->getLight(lightName),
638                                shadowMapSize,
639                                shadowMapSize,
640                                shadowMapMaterialName //TODO
641                                );
642                        runs->addRun(ILLUMRUN_DEPTH_SHADOWMAP, run);
643                       
644                }               
645                break;
646                case ILLUMRUN_PM_WEIGHTMAP:
647                if(runs->getRun(ILLUMRUN_PM_WEIGHTMAP) == 0)
648                {
649                        SceneManager* sm = Root::getSingleton()._getCurrentSceneManager();
650                        OgrePMWeightComputeRenderingRun* run  = new OgrePMWeightComputeRenderingRun(                           
651                                lightName + "PM_WEIGHT_MAP",
652                                lightName);
653                        runs->addRun(ILLUMRUN_PM_WEIGHTMAP, run);                       
654                }               
655                break;
656        }       
657}
658
659RenderingRun* OgreIlluminationManager::getPerLightRun(String lightName, RenderingRunType runType)
660{
661        return perLightRuns[lightName]->getRun(runType);
662}
663
664void OgreIlluminationManager::updatePerLightRun(String lightName, RenderingRunType runType, unsigned long frameNum)
665{
666        perLightRuns[lightName]->updateRun(runType, frameNum);
667}
668
Note: See TracBrowser for help on using the repository browser.