# 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 (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 (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
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sat May 10 16:25:02 2008