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? 00113 if (pTech->isTransparent()) 00114 { 00115 addTransparentRenderable(pTech, rend); 00116 } 00117 else 00118 { 00119 if (mSplitNoShadowPasses && !pTech->getParent()->getReceiveShadows()) 00120 { 00121 // Add solid renderable and add passes to no-shadow group 00122 addSolidRenderable(pTech, rend, true); 00123 } 00124 else 00125 { 00126 if (mSplitPassesByLightingType) 00127 { 00128 addSolidRenderableSplitByLightType(pTech, rend); 00129 } 00130 else 00131 { 00132 addSolidRenderable(pTech, rend, false); 00133 } 00134 } 00135 } 00136 00137 } 00138 //----------------------------------------------------------------------- 00139 void RenderPriorityGroup::addSolidRenderable(Technique* pTech, 00140 Renderable* rend, bool addToNoShadow) 00141 { 00142 Technique::PassIterator pi = pTech->getPassIterator(); 00143 00144 SolidRenderablePassMap* passMap; 00145 if (addToNoShadow) 00146 { 00147 passMap = &mSolidPassesNoShadow; 00148 } 00149 else 00150 { 00151 passMap = &mSolidPasses; 00152 } 00153 00154 00155 while (pi.hasMoreElements()) 00156 { 00157 // Insert into solid list 00158 Pass* p = pi.getNext(); 00159 SolidRenderablePassMap::iterator i = passMap->find(p); 00160 if (i == passMap->end()) 00161 { 00162 std::pair<SolidRenderablePassMap::iterator, bool> retPair; 00163 // Create new pass entry, build a new list 00164 // Note that this pass and list are never destroyed until the engine 00165 // shuts down, although the lists will be cleared 00166 retPair = passMap->insert( 00167 SolidRenderablePassMap::value_type(p, new RenderableList() ) ); 00168 assert(retPair.second && "Error inserting new pass entry into SolidRenderablePassMap"); 00169 i = retPair.first; 00170 } 00171 // Insert renderable 00172 i->second->push_back(rend); 00173 00174 } 00175 } 00176 //----------------------------------------------------------------------- 00177 void RenderPriorityGroup::addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend) 00178 { 00179 // Divide the passes into the 3 categories 00180 Technique::IlluminationPassIterator pi = 00181 pTech->getIlluminationPassIterator(); 00182 00183 while (pi.hasMoreElements()) 00184 { 00185 // Insert into solid list 00186 IlluminationPass* p = pi.getNext(); 00187 SolidRenderablePassMap* passMap; 00188 switch(p->stage) 00189 { 00190 case IS_AMBIENT: 00191 passMap = &mSolidPasses; 00192 break; 00193 case IS_PER_LIGHT: 00194 passMap = &mSolidPassesDiffuseSpecular; 00195 break; 00196 case IS_DECAL: 00197 passMap = &mSolidPassesDecal; 00198 break; 00199 }; 00200 00201 SolidRenderablePassMap::iterator i = passMap->find(p->pass); 00202 if (i == passMap->end()) 00203 { 00204 std::pair<SolidRenderablePassMap::iterator, bool> retPair; 00205 // Create new pass entry, build a new list 00206 // Note that this pass and list are never destroyed until the engine 00207 // shuts down, although the lists will be cleared 00208 retPair = passMap->insert( 00209 SolidRenderablePassMap::value_type(p->pass, new RenderableList() ) ); 00210 assert(retPair.second && "Error inserting new pass entry into SolidRenderablePassMap"); 00211 i = retPair.first; 00212 } 00213 // Insert renderable 00214 i->second->push_back(rend); 00215 } 00216 } 00217 //----------------------------------------------------------------------- 00218 void RenderPriorityGroup::addTransparentRenderable(Technique* pTech, Renderable* rend) 00219 { 00220 Technique::PassIterator pi = pTech->getPassIterator(); 00221 00222 while (pi.hasMoreElements()) 00223 { 00224 // Insert into transparent list 00225 mTransparentPasses.push_back(RenderablePass(rend, pi.getNext())); 00226 } 00227 } 00228 //----------------------------------------------------------------------- 00229 void RenderPriorityGroup::sort(const Camera* cam) 00230 { 00231 TransparentQueueItemLess transFunctor; 00232 transFunctor.camera = cam; 00233 00234 std::stable_sort(mTransparentPasses.begin(), mTransparentPasses.end(), 00235 transFunctor); 00236 } 00237 //----------------------------------------------------------------------- 00238 void RenderPriorityGroup::clear(void) 00239 { 00240 SolidRenderablePassMap::iterator i, iend; 00241 // Delete queue groups which are using passes which are to be 00242 // deleted, we won't need these any more and they clutter up 00243 // the list and can cause problems with future clones 00244 const Pass::PassSet& graveyardList = Pass::getPassGraveyard(); 00245 Pass::PassSet::const_iterator gi, giend; 00246 giend = graveyardList.end(); 00247 for (gi = graveyardList.begin(); gi != giend; ++gi) 00248 { 00249 removeSolidPassEntry(*gi); 00250 } 00251 00252 // Now remove any dirty passes, these will have their hashes recalculated 00253 // by the parent queue after all groups have been processed 00254 // If we don't do this, the std::map will become inconsistent for new insterts 00255 const Pass::PassSet& dirtyList = Pass::getDirtyHashList(); 00256 Pass::PassSet::const_iterator di, diend; 00257 diend = dirtyList.end(); 00258 for (di = dirtyList.begin(); di != diend; ++di) 00259 { 00260 removeSolidPassEntry(*di); 00261 } 00262 // NB we do NOT clear the graveyard or the dirty list here, because 00263 // it needs to be acted on for all groups, the parent queue takes 00264 // care of this afterwards 00265 00266 // We do not clear the unchanged solid pass maps, only the contents of each list 00267 // This is because we assume passes are reused a lot and it saves resorting 00268 clearSolidPassMap(mSolidPasses); 00269 clearSolidPassMap(mSolidPassesDecal); 00270 clearSolidPassMap(mSolidPassesDiffuseSpecular); 00271 clearSolidPassMap(mSolidPassesNoShadow); 00272 00273 // Always empty the transparents list 00274 mTransparentPasses.clear(); 00275 00276 } 00277 //----------------------------------------------------------------------- 00278 00279 00280 00281 00282 00283 } 00284
Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:39 2004