# 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-2005 The OGRE Team
    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 */
    00025 #ifndef __RenderQueueSortingGrouping_H__
    00026 #define __RenderQueueSortingGrouping_H__
    00027
    00028 // Precompiler options
    00029 #include "OgrePrerequisites.h"
    00030 #include "OgreIteratorWrappers.h"
    00031 #include "OgreMaterial.h"
    00032 #include "OgreTechnique.h"
    00033 #include "OgrePass.h"
    00034 #include "OgreRadixSort.h"
    00035
    00036 namespace Ogre {
    00037
    00042     struct RenderablePass
    00043     {
    00045         Renderable* renderable;
    00047         Pass* pass;
    00048
    00049         RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {}
    00050     };
    00051
    00052
    00060     class _OgreExport QueuedRenderableVisitor
    00061     {
    00062     public:
    00063         QueuedRenderableVisitor() {}
    00064         virtual ~QueuedRenderableVisitor() {}
    00065
    00072         virtual void visit(const RenderablePass* rp) = 0;
    00073
    00074         /* When visiting a collection grouped by pass, this is
    00075             called when the grouping pass changes.
    00076         @remarks
    00077             If this method is called, the RenderablePass visit
    00078             method will not be called for this collection. The
    00079             Renderable visit method will be called for each item
    00080             underneath the pass grouping level.
    00081         @returns True to continue, false to skip the Renderables underneath
    00082         */
    00083         virtual bool visit(const Pass* p) = 0;
    00090         virtual void visit(const Renderable* r) = 0;
    00091
    00092
    00093     };
    00094
    00104     class _OgreExport QueuedRenderableCollection
    00105     {
    00106     public:
    00115         enum OrganisationMode
    00116         {
    00118             OM_PASS_GROUP = 1,
    00120             OM_SORT_DESCENDING = 2,
    00124             OM_SORT_ASCENDING = 6
    00125         };
    00126
    00127     protected:
    00129         struct PassGroupLess
    00130         {
    00131             bool _OgreExport operator()(const Pass* a, const Pass* b) const
    00132             {
    00133                 // Sort by passHash, which is pass, then texture unit changes
    00134                 uint32 hasha = a->getHash();
    00135                 uint32 hashb = b->getHash();
    00136                 if (hasha == hashb)
    00137                 {
    00138                     // Must differentTransparentQueueItemLessiate by pointer incase 2 passes end up with the same hash
    00139                     return a < b;
    00140                 }
    00141                 else
    00142                 {
    00143                     return hasha < hashb;
    00144                 }
    00145             }
    00146         };
    00148         struct DepthSortDescendingLess
    00149         {
    00150             const Camera* camera;
    00151
    00152             DepthSortDescendingLess(const Camera* cam)
    00153                 : camera(cam)
    00154             {
    00155             }
    00156
    00157             bool _OgreExport operator()(const RenderablePass& a, const RenderablePass& b) const
    00158             {
    00159                 if (a.renderable == b.renderable)
    00160                 {
    00161                     // Same renderable, sort by pass hash
    00162                     return a.pass->getHash() < b.pass->getHash();
    00163                 }
    00164                 else
    00165                 {
    00166                     // Different renderables, sort by depth
    00167                     Real adepth = a.renderable->getSquaredViewDepth(camera);
    00168                     Real bdepth = b.renderable->getSquaredViewDepth(camera);
    00169                     if (adepth == bdepth)
    00170                     {
    00171                         // Must return deterministic result, doesn't matter what
    00172                         return a.pass < b.pass;
    00173                     }
    00174                     else
    00175                     {
    00176                         // Sort DESCENDING by depth (ie far objects first)
    00177                         return (adepth > bdepth);
    00178                     }
    00179                 }
    00180
    00181             }
    00182         };
    00183
    00187         typedef std::vector<RenderablePass> RenderablePassList;
    00188         typedef std::vector<Renderable*> RenderableList;
    00190         typedef std::map<Pass*, RenderableList*, PassGroupLess> PassGroupRenderableMap;
    00191
    00193         struct RadixSortFunctorPass
    00194         {
    00195             uint32 operator()(const RenderablePass& p) const
    00196             {
    00197                 return p.pass->getHash();
    00198             }
    00199         };
    00200
    00202         static RadixSort<RenderablePassList, RenderablePass, uint32> msRadixSorter1;
    00203
    00205         struct RadixSortFunctorDistance
    00206         {
    00207             const Camera* camera;
    00208
    00209             RadixSortFunctorDistance(const Camera* cam)
    00210                 : camera(cam)
    00211             {
    00212             }
    00213
    00214             float operator()(const RenderablePass& p) const
    00215             {
    00216                 // Sort DESCENDING by depth (ie far objects first), use negative distance
    00217                 // here because radix sorter always dealing with accessing sort
    00218                 return static_cast<float>(- p.renderable->getSquaredViewDepth(camera));
    00219             }
    00220         };
    00221
    00223         static RadixSort<RenderablePassList, RenderablePass, float> msRadixSorter2;
    00224
    00226         uint8 mOrganisationMode;
    00227
    00229         PassGroupRenderableMap mGrouped;
    00231         RenderablePassList mSortedDescending;
    00232
    00234         void acceptVisitorGrouped(QueuedRenderableVisitor* visitor) const;
    00236         void acceptVisitorDescending(QueuedRenderableVisitor* visitor) const;
    00238         void acceptVisitorAscending(QueuedRenderableVisitor* visitor) const;
    00239
    00240     public:
    00241         QueuedRenderableCollection();
    00242         ~QueuedRenderableCollection();
    00243
    00245         void clear(void);
    00246
    00252         void removePassGroup(Pass* p);
    00253
    00259         void resetOrganisationModes(void)
    00260         {
    00261             mOrganisationMode = 0;
    00262         }
    00263
    00269         void addOrganisationMode(OrganisationMode om)
    00270         {
    00271             mOrganisationMode |= om;
    00272         }
    00273
    00275         void addRenderable(Pass* pass, Renderable* rend);
    00276
    00280         void sort(const Camera* cam);
    00281
    00288         void acceptVisitor(QueuedRenderableVisitor* visitor, OrganisationMode om) const;
    00289
    00290     };
    00291
    00311     class _OgreExport RenderPriorityGroup
    00312     {
    00313     protected:
    00314
    00316         RenderQueueGroup* mParent;
    00317         bool mSplitPassesByLightingType;
    00318         bool mSplitNoShadowPasses;
    00319         bool mShadowCastersNotReceivers;
    00321         QueuedRenderableCollection mSolidsBasic;
    00323         QueuedRenderableCollection mSolidsDiffuseSpecular;
    00325         QueuedRenderableCollection mSolidsDecal;
    00327         QueuedRenderableCollection mSolidsNoShadowReceive;
    00329         QueuedRenderableCollection mTransparents;
    00330
    00332         void removePassEntry(Pass* p);
    00333
    00335         void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap);
    00337         void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend);
    00339         void addTransparentRenderable(Technique* pTech, Renderable* rend);
    00340
    00341     public:
    00342         RenderPriorityGroup(RenderQueueGroup* parent,
    00343             bool splitPassesByLightingType,
    00344             bool splitNoShadowPasses,
    00345             bool shadowCastersNotReceivers);
    00346
    00347         ~RenderPriorityGroup() { }
    00348
    00353         const QueuedRenderableCollection& getSolidsBasic(void) const
    00354         { return mSolidsBasic; }
    00357         const QueuedRenderableCollection& getSolidsDiffuseSpecular(void) const
    00358         { return mSolidsDiffuseSpecular; }
    00361         const QueuedRenderableCollection& getSolidsDecal(void) const
    00362         { return mSolidsDecal; }
    00365         const QueuedRenderableCollection& getSolidsNoShadowReceive(void) const
    00366         { return mSolidsNoShadowReceive; }
    00368         const QueuedRenderableCollection& getTransparents(void) const
    00369         { return mTransparents; }
    00370
    00371
    00378         void resetOrganisationModes(void);
    00379
    00386         void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om);
    00387
    00394         void defaultOrganisationMode(void);
    00395
    00397         void addRenderable(Renderable* pRend, Technique* pTech);
    00398
    00401         void sort(const Camera* cam);
    00402
    00405         void clear(void);
    00406
    00410         void setSplitPassesByLightingType(bool split)
    00411         {
    00412             mSplitPassesByLightingType = split;
    00413         }
    00414
    00418         void setSplitNoShadowPasses(bool split)
    00419         {
    00420             mSplitNoShadowPasses = split;
    00421         }
    00422
    00426         void setShadowCastersCannotBeReceivers(bool ind)
    00427         {
    00428             mShadowCastersNotReceivers = ind;
    00429         }
    00430
    00431
    00432
    00433     };
    00434
    00435
    00443     class _OgreExport RenderQueueGroup
    00444     {
    00445     public:
    00446         typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
    00447         typedef MapIterator<PriorityMap> PriorityMapIterator;
    00448     protected:
    00449         RenderQueue* mParent;
    00450         bool mSplitPassesByLightingType;
    00451         bool mSplitNoShadowPasses;
    00452         bool mShadowCastersNotReceivers;
    00454         PriorityMap mPriorityGroups;
    00456         bool mShadowsEnabled;
    00457
    00458
    00459     public:
    00460         RenderQueueGroup(RenderQueue* parent,
    00461             bool splitPassesByLightingType,
    00462             bool splitNoShadowPasses,
    00463             bool shadowCastersNotReceivers)
    00464             : mParent(parent)
    00465             , mSplitPassesByLightingType(splitPassesByLightingType)
    00466             , mSplitNoShadowPasses(splitNoShadowPasses)
    00467             , mShadowCastersNotReceivers(shadowCastersNotReceivers)
    00468             , mShadowsEnabled(true)
    00469         {
    00470         }
    00471
    00472         ~RenderQueueGroup() {
    00473             // destroy contents now
    00474             PriorityMap::iterator i;
    00475             for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
    00476             {
    00477                 delete i->second;
    00478             }
    00479         }
    00480
    00482         PriorityMapIterator getIterator(void)
    00483         {
    00484             return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
    00485         }
    00486
    00488         void addRenderable(Renderable* pRend, Technique* pTech, ushort priority)
    00489         {
    00490             // Check if priority group is there
    00491             PriorityMap::iterator i = mPriorityGroups.find(priority);
    00492             RenderPriorityGroup* pPriorityGrp;
    00493             if (i == mPriorityGroups.end())
    00494             {
    00495                 // Missing, create
    00496                 pPriorityGrp = new RenderPriorityGroup(this,
    00497                     mSplitPassesByLightingType,
    00498                     mSplitNoShadowPasses,
    00499                     mShadowCastersNotReceivers);
    00500                 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
    00501             }
    00502             else
    00503             {
    00504                 pPriorityGrp = i->second;
    00505             }
    00506
    00507             // Add
    00508             pPriorityGrp->addRenderable(pRend, pTech);
    00509
    00510         }
    00511
    00519         void clear(bool destroy = false)
    00520         {
    00521             PriorityMap::iterator i, iend;
    00522             iend = mPriorityGroups.end();
    00523             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00524             {
    00525                 if (destroy)
    00526                     delete i->second;
    00527                 else
    00528                     i->second->clear();
    00529             }
    00530
    00531             if (destroy)
    00532                 mPriorityGroups.clear();
    00533
    00534         }
    00535
    00548         void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; }
    00549
    00551         bool getShadowsEnabled(void) const { return mShadowsEnabled; }
    00552
    00556         void setSplitPassesByLightingType(bool split)
    00557         {
    00558             mSplitPassesByLightingType = split;
    00559             PriorityMap::iterator i, iend;
    00560             iend = mPriorityGroups.end();
    00561             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00562             {
    00563                 i->second->setSplitPassesByLightingType(split);
    00564             }
    00565         }
    00570         void setSplitNoShadowPasses(bool split)
    00571         {
    00572             mSplitNoShadowPasses = split;
    00573             PriorityMap::iterator i, iend;
    00574             iend = mPriorityGroups.end();
    00575             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00576             {
    00577                 i->second->setSplitNoShadowPasses(split);
    00578             }
    00579         }
    00583         void setShadowCastersCannotBeReceivers(bool ind)
    00584         {
    00585             mShadowCastersNotReceivers = ind;
    00586             PriorityMap::iterator i, iend;
    00587             iend = mPriorityGroups.end();
    00588             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00589             {
    00590                 i->second->setShadowCastersCannotBeReceivers(ind);
    00591             }
    00592         }
    00599         void resetOrganisationModes(void)
    00600         {
    00601             PriorityMap::iterator i, iend;
    00602             iend = mPriorityGroups.end();
    00603             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00604             {
    00605                 i->second->resetOrganisationModes();
    00606             }
    00607         }
    00608
    00615         void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om)
    00616         {
    00617             PriorityMap::iterator i, iend;
    00618             iend = mPriorityGroups.end();
    00619             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00620             {
    00621                 i->second->addOrganisationMode(om);
    00622             }
    00623         }
    00624
    00631         void defaultOrganisationMode(void)
    00632         {
    00633             PriorityMap::iterator i, iend;
    00634             iend = mPriorityGroups.end();
    00635             for (i = mPriorityGroups.begin(); i != iend; ++i)
    00636             {
    00637                 i->second->defaultOrganisationMode();
    00638             }
    00639         }
    00640
    00641     };
    00642
    00643
    00644
    00645 }
    00646
    00647 #endif
    00648
    00649

Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 17 15:39:11 2006