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-2012 Torus Knot Software Ltd
00008 
00009 Permission is hereby granted, free of charge, to any person obtaining a copy
00010 of this software and associated documentation files (the "Software"), to deal
00011 in the Software without restriction, including without limitation the rights
00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00013 copies of the Software, and to permit persons to whom the Software is
00014 furnished to do so, subject to the following conditions:
00015 
00016 The above copyright notice and this permission notice shall be included in
00017 all copies or substantial portions of the Software.
00018 
00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00025 THE SOFTWARE.
00026 -----------------------------------------------------------------------------
00027 */
00028 #ifndef __RenderQueueSortingGrouping_H__
00029 #define __RenderQueueSortingGrouping_H__
00030 
00031 // Precompiler options
00032 #include "OgrePrerequisites.h"
00033 #include "OgreIteratorWrappers.h"
00034 #include "OgreMaterial.h"
00035 #include "OgreTechnique.h"
00036 #include "OgrePass.h"
00037 #include "OgreRadixSort.h"
00038 
00039 namespace Ogre {
00040 
00051     struct RenderablePass
00052     {
00054         Renderable* renderable;
00056         Pass* pass;
00057 
00058         RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {}
00059     };
00060 
00061 
00069     class _OgreExport QueuedRenderableVisitor
00070     {
00071     public:
00072         QueuedRenderableVisitor() {}
00073         virtual ~QueuedRenderableVisitor() {}
00074         
00081         virtual void visit(RenderablePass* rp) = 0;
00082 
00083         /* When visiting a collection grouped by pass, this is
00084             called when the grouping pass changes.
00085         @remarks
00086             If this method is called, the RenderablePass visit 
00087             method will not be called for this collection. The 
00088             Renderable visit method will be called for each item
00089             underneath the pass grouping level.
00090         @return True to continue, false to skip the Renderables underneath
00091         */
00092         virtual bool visit(const Pass* p) = 0;
00099         virtual void visit(Renderable* r) = 0;
00100         
00101         
00102     };
00103 
00113     class _OgreExport QueuedRenderableCollection : public RenderQueueAlloc
00114     {
00115     public:
00124         enum OrganisationMode
00125         {
00127             OM_PASS_GROUP = 1,
00129             OM_SORT_DESCENDING = 2,
00133             OM_SORT_ASCENDING = 6
00134         };
00135 
00136     protected:
00138         struct PassGroupLess
00139         {
00140             bool _OgreExport operator()(const Pass* a, const Pass* b) const
00141             {
00142                 // Sort by passHash, which is pass, then texture unit changes
00143                 uint32 hasha = a->getHash();
00144                 uint32 hashb = b->getHash();
00145                 if (hasha == hashb)
00146                 {
00147                     // Must differentTransparentQueueItemLessiate by pointer incase 2 passes end up with the same hash
00148                     return a < b;
00149                 }
00150                 else
00151                 {
00152                     return hasha < hashb;
00153                 }
00154             }
00155         };
00157         struct DepthSortDescendingLess
00158         {
00159             const Camera* camera;
00160 
00161             DepthSortDescendingLess(const Camera* cam)
00162                 : camera(cam)
00163             {
00164             }
00165 
00166             bool _OgreExport operator()(const RenderablePass& a, const RenderablePass& b) const
00167             {
00168                 if (a.renderable == b.renderable)
00169                 {
00170                     // Same renderable, sort by pass hash
00171                     return a.pass->getHash() < b.pass->getHash();
00172                 }
00173                 else
00174                 {
00175                     // Different renderables, sort by depth
00176                     Real adepth = a.renderable->getSquaredViewDepth(camera);
00177                     Real bdepth = b.renderable->getSquaredViewDepth(camera);
00178                     if (Math::RealEqual(adepth, bdepth))
00179                     {
00180                         // Must return deterministic result, doesn't matter what
00181                         return a.pass < b.pass;
00182                     }
00183                     else
00184                     {
00185                         // Sort DESCENDING by depth (i.e. far objects first)
00186                         return (adepth > bdepth);
00187                     }
00188                 }
00189 
00190             }
00191         };
00192 
00196         typedef vector<RenderablePass>::type RenderablePassList;
00197         typedef vector<Renderable*>::type RenderableList;
00199         typedef map<Pass*, RenderableList*, PassGroupLess>::type PassGroupRenderableMap;
00200 
00202         struct RadixSortFunctorPass
00203         {
00204             uint32 operator()(const RenderablePass& p) const
00205             {
00206                 return p.pass->getHash();
00207             }
00208         };
00209 
00211         static RadixSort<RenderablePassList, RenderablePass, uint32> msRadixSorter1;
00212 
00214         struct RadixSortFunctorDistance
00215         {
00216             const Camera* camera;
00217 
00218             RadixSortFunctorDistance(const Camera* cam)
00219                 : camera(cam)
00220             {
00221             }
00222 
00223             float operator()(const RenderablePass& p) const
00224             {
00225                 // Sort DESCENDING by depth (ie far objects first), use negative distance
00226                 // here because radix sorter always dealing with accessing sort
00227                 return static_cast<float>(- p.renderable->getSquaredViewDepth(camera));
00228             }
00229         };
00230 
00232         static RadixSort<RenderablePassList, RenderablePass, float> msRadixSorter2;
00233 
00235         uint8 mOrganisationMode;
00236 
00238         PassGroupRenderableMap mGrouped;
00240         RenderablePassList mSortedDescending;
00241 
00243         void acceptVisitorGrouped(QueuedRenderableVisitor* visitor) const;
00245         void acceptVisitorDescending(QueuedRenderableVisitor* visitor) const;
00247         void acceptVisitorAscending(QueuedRenderableVisitor* visitor) const;
00248 
00249     public:
00250         QueuedRenderableCollection();
00251         ~QueuedRenderableCollection();
00252 
00254         void clear(void);
00255 
00261         void removePassGroup(Pass* p);
00262         
00268         void resetOrganisationModes(void) 
00269         { 
00270             mOrganisationMode = 0; 
00271         }
00272         
00278         void addOrganisationMode(OrganisationMode om) 
00279         { 
00280             mOrganisationMode |= om; 
00281         }
00282 
00284         void addRenderable(Pass* pass, Renderable* rend);
00285         
00289         void sort(const Camera* cam);
00290 
00297         void acceptVisitor(QueuedRenderableVisitor* visitor, OrganisationMode om) const;
00298 
00301         void merge( const QueuedRenderableCollection& rhs );
00302     };
00303 
00323     class _OgreExport RenderPriorityGroup : public RenderQueueAlloc
00324     {
00325     protected:
00326 
00328         RenderQueueGroup* mParent;
00329         bool mSplitPassesByLightingType;
00330         bool mSplitNoShadowPasses;
00331         bool mShadowCastersNotReceivers;
00333         QueuedRenderableCollection mSolidsBasic;
00335         QueuedRenderableCollection mSolidsDiffuseSpecular;
00337         QueuedRenderableCollection mSolidsDecal;
00339         QueuedRenderableCollection mSolidsNoShadowReceive;
00341         QueuedRenderableCollection mTransparentsUnsorted;
00343         QueuedRenderableCollection mTransparents;
00344 
00346         void removePassEntry(Pass* p);
00347 
00349         void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap);
00351         void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend);
00353         void addUnsortedTransparentRenderable(Technique* pTech, Renderable* rend);
00355         void addTransparentRenderable(Technique* pTech, Renderable* rend);
00356 
00357     public:
00358         RenderPriorityGroup(RenderQueueGroup* parent, 
00359             bool splitPassesByLightingType,
00360             bool splitNoShadowPasses, 
00361             bool shadowCastersNotReceivers); 
00362            
00363         ~RenderPriorityGroup() { }
00364 
00369         const QueuedRenderableCollection& getSolidsBasic(void) const
00370         { return mSolidsBasic; }
00373         const QueuedRenderableCollection& getSolidsDiffuseSpecular(void) const
00374         { return mSolidsDiffuseSpecular; }
00377         const QueuedRenderableCollection& getSolidsDecal(void) const
00378         { return mSolidsDecal; }
00381         const QueuedRenderableCollection& getSolidsNoShadowReceive(void) const
00382         { return mSolidsNoShadowReceive; }
00384         const QueuedRenderableCollection& getTransparentsUnsorted(void) const
00385         { return mTransparentsUnsorted; }
00387         const QueuedRenderableCollection& getTransparents(void) const
00388         { return mTransparents; }
00389 
00390 
00397         void resetOrganisationModes(void);
00398         
00405         void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om); 
00406 
00413         void defaultOrganisationMode(void); 
00414 
00416         void addRenderable(Renderable* pRend, Technique* pTech);
00417 
00420         void sort(const Camera* cam);
00421 
00424         void clear(void);
00425 
00429         void setSplitPassesByLightingType(bool split)
00430         {
00431             mSplitPassesByLightingType = split;
00432         }
00433 
00437         void setSplitNoShadowPasses(bool split)
00438         {
00439             mSplitNoShadowPasses = split;
00440         }
00441 
00445         void setShadowCastersCannotBeReceivers(bool ind)
00446         {
00447             mShadowCastersNotReceivers = ind;
00448         }
00449 
00452         void merge( const RenderPriorityGroup* rhs );
00453 
00454 
00455     };
00456 
00457 
00465     class _OgreExport RenderQueueGroup : public RenderQueueAlloc
00466     {
00467     public:
00468         typedef map<ushort, RenderPriorityGroup*, std::less<ushort> >::type PriorityMap;
00469         typedef MapIterator<PriorityMap> PriorityMapIterator;
00470         typedef ConstMapIterator<PriorityMap> ConstPriorityMapIterator;
00471     protected:
00472         RenderQueue* mParent;
00473         bool mSplitPassesByLightingType;
00474         bool mSplitNoShadowPasses;
00475         bool mShadowCastersNotReceivers;
00477         PriorityMap mPriorityGroups;
00479         bool mShadowsEnabled;
00481         uint8 mOrganisationMode;
00482 
00483 
00484     public:
00485         RenderQueueGroup(RenderQueue* parent,
00486             bool splitPassesByLightingType,
00487             bool splitNoShadowPasses,
00488             bool shadowCastersNotReceivers) 
00489             : mParent(parent)
00490             , mSplitPassesByLightingType(splitPassesByLightingType)
00491             , mSplitNoShadowPasses(splitNoShadowPasses)
00492             , mShadowCastersNotReceivers(shadowCastersNotReceivers)
00493             , mShadowsEnabled(true)
00494             , mOrganisationMode(0)
00495         {
00496         }
00497 
00498         ~RenderQueueGroup() {
00499             // destroy contents now
00500             PriorityMap::iterator i;
00501             for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
00502             {
00503                 OGRE_DELETE i->second;
00504             }
00505         }
00506 
00508         PriorityMapIterator getIterator(void)
00509         {
00510             return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
00511         }
00512 
00514         ConstPriorityMapIterator getIterator(void) const
00515         {
00516             return ConstPriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
00517         }
00518 
00520         void addRenderable(Renderable* pRend, Technique* pTech, ushort priority)
00521         {
00522             // Check if priority group is there
00523             PriorityMap::iterator i = mPriorityGroups.find(priority);
00524             RenderPriorityGroup* pPriorityGrp;
00525             if (i == mPriorityGroups.end())
00526             {
00527                 // Missing, create
00528                 pPriorityGrp = OGRE_NEW RenderPriorityGroup(this, 
00529                     mSplitPassesByLightingType,
00530                     mSplitNoShadowPasses, 
00531                     mShadowCastersNotReceivers);
00532                 if (mOrganisationMode)
00533                 {
00534                     pPriorityGrp->resetOrganisationModes();
00535                     pPriorityGrp->addOrganisationMode((QueuedRenderableCollection::OrganisationMode)mOrganisationMode);
00536                 }
00537 
00538                 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
00539             }
00540             else
00541             {
00542                 pPriorityGrp = i->second;
00543             }
00544 
00545             // Add
00546             pPriorityGrp->addRenderable(pRend, pTech);
00547 
00548         }
00549 
00557         void clear(bool destroy = false)
00558         {
00559             PriorityMap::iterator i, iend;
00560             iend = mPriorityGroups.end();
00561             for (i = mPriorityGroups.begin(); i != iend; ++i)
00562             {
00563                 if (destroy)
00564                     OGRE_DELETE i->second;
00565                 else
00566                     i->second->clear();
00567             }
00568 
00569             if (destroy)
00570                 mPriorityGroups.clear();
00571 
00572         }
00573 
00586         void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; }
00587 
00589         bool getShadowsEnabled(void) const { return mShadowsEnabled; }
00590 
00594         void setSplitPassesByLightingType(bool split)
00595         {
00596             mSplitPassesByLightingType = split;
00597             PriorityMap::iterator i, iend;
00598             iend = mPriorityGroups.end();
00599             for (i = mPriorityGroups.begin(); i != iend; ++i)
00600             {
00601                 i->second->setSplitPassesByLightingType(split);
00602             }
00603         }
00608         void setSplitNoShadowPasses(bool split)
00609         {
00610             mSplitNoShadowPasses = split;
00611             PriorityMap::iterator i, iend;
00612             iend = mPriorityGroups.end();
00613             for (i = mPriorityGroups.begin(); i != iend; ++i)
00614             {
00615                 i->second->setSplitNoShadowPasses(split);
00616             }
00617         }
00621         void setShadowCastersCannotBeReceivers(bool ind)
00622         {
00623             mShadowCastersNotReceivers = ind;
00624             PriorityMap::iterator i, iend;
00625             iend = mPriorityGroups.end();
00626             for (i = mPriorityGroups.begin(); i != iend; ++i)
00627             {
00628                 i->second->setShadowCastersCannotBeReceivers(ind);
00629             }
00630         }
00637         void resetOrganisationModes(void)
00638         {
00639             mOrganisationMode = 0;
00640 
00641             PriorityMap::iterator i, iend;
00642             iend = mPriorityGroups.end();
00643             for (i = mPriorityGroups.begin(); i != iend; ++i)
00644             {
00645                 i->second->resetOrganisationModes();
00646             }
00647         }
00648         
00655         void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om)
00656         {
00657             mOrganisationMode |= om;
00658 
00659             PriorityMap::iterator i, iend;
00660             iend = mPriorityGroups.end();
00661             for (i = mPriorityGroups.begin(); i != iend; ++i)
00662             {
00663                 i->second->addOrganisationMode(om);
00664             }
00665         }
00666 
00673         void defaultOrganisationMode(void)
00674         {
00675             mOrganisationMode = 0;
00676 
00677             PriorityMap::iterator i, iend;
00678             iend = mPriorityGroups.end();
00679             for (i = mPriorityGroups.begin(); i != iend; ++i)
00680             {
00681                 i->second->defaultOrganisationMode();
00682             }
00683         }
00684 
00687         void merge( const RenderQueueGroup* rhs )
00688         {
00689             ConstPriorityMapIterator it = rhs->getIterator();
00690 
00691             while( it.hasMoreElements() )
00692             {
00693                 ushort priority = it.peekNextKey();
00694                 RenderPriorityGroup* pSrcPriorityGrp = it.getNext();
00695                 RenderPriorityGroup* pDstPriorityGrp;
00696 
00697                 // Check if priority group is there
00698                 PriorityMap::iterator i = mPriorityGroups.find(priority);
00699                 if (i == mPriorityGroups.end())
00700                 {
00701                     // Missing, create
00702                     pDstPriorityGrp = OGRE_NEW RenderPriorityGroup(this, 
00703                         mSplitPassesByLightingType,
00704                         mSplitNoShadowPasses, 
00705                         mShadowCastersNotReceivers);
00706                     if (mOrganisationMode)
00707                     {
00708                         pDstPriorityGrp->resetOrganisationModes();
00709                         pDstPriorityGrp->addOrganisationMode((QueuedRenderableCollection::OrganisationMode)mOrganisationMode);
00710                     }
00711 
00712                     mPriorityGroups.insert(PriorityMap::value_type(priority, pDstPriorityGrp));
00713                 }
00714                 else
00715                 {
00716                     pDstPriorityGrp = i->second;
00717                 }
00718 
00719                 // merge
00720                 pDstPriorityGrp->merge( pSrcPriorityGrp );
00721             }
00722         }
00723     };
00724 
00729 }
00730 
00731 #endif
00732 
00733 

Copyright © 2012 Torus Knot Software Ltd
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:25 2012