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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 27 22:02:25 2009