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