Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound 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 © 2000-2002 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 "OgreMaterialManager.h"
00035 
00036 namespace Ogre {
00037 
00050     class RenderPriorityGroup
00051     {
00055         struct RenderablePass
00056         {
00058             Renderable* renderable;
00060             Pass* pass;
00061 
00062             RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {}
00063         };
00064 
00065         friend class Ogre::SceneManager;
00067         struct SolidQueueItemLess
00068         {
00069             _OgreExport bool operator()(const Pass* a, const Pass* b) const
00070             {
00071                 // Sort by passHash, which is pass, then texture unit changes
00072                 unsigned long hasha = a->getHash();
00073                 unsigned long hashb = b->getHash();
00074                 if (hasha == hashb)
00075                 {
00076                     // Must differentiate by pointer incase 2 passes end up with the same hash
00077                     return a < b;
00078                 }
00079                 else
00080                 {
00081                     return hasha < hashb;
00082                 }
00083             }
00084         };
00086         struct TransparentQueueItemLess
00087         {
00088             const Camera* camera;
00089 
00090             _OgreExport bool operator()(const RenderablePass& a, const RenderablePass& b) const
00091             {
00092                 if (a.renderable == b.renderable)
00093                 {
00094                     // Same renderable, sort by pass hash
00095                     return a.pass->getHash() < b.pass->getHash();
00096                 }
00097                 else
00098                 {
00099                     // Different renderables, sort by depth
00100                     Real adepth = a.renderable->getSquaredViewDepth(camera);
00101                     Real bdepth = b.renderable->getSquaredViewDepth(camera);
00102                     if (adepth == bdepth)
00103                     {
00104                         // Must return deterministic result, doesn't matter what
00105                         return a.pass < b.pass;
00106                     }
00107                     else
00108                     {
00109                         // Sort DESCENDING by depth (ie far objects first)
00110                         return (adepth > bdepth);
00111                     }
00112                 }
00113 
00114             }
00115         };
00116     public:
00120         typedef std::vector<RenderablePass> TransparentRenderablePassList;
00121         typedef std::vector<Renderable*> RenderableList;
00124         typedef std::map<Pass*, RenderableList*, SolidQueueItemLess> SolidRenderablePassMap;
00125     protected:
00127         SolidRenderablePassMap mSolidPasses;
00129         TransparentRenderablePassList mTransparentPasses;
00130 
00133         typedef std::vector<RenderablePass> TransparentRenderablePasses;
00134         TransparentRenderablePasses mRenderablePasses;
00135 
00136     public:
00137         RenderPriorityGroup() {}
00138 
00139         ~RenderPriorityGroup() {
00140             // destroy all the pass map entries
00141             SolidRenderablePassMap::iterator i, iend;
00142             iend = mSolidPasses.end();
00143             for (i = mSolidPasses.begin(); i != iend; ++i)
00144             {
00145                 // Free the list associated with this pass
00146                 delete i->second;
00147             }
00148             mSolidPasses.clear();
00149             mTransparentPasses.clear();
00150 
00151         }
00152 
00154         void addRenderable(Renderable* pRend)
00155         {
00156             // Check material & technique supplied (the former since the default implementation
00157             // of getTechnique is based on it for backwards compatibility
00158             Technique* pTech;
00159             if(!pRend->getMaterial() || !pRend->getTechnique())
00160             {
00161                 // Use default base white
00162                 pTech = static_cast<Material*>(
00163                     MaterialManager::getSingleton().getByName("BaseWhite"))->getTechnique(0);
00164             }
00165             else
00166             {
00167                 // Get technique
00168                 pTech = pRend->getTechnique();
00169             }
00170             Technique::PassIterator pi = pTech->getPassIterator();
00171 
00172             if (pTech->isTransparent())
00173             {
00174                 while (pi.hasMoreElements())
00175                 {
00176                     // Insert into transparent list
00177                     mTransparentPasses.push_back(RenderablePass(pRend, pi.getNext()));
00178                 }
00179             }
00180             else
00181             {
00182                 while (pi.hasMoreElements())
00183                 {
00184                     // Insert into solid list
00185                     Pass* p = pi.getNext();
00186                     SolidRenderablePassMap::iterator i = mSolidPasses.find(p);
00187                     if (i == mSolidPasses.end())
00188                     {
00189                         std::pair<SolidRenderablePassMap::iterator, bool> retPair;
00190                         // Create new pass entry, build a new list
00191                         // Note that this pass and list are never destroyed until the engine
00192                         // shuts down, although the lists will be cleared
00193                         retPair = mSolidPasses.insert(
00194                             SolidRenderablePassMap::value_type(p, new RenderableList() ) );
00195                         assert(retPair.second && "Error inserting new pass entry into SolidRenderablePassMap");
00196                         i = retPair.first;
00197                     }
00198                     // Insert renderable
00199                     i->second->push_back(pRend);
00200                 }
00201             }
00202 
00203         }
00204 
00207         void sort(const Camera* cam)
00208         {
00209             TransparentQueueItemLess transFunctor;
00210             transFunctor.camera = cam;
00211 
00212             std::stable_sort(mTransparentPasses.begin(), mTransparentPasses.end(), 
00213                 transFunctor);
00214         }
00215 
00216          
00217 
00220         void clear(void)
00221         {
00222             // NB we do not clear the solid pass map, only the contents of each list
00223             // This is because we assume passes are reused a lot and it saves resorting
00224             SolidRenderablePassMap::iterator i, iend;
00225             iend = mSolidPasses.end();
00226             for (i = mSolidPasses.begin(); i != iend; ++i)
00227             {
00228                 // Clear the list associated with this pass, but leave the pass entry
00229                 i->second->clear();
00230             }
00231             mTransparentPasses.clear();
00232 
00233         }
00234 
00235 
00236 
00237     };
00238 
00239 
00249     class RenderQueueGroup
00250     {
00251     public:
00252         typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap;
00253         typedef MapIterator<PriorityMap> PriorityMapIterator;
00254     protected:
00255         // Map of RenderPriorityGroup objects
00256         PriorityMap mPriorityGroups;
00257 
00258 
00259     public:
00260         RenderQueueGroup() {}
00261 
00262         ~RenderQueueGroup() {
00263             // destroy contents now
00264             PriorityMap::iterator i;
00265             for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i)
00266             {
00267                 delete i->second;
00268             }
00269         }
00270 
00272         PriorityMapIterator getIterator(void)
00273         {
00274             return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end());
00275         }
00276 
00278         void addRenderable(Renderable* pRend, ushort priority)
00279         {
00280             // Check if priority group is there
00281             PriorityMap::iterator i = mPriorityGroups.find(priority);
00282             RenderPriorityGroup* pPriorityGrp;
00283             if (i == mPriorityGroups.end())
00284             {
00285                 // Missing, create
00286                 pPriorityGrp = new RenderPriorityGroup();
00287                 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp));
00288             }
00289             else
00290             {
00291                 pPriorityGrp = i->second;
00292             }
00293 
00294             // Add
00295             pPriorityGrp->addRenderable(pRend);
00296 
00297         }
00298 
00305         void clear(void)
00306         {
00307             PriorityMap::iterator i, iend;
00308             iend = mPriorityGroups.end();
00309             for (i = mPriorityGroups.begin(); i != iend; ++i)
00310             {
00311                 i->second->clear();
00312             }
00313 
00314         }
00315 
00316 
00317     };
00318 
00319 
00320 
00321 }
00322 
00323 #endif
00324 
00325 

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:24 2004