Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Mar 12 14:37:48 2006