Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OgreRenderQueueSortingGrouping.h

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright (c) 2000-2006 Torus Knot Software Ltd
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 
00024 You may alternatively use this source under the terms of a specific version of
00025 the OGRE Unrestricted License provided you have obtained such a license from
00026 Torus Knot Software Ltd.
00027 -----------------------------------------------------------------------------
00028 */
00029 #ifndef __RenderQueueSortingGrouping_H__
00030 #define __RenderQueueSortingGrouping_H__
00031 
00032 // Precompiler options
00033 #include "OgrePrerequisites.h"
00034 #include "OgreIteratorWrappers.h"
00035 #include "OgreMaterial.h"
00036 #include "OgreTechnique.h"
00037 #include "OgrePass.h"
00038 #include "OgreRadixSort.h"
00039 
00040 namespace Ogre {
00041 
00046     struct RenderablePass
00047     {
00049         Renderable* renderable;
00051         Pass* pass;
00052 
00053         RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {}
00054     };
00055 
00056 
00064     class _OgreExport QueuedRenderableVisitor
00065     {
00066     public:
00067         QueuedRenderableVisitor() {}
00068         virtual ~QueuedRenderableVisitor() {}
00069         
00076         virtual void visit(const RenderablePass* rp) = 0;
00077 
00078         /* When visiting a collection grouped by pass, this is
00079             called when the grouping pass changes.
00080         @remarks
00081             If this method is called, the RenderablePass visit 
00082             method will not be called for this collection. The 
00083             Renderable visit method will be called for each item
00084             underneath the pass grouping level.
00085         @returns True to continue, false to skip the Renderables underneath
00086         */
00087         virtual bool visit(const Pass* p) = 0;
00094         virtual void visit(const Renderable* r) = 0;
00095         
00096         
00097     };
00098 
00108     class _OgreExport QueuedRenderableCollection
00109     {
00110     public:
00119         enum OrganisationMode
00120         {
00122             OM_PASS_GROUP = 1,
00124             OM_SORT_DESCENDING = 2,
00128             OM_SORT_ASCENDING = 6
00129         };
00130 
00131     protected:
00133         struct PassGroupLess
00134         {
00135             bool _OgreExport operator()(const Pass* a, const Pass* b) const
00136             {
00137                 // Sort by passHash, which is pass, then texture unit changes
00138                 uint32 hasha = a->getHash();
00139                 uint32 hashb = b->getHash();
00140                 if (hasha == hashb)
00141                 {
00142                     // Must differentTransparentQueueItemLessiate by pointer incase 2 passes end up with the same hash
00143                     return a < b;
00144                 }
00145                 else
00146                 {
00147                     return hasha < hashb;
00148                 }
00149             }
00150         };
00152         struct DepthSortDescendingLess
00153         {
00154             const Camera* camera;
00155 
00156             DepthSortDescendingLess(const Camera* cam)
00157                 : camera(cam)
00158             {
00159             }
00160 
00161             bool _OgreExport operator()(const RenderablePass& a, const RenderablePass& b) const
00162             {
00163                 if (a.renderable == b.renderable)
00164                 {
00165                     // Same renderable, sort by pass hash
00166                     return a.pass->getHash() < b.pass->getHash();
00167                 }
00168                 else
00169                 {
00170                     // Different renderables, sort by depth
00171                     Real adepth = a.renderable->getSquaredViewDepth(camera);
00172                     Real bdepth = b.renderable->getSquaredViewDepth(camera);
00173                     if (adepth == bdepth)
00174                     {
00175                         // Must return deterministic result, doesn't matter what
00176                         return a.pass < b.pass;
00177                     }
00178                     else
00179                     {
00180                         // Sort DESCENDING by depth (ie far objects first)
00181                         return (adepth > bdepth);
00182                     }
00183                 }
00184 
00185             }
00186         };
00187 
00191         typedef std::vector<RenderablePass> RenderablePassList;
00192         typedef std::vector<Renderable*> RenderableList;
00194         typedef std::map<Pass*, RenderableList*, PassGroupLess> PassGroupRenderableMap;
00195 
00197         struct RadixSortFunctorPass
00198         {
00199             uint32 operator()(const RenderablePass& p) const
00200             {
00201                 return p.pass->getHash();
00202             }
00203         };
00204 
00206         static RadixSort<RenderablePassList, RenderablePass, uint32> msRadixSorter1;
00207 
00209         struct RadixSortFunctorDistance
00210         {
00211             const Camera* camera;
00212 
00213             RadixSortFunctorDistance(const Camera* cam)
00214                 : camera(cam)
00215             {
00216             }
00217 
00218             float operator()(const RenderablePass& p) const
00219             {
00220                 // Sort DESCENDING by depth (ie far objects first), use negative distance
00221                 // here because radix sorter always dealing with accessing sort
00222                 return static_cast<float>(- p.renderable->getSquaredViewDepth(camera));
00223             }
00224         };
00225 
00227         static RadixSort<RenderablePassList, RenderablePass, float> msRadixSorter2;
00228 
00230         uint8 mOrganisationMode;
00231 
00233         PassGroupRenderableMap mGrouped;
00235         RenderablePassList mSortedDescending;
00236 
00238         void acceptVisitorGrouped(QueuedRenderableVisitor* visitor) const;
00240         void acceptVisitorDescending(QueuedRenderableVisitor* visitor) const;
00242         void acceptVisitorAscending(QueuedRenderableVisitor* visitor) const;
00243 
00244     public:
00245         QueuedRenderableCollection();
00246         ~QueuedRenderableCollection();
00247 
00249         void clear(void);
00250 
00256         void removePassGroup(Pass* p);
00257         
00263         void resetOrganisationModes(void) 
00264         { 
00265             mOrganisationMode = 0; 
00266         }
00267         
00273         void addOrganisationMode(OrganisationMode om) 
00274         { 
00275             mOrganisationMode |= om; 
00276         }
00277 
00279         void addRenderable(Pass* pass, Renderable* rend);
00280         
00284         void sort(const Camera* cam);
00285 
00292         void acceptVisitor(QueuedRenderableVisitor* visitor, OrganisationMode om) const;
00293         
00294     };
00295 
00315     class _OgreExport RenderPriorityGroup
00316     {
00317     protected:
00318 
00320         RenderQueueGroup* mParent;
00321         bool mSplitPassesByLightingType;
00322         bool mSplitNoShadowPasses;
00323         bool mShadowCastersNotReceivers;
00325         QueuedRenderableCollection mSolidsBasic;
00327         QueuedRenderableCollection mSolidsDiffuseSpecular;
00329         QueuedRenderableCollection mSolidsDecal;
00331         QueuedRenderableCollection mSolidsNoShadowReceive;
00333         QueuedRenderableCollection mTransparents;
00334 
00336         void removePassEntry(Pass* p);
00337 
00339         void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap);
00341         void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend);
00343         void addTransparentRenderable(Technique* pTech, Renderable* rend);
00344 
00345     public:
00346         RenderPriorityGroup(RenderQueueGroup* parent, 
00347             bool splitPassesByLightingType,
00348             bool splitNoShadowPasses, 
00349             bool shadowCastersNotReceivers); 
00350            
00351         ~RenderPriorityGroup() { }
00352 
00357         const QueuedRenderableCollection& getSolidsBasic(void) const
00358         { return mSolidsBasic; }
00361         const QueuedRenderableCollection& getSolidsDiffuseSpecular(void) const
00362         { return mSolidsDiffuseSpecular; }
00365         const QueuedRenderableCollection& getSolidsDecal(void) const
00366         { return mSolidsDecal; }
00369         const QueuedRenderableCollection& getSolidsNoShadowReceive(void) const
00370         { return mSolidsNoShadowReceive; }
00372         const QueuedRenderableCollection& getTransparents(void) const
00373         { return mTransparents; }
00374 
00375 
00382         void resetOrganisationModes(void);
00383         
00390         void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om); 
00391 
00398         void defaultOrganisationMode(void); 
00399 
00401         void addRenderable(Renderable* pRend, Technique* pTech);
00402 
00405         void sort(const Camera* cam);
00406 
00409         void clear(void);
00410 
00414         void setSplitPassesByLightingType(bool split)
00415         {
00416             mSplitPassesByLightingType = split;
00417         }
00418 
00422         void setSplitNoShadowPasses(bool split)
00423         {
00424             mSplitNoShadowPasses = split;
00425         }
00426 
00430         void setShadowCastersCannotBeReceivers(bool ind)
00431         {
00432             mShadowCastersNotReceivers = ind;
00433         }
00434 
00435 
00436 
00437     };
00438 
00439 
00447     class _OgreExport RenderQueueGroup
00448     {
00449     public:
00450         typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
00451         typedef MapIterator<PriorityMap> PriorityMapIterator;
00452     protected:
00453         RenderQueue* mParent;
00454         bool mSplitPassesByLightingType;
00455         bool mSplitNoShadowPasses;
00456         bool mShadowCastersNotReceivers;
00458         PriorityMap mPriorityGroups;
00460         bool mShadowsEnabled;
00461 
00462 
00463     public:
00464         RenderQueueGroup(RenderQueue* parent,
00465             bool splitPassesByLightingType,
00466             bool splitNoShadowPasses,
00467             bool shadowCastersNotReceivers) 
00468             : mParent(parent)
00469             , mSplitPassesByLightingType(splitPassesByLightingType)
00470             , mSplitNoShadowPasses(splitNoShadowPasses)
00471             , mShadowCastersNotReceivers(shadowCastersNotReceivers)
00472             , mShadowsEnabled(true)
00473         {
00474         }
00475 
00476         ~RenderQueueGroup() {
00477             // destroy contents now
00478             PriorityMap::iterator i;
00479             for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
00480             {
00481                 delete i->second;
00482             }
00483         }
00484 
00486         PriorityMapIterator getIterator(void)
00487         {
00488             return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
00489         }
00490 
00492         void addRenderable(Renderable* pRend, Technique* pTech, ushort priority)
00493         {
00494             // Check if priority group is there
00495             PriorityMap::iterator i = mPriorityGroups.find(priority);
00496             RenderPriorityGroup* pPriorityGrp;
00497             if (i == mPriorityGroups.end())
00498             {
00499                 // Missing, create
00500                 pPriorityGrp = new RenderPriorityGroup(this, 
00501                     mSplitPassesByLightingType,
00502                     mSplitNoShadowPasses, 
00503                     mShadowCastersNotReceivers);
00504                 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
00505             }
00506             else
00507             {
00508                 pPriorityGrp = i->second;
00509             }
00510 
00511             // Add
00512             pPriorityGrp->addRenderable(pRend, pTech);
00513 
00514         }
00515 
00523         void clear(bool destroy = false)
00524         {
00525             PriorityMap::iterator i, iend;
00526             iend = mPriorityGroups.end();
00527             for (i = mPriorityGroups.begin(); i != iend; ++i)
00528             {
00529                 if (destroy)
00530                     delete i->second;
00531                 else
00532                     i->second->clear();
00533             }
00534 
00535             if (destroy)
00536                 mPriorityGroups.clear();
00537 
00538         }
00539 
00552         void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; }
00553 
00555         bool getShadowsEnabled(void) const { return mShadowsEnabled; }
00556 
00560         void setSplitPassesByLightingType(bool split)
00561         {
00562             mSplitPassesByLightingType = split;
00563             PriorityMap::iterator i, iend;
00564             iend = mPriorityGroups.end();
00565             for (i = mPriorityGroups.begin(); i != iend; ++i)
00566             {
00567                 i->second->setSplitPassesByLightingType(split);
00568             }
00569         }
00574         void setSplitNoShadowPasses(bool split)
00575         {
00576             mSplitNoShadowPasses = split;
00577             PriorityMap::iterator i, iend;
00578             iend = mPriorityGroups.end();
00579             for (i = mPriorityGroups.begin(); i != iend; ++i)
00580             {
00581                 i->second->setSplitNoShadowPasses(split);
00582             }
00583         }
00587         void setShadowCastersCannotBeReceivers(bool ind)
00588         {
00589             mShadowCastersNotReceivers = ind;
00590             PriorityMap::iterator i, iend;
00591             iend = mPriorityGroups.end();
00592             for (i = mPriorityGroups.begin(); i != iend; ++i)
00593             {
00594                 i->second->setShadowCastersCannotBeReceivers(ind);
00595             }
00596         }
00603         void resetOrganisationModes(void)
00604         {
00605             PriorityMap::iterator i, iend;
00606             iend = mPriorityGroups.end();
00607             for (i = mPriorityGroups.begin(); i != iend; ++i)
00608             {
00609                 i->second->resetOrganisationModes();
00610             }
00611         }
00612         
00619         void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om)
00620         {
00621             PriorityMap::iterator i, iend;
00622             iend = mPriorityGroups.end();
00623             for (i = mPriorityGroups.begin(); i != iend; ++i)
00624             {
00625                 i->second->addOrganisationMode(om);
00626             }
00627         }
00628 
00635         void defaultOrganisationMode(void)
00636         {
00637             PriorityMap::iterator i, iend;
00638             iend = mPriorityGroups.end();
00639             for (i = mPriorityGroups.begin(); i != iend; ++i)
00640             {
00641                 i->second->defaultOrganisationMode();
00642             }
00643         }
00644 
00645     };
00646 
00647 
00648 
00649 }
00650 
00651 #endif
00652 
00653 

Copyright © 2000-2005 by The OGRE Team
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Jun 10 10:35:49 2007