# 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(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(Renderable* r) = 0;
    00095
    00096
    00097     };
    00098
    00108     class _OgreExport QueuedRenderableCollection : public RenderQueueAlloc
    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 (Math::RealEqual(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 (i.e. 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 : public RenderQueueAlloc
    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 mTransparentsUnsorted;
    00335         QueuedRenderableCollection mTransparents;
    00336
    00338         void removePassEntry(Pass* p);
    00339
    00341         void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap);
    00343         void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend);
    00345         void addUnsortedTransparentRenderable(Technique* pTech, Renderable* rend);
    00347         void addTransparentRenderable(Technique* pTech, Renderable* rend);
    00348
    00349     public:
    00350         RenderPriorityGroup(RenderQueueGroup* parent,
    00351             bool splitPassesByLightingType,
    00352             bool splitNoShadowPasses,
    00353             bool shadowCastersNotReceivers);
    00354
    00355         ~RenderPriorityGroup() { }
    00356
    00361         const QueuedRenderableCollection& getSolidsBasic(void) const
    00362         { return mSolidsBasic; }
    00365         const QueuedRenderableCollection& getSolidsDiffuseSpecular(void) const
    00366         { return mSolidsDiffuseSpecular; }
    00369         const QueuedRenderableCollection& getSolidsDecal(void) const
    00370         { return mSolidsDecal; }
    00373         const QueuedRenderableCollection& getSolidsNoShadowReceive(void) const
    00374         { return mSolidsNoShadowReceive; }
    00376         const QueuedRenderableCollection& getTransparentsUnsorted(void) const
    00377         { return mTransparentsUnsorted; }
    00379         const QueuedRenderableCollection& getTransparents(void) const
    00380         { return mTransparents; }
    00381
    00382
    00389         void resetOrganisationModes(void);
    00390
    00397         void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om);
    00398
    00405         void defaultOrganisationMode(void);
    00406
    00408         void addRenderable(Renderable* pRend, Technique* pTech);
    00409
    00412         void sort(const Camera* cam);
    00413
    00416         void clear(void);
    00417
    00421         void setSplitPassesByLightingType(bool split)
    00422         {
    00423             mSplitPassesByLightingType = split;
    00424         }
    00425
    00429         void setSplitNoShadowPasses(bool split)
    00430         {
    00431             mSplitNoShadowPasses = split;
    00432         }
    00433
    00437         void setShadowCastersCannotBeReceivers(bool ind)
    00438         {
    00439             mShadowCastersNotReceivers = ind;
    00440         }
    00441
    00442
    00443
    00444     };
    00445
    00446
    00454     class _OgreExport RenderQueueGroup : public RenderQueueAlloc
    00455     {
    00456     public:
    00457         typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
    00458         typedef MapIterator<PriorityMap> PriorityMapIterator;
    00459     protected:
    00460         RenderQueue* mParent;
    00461         bool mSplitPassesByLightingType;
    00462         bool mSplitNoShadowPasses;
    00463         bool mShadowCastersNotReceivers;
    00465         PriorityMap mPriorityGroups;
    00467         bool mShadowsEnabled;
    00469         uint8 mOrganisationMode;
    00470
    00471
    00472     public:
    00473         RenderQueueGroup(RenderQueue* parent,
    00474             bool splitPassesByLightingType,
    00475             bool splitNoShadowPasses,
    00476             bool shadowCastersNotReceivers)
    00477             : mParent(parent)
    00478             , mSplitPassesByLightingType(splitPassesByLightingType)
    00479             , mSplitNoShadowPasses(splitNoShadowPasses)
    00480             , mShadowCastersNotReceivers(shadowCastersNotReceivers)
    00481             , mShadowsEnabled(true)
    00482             , mOrganisationMode(0)
    00483         {
    00484         }
    00485
    00486         ~RenderQueueGroup() {
    00487             // destroy contents now
    00488             PriorityMap::iterator i;
    00489             for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
    00490             {
    00491                 OGRE_DELETE i->second;
    00492             }
    00493         }
    00494
    00496         PriorityMapIterator getIterator(void)
    00497         {
    00498             return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
    00499         }
    00500
    00502         void addRenderable(Renderable* pRend, Technique* pTech, ushort priority)
    00503         {
    00504             // Check if priority group is there
    00505             PriorityMap::iterator i = mPriorityGroups.find(priority);
    00506             RenderPriorityGroup* pPriorityGrp;
    00507             if (i == mPriorityGroups.end())
    00508             {
    00509                 // Missing, create
    00510                 pPriorityGrp = OGRE_NEW RenderPriorityGroup(this,
    00511                     mSplitPassesByLightingType,
    00512                     mSplitNoShadowPasses,
    00513                     mShadowCastersNotReceivers);
    00514                 if (mOrganisationMode)
    00515                 {
    00516                     pPriorityGrp->resetOrganisationModes();
    00517                     pPriorityGrp->addOrganisationMode((QueuedRenderableCollection::OrganisationMode)mOrganisationMode);
    00518                 }
    00519
    00520                 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
    00521             }
    00522             else
    00523             {
    00524                 pPriorityGrp = i->second;
    00525             }
    00526
    00527             // Add
    00528             pPriorityGrp->addRenderable(pRend, pTech);
    00529
    00530         }
    00531
    00539         void clear(bool destroy = false)
    00540         {
    00541             PriorityMap::iterator i, iend;
    00542             iend = mPriorityGroups.end();
    00543             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00544             {
    00545                 if (destroy)
    00546                     OGRE_DELETE i->second;
    00547                 else
    00548                     i->second->clear();
    00549             }
    00550
    00551             if (destroy)
    00552                 mPriorityGroups.clear();
    00553
    00554         }
    00555
    00568         void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; }
    00569
    00571         bool getShadowsEnabled(void) const { return mShadowsEnabled; }
    00572
    00576         void setSplitPassesByLightingType(bool split)
    00577         {
    00578             mSplitPassesByLightingType = split;
    00579             PriorityMap::iterator i, iend;
    00580             iend = mPriorityGroups.end();
    00581             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00582             {
    00583                 i->second->setSplitPassesByLightingType(split);
    00584             }
    00585         }
    00590         void setSplitNoShadowPasses(bool split)
    00591         {
    00592             mSplitNoShadowPasses = split;
    00593             PriorityMap::iterator i, iend;
    00594             iend = mPriorityGroups.end();
    00595             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00596             {
    00597                 i->second->setSplitNoShadowPasses(split);
    00598             }
    00599         }
    00603         void setShadowCastersCannotBeReceivers(bool ind)
    00604         {
    00605             mShadowCastersNotReceivers = ind;
    00606             PriorityMap::iterator i, iend;
    00607             iend = mPriorityGroups.end();
    00608             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00609             {
    00610                 i->second->setShadowCastersCannotBeReceivers(ind);
    00611             }
    00612         }
    00619         void resetOrganisationModes(void)
    00620         {
    00621             mOrganisationMode = 0;
    00622
    00623             PriorityMap::iterator i, iend;
    00624             iend = mPriorityGroups.end();
    00625             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00626             {
    00627                 i->second->resetOrganisationModes();
    00628             }
    00629         }
    00630
    00637         void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om)
    00638         {
    00639             mOrganisationMode |= om;
    00640
    00641             PriorityMap::iterator i, iend;
    00642             iend = mPriorityGroups.end();
    00643             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00644             {
    00645                 i->second->addOrganisationMode(om);
    00646             }
    00647         }
    00648
    00655         void defaultOrganisationMode(void)
    00656         {
    00657             mOrganisationMode = 0;
    00658
    00659             PriorityMap::iterator i, iend;
    00660             iend = mPriorityGroups.end();
    00661             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00662             {
    00663                 i->second->defaultOrganisationMode();
    00664             }
    00665         }
    00666
    00667     };
    00668
    00669
    00670
    00671 }
    00672
    00673 #endif
    00674
    00675

Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sat Apr 11 14:26:45 2009