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-2004 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 #include "OgreStableHeaders.h" 00026 #include "OgreRenderQueueSortingGrouping.h" 00027 00028 namespace Ogre { 00029 00030 //----------------------------------------------------------------------- 00031 void RenderPriorityGroup::destroySolidPassMap(SolidRenderablePassMap& passmap) 00032 { 00033 // destroy all the pass map entries 00034 SolidRenderablePassMap::iterator i, iend; 00035 iend = passmap.end(); 00036 for (i = passmap.begin(); i != iend; ++i) 00037 { 00038 // Free the list associated with this pass 00039 delete i->second; 00040 } 00041 passmap.clear(); 00042 } 00043 //----------------------------------------------------------------------- 00044 void RenderPriorityGroup::removeSolidPassEntry(Pass* p) 00045 { 00046 SolidRenderablePassMap::iterator i; 00047 00048 i = mSolidPasses.find(p); 00049 if (i != mSolidPasses.end()) 00050 { 00051 // free memory 00052 delete i->second; 00053 // erase from map 00054 mSolidPasses.erase(i); 00055 } 00056 00057 i = mSolidPassesDiffuseSpecular.find(p); 00058 if (i != mSolidPassesDiffuseSpecular.end()) 00059 { 00060 // free memory 00061 delete i->second; 00062 // erase from map 00063 mSolidPassesDiffuseSpecular.erase(i); 00064 } 00065 i = mSolidPassesDecal.find(p); 00066 if (i != mSolidPassesDecal.end()) 00067 { 00068 // free memory 00069 delete i->second; 00070 // erase from map 00071 mSolidPassesDecal.erase(i); 00072 } 00073 i = mSolidPassesNoShadow.find(p); 00074 if (i != mSolidPassesNoShadow.end()) 00075 { 00076 // free memory 00077 delete i->second; 00078 // erase from map 00079 mSolidPassesNoShadow.erase(i); 00080 } 00081 00082 } 00083 //----------------------------------------------------------------------- 00084 void RenderPriorityGroup::clearSolidPassMap(SolidRenderablePassMap& passmap) 00085 { 00086 SolidRenderablePassMap::iterator i, iend; 00087 iend = passmap.end(); 00088 for (i = passmap.begin(); i != iend; ++i) 00089 { 00090 // Clear the list associated with this pass, but leave the pass entry 00091 i->second->clear(); 00092 } 00093 } 00094 //----------------------------------------------------------------------- 00095 void RenderPriorityGroup::addRenderable(Renderable* rend) 00096 { 00097 // Check material & technique supplied (the former since the default implementation 00098 // of getTechnique is based on it for backwards compatibility 00099 Technique* pTech; 00100 if(!rend->getMaterial() || !rend->getTechnique()) 00101 { 00102 // Use default base white 00103 pTech = static_cast<Material*>( 00104 MaterialManager::getSingleton().getByName("BaseWhite"))->getTechnique(0); 00105 } 00106 else 00107 { 00108 // Get technique 00109 pTech = rend->getTechnique(); 00110 } 00111 00112 // Transparent and depth settings mean depth sorting is required? 00113 if (pTech->isTransparent() && 00114 !(pTech->isDepthWriteEnabled() && pTech->isDepthCheckEnabled()) ) 00115 { 00116 addTransparentRenderable(pTech, rend); 00117 } 00118 else 00119 { 00120 if (mSplitNoShadowPasses && !pTech->getParent()->getReceiveShadows()) 00121 { 00122 // Add solid renderable and add passes to no-shadow group 00123 addSolidRenderable(pTech, rend, true); 00124 } 00125 else 00126 { 00127 if (mSplitPassesByLightingType) 00128 { 00129 addSolidRenderableSplitByLightType(pTech, rend); 00130 } 00131 else 00132 { 00133 addSolidRenderable(pTech, rend, false); 00134 } 00135 } 00136 } 00137 00138 } 00139 //----------------------------------------------------------------------- 00140 void RenderPriorityGroup::addSolidRenderable(Technique* pTech, 00141 Renderable* rend, bool addToNoShadow) 00142 { 00143 Technique::PassIterator pi = pTech->getPassIterator(); 00144 00145 SolidRenderablePassMap* passMap; 00146 if (addToNoShadow) 00147 { 00148 passMap = &mSolidPassesNoShadow; 00149 } 00150 else 00151 { 00152 passMap = &mSolidPasses; 00153 } 00154 00155 00156 while (pi.hasMoreElements()) 00157 { 00158 // Insert into solid list 00159 Pass* p = pi.getNext(); 00160 SolidRenderablePassMap::iterator i = passMap->find(p); 00161 if (i == passMap->end()) 00162 { 00163 std::pair<SolidRenderablePassMap::iterator, bool> retPair; 00164 // Create new pass entry, build a new list 00165 // Note that this pass and list are never destroyed until the engine 00166 // shuts down, although the lists will be cleared 00167 retPair = passMap->insert( 00168 SolidRenderablePassMap::value_type(p, new RenderableList() ) ); 00169 assert(retPair.second && "Error inserting new pass entry into SolidRenderablePassMap"); 00170 i = retPair.first; 00171 } 00172 // Insert renderable 00173 i->second->push_back(rend); 00174 00175 } 00176 } 00177 //----------------------------------------------------------------------- 00178 void RenderPriorityGroup::addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend) 00179 { 00180 // Divide the passes into the 3 categories 00181 Technique::IlluminationPassIterator pi = 00182 pTech->getIlluminationPassIterator(); 00183 00184 while (pi.hasMoreElements()) 00185 { 00186 // Insert into solid list 00187 IlluminationPass* p = pi.getNext(); 00188 SolidRenderablePassMap* passMap; 00189 switch(p->stage) 00190 { 00191 case IS_AMBIENT: 00192 passMap = &mSolidPasses; 00193 break; 00194 case IS_PER_LIGHT: 00195 passMap = &mSolidPassesDiffuseSpecular; 00196 break; 00197 case IS_DECAL: 00198 passMap = &mSolidPassesDecal; 00199 break; 00200 }; 00201 00202 SolidRenderablePassMap::iterator i = passMap->find(p->pass); 00203 if (i == passMap->end()) 00204 { 00205 std::pair<SolidRenderablePassMap::iterator, bool> retPair; 00206 // Create new pass entry, build a new list 00207 // Note that this pass and list are never destroyed until the engine 00208 // shuts down, although the lists will be cleared 00209 retPair = passMap->insert( 00210 SolidRenderablePassMap::value_type(p->pass, new RenderableList() ) ); 00211 assert(retPair.second && "Error inserting new pass entry into SolidRenderablePassMap"); 00212 i = retPair.first; 00213 } 00214 // Insert renderable 00215 i->second->push_back(rend); 00216 } 00217 } 00218 //----------------------------------------------------------------------- 00219 void RenderPriorityGroup::addTransparentRenderable(Technique* pTech, Renderable* rend) 00220 { 00221 Technique::PassIterator pi = pTech->getPassIterator(); 00222 00223 while (pi.hasMoreElements()) 00224 { 00225 // Insert into transparent list 00226 mTransparentPasses.push_back(RenderablePass(rend, pi.getNext())); 00227 } 00228 } 00229 //----------------------------------------------------------------------- 00230 void RenderPriorityGroup::sort(const Camera* cam) 00231 { 00232 TransparentQueueItemLess transFunctor; 00233 transFunctor.camera = cam; 00234 00235 std::stable_sort(mTransparentPasses.begin(), mTransparentPasses.end(), 00236 transFunctor); 00237 } 00238 //----------------------------------------------------------------------- 00239 void RenderPriorityGroup::clear(void) 00240 { 00241 SolidRenderablePassMap::iterator i, iend; 00242 // Delete queue groups which are using passes which are to be 00243 // deleted, we won't need these any more and they clutter up 00244 // the list and can cause problems with future clones 00245 const Pass::PassSet& graveyardList = Pass::getPassGraveyard(); 00246 Pass::PassSet::const_iterator gi, giend; 00247 giend = graveyardList.end(); 00248 for (gi = graveyardList.begin(); gi != giend; ++gi) 00249 { 00250 removeSolidPassEntry(*gi); 00251 } 00252 00253 // Now remove any dirty passes, these will have their hashes recalculated 00254 // by the parent queue after all groups have been processed 00255 // If we don't do this, the std::map will become inconsistent for new insterts 00256 const Pass::PassSet& dirtyList = Pass::getDirtyHashList(); 00257 Pass::PassSet::const_iterator di, diend; 00258 diend = dirtyList.end(); 00259 for (di = dirtyList.begin(); di != diend; ++di) 00260 { 00261 removeSolidPassEntry(*di); 00262 } 00263 // NB we do NOT clear the graveyard or the dirty list here, because 00264 // it needs to be acted on for all groups, the parent queue takes 00265 // care of this afterwards 00266 00267 // We do not clear the unchanged solid pass maps, only the contents of each list 00268 // This is because we assume passes are reused a lot and it saves resorting 00269 clearSolidPassMap(mSolidPasses); 00270 clearSolidPassMap(mSolidPassesDecal); 00271 clearSolidPassMap(mSolidPassesDiffuseSpecular); 00272 clearSolidPassMap(mSolidPassesNoShadow); 00273 00274 // Always empty the transparents list 00275 mTransparentPasses.clear(); 00276 00277 } 00278 //----------------------------------------------------------------------- 00279 00280 00281 00282 00283 00284 } 00285
Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:42 2004