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
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Sun Sep 2 2012 07:27:23