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