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-2012 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef __RenderQueueSortingGrouping_H__ 00029 #define __RenderQueueSortingGrouping_H__ 00030 00031 // Precompiler options 00032 #include "OgrePrerequisites.h" 00033 #include "OgreIteratorWrappers.h" 00034 #include "OgreMaterial.h" 00035 #include "OgreTechnique.h" 00036 #include "OgrePass.h" 00037 #include "OgreRadixSort.h" 00038 00039 namespace Ogre { 00040 00051 struct RenderablePass 00052 { 00054 Renderable* renderable; 00056 Pass* pass; 00057 00058 RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {} 00059 }; 00060 00061 00069 class _OgreExport QueuedRenderableVisitor 00070 { 00071 public: 00072 QueuedRenderableVisitor() {} 00073 virtual ~QueuedRenderableVisitor() {} 00074 00081 virtual void visit(RenderablePass* rp) = 0; 00082 00083 /* When visiting a collection grouped by pass, this is 00084 called when the grouping pass changes. 00085 @remarks 00086 If this method is called, the RenderablePass visit 00087 method will not be called for this collection. The 00088 Renderable visit method will be called for each item 00089 underneath the pass grouping level. 00090 @return True to continue, false to skip the Renderables underneath 00091 */ 00092 virtual bool visit(const Pass* p) = 0; 00099 virtual void visit(Renderable* r) = 0; 00100 00101 00102 }; 00103 00113 class _OgreExport QueuedRenderableCollection : public RenderQueueAlloc 00114 { 00115 public: 00124 enum OrganisationMode 00125 { 00127 OM_PASS_GROUP = 1, 00129 OM_SORT_DESCENDING = 2, 00133 OM_SORT_ASCENDING = 6 00134 }; 00135 00136 protected: 00138 struct PassGroupLess 00139 { 00140 bool _OgreExport operator()(const Pass* a, const Pass* b) const 00141 { 00142 // Sort by passHash, which is pass, then texture unit changes 00143 uint32 hasha = a->getHash(); 00144 uint32 hashb = b->getHash(); 00145 if (hasha == hashb) 00146 { 00147 // Must differentTransparentQueueItemLessiate by pointer incase 2 passes end up with the same hash 00148 return a < b; 00149 } 00150 else 00151 { 00152 return hasha < hashb; 00153 } 00154 } 00155 }; 00157 struct DepthSortDescendingLess 00158 { 00159 const Camera* camera; 00160 00161 DepthSortDescendingLess(const Camera* cam) 00162 : camera(cam) 00163 { 00164 } 00165 00166 bool _OgreExport operator()(const RenderablePass& a, const RenderablePass& b) const 00167 { 00168 if (a.renderable == b.renderable) 00169 { 00170 // Same renderable, sort by pass hash 00171 return a.pass->getHash() < b.pass->getHash(); 00172 } 00173 else 00174 { 00175 // Different renderables, sort by depth 00176 Real adepth = a.renderable->getSquaredViewDepth(camera); 00177 Real bdepth = b.renderable->getSquaredViewDepth(camera); 00178 if (Math::RealEqual(adepth, bdepth)) 00179 { 00180 // Must return deterministic result, doesn't matter what 00181 return a.pass < b.pass; 00182 } 00183 else 00184 { 00185 // Sort DESCENDING by depth (i.e. far objects first) 00186 return (adepth > bdepth); 00187 } 00188 } 00189 00190 } 00191 }; 00192 00196 typedef vector<RenderablePass>::type RenderablePassList; 00197 typedef vector<Renderable*>::type RenderableList; 00199 typedef map<Pass*, RenderableList*, PassGroupLess>::type PassGroupRenderableMap; 00200 00202 struct RadixSortFunctorPass 00203 { 00204 uint32 operator()(const RenderablePass& p) const 00205 { 00206 return p.pass->getHash(); 00207 } 00208 }; 00209 00211 static RadixSort<RenderablePassList, RenderablePass, uint32> msRadixSorter1; 00212 00214 struct RadixSortFunctorDistance 00215 { 00216 const Camera* camera; 00217 00218 RadixSortFunctorDistance(const Camera* cam) 00219 : camera(cam) 00220 { 00221 } 00222 00223 float operator()(const RenderablePass& p) const 00224 { 00225 // Sort DESCENDING by depth (ie far objects first), use negative distance 00226 // here because radix sorter always dealing with accessing sort 00227 return static_cast<float>(- p.renderable->getSquaredViewDepth(camera)); 00228 } 00229 }; 00230 00232 static RadixSort<RenderablePassList, RenderablePass, float> msRadixSorter2; 00233 00235 uint8 mOrganisationMode; 00236 00238 PassGroupRenderableMap mGrouped; 00240 RenderablePassList mSortedDescending; 00241 00243 void acceptVisitorGrouped(QueuedRenderableVisitor* visitor) const; 00245 void acceptVisitorDescending(QueuedRenderableVisitor* visitor) const; 00247 void acceptVisitorAscending(QueuedRenderableVisitor* visitor) const; 00248 00249 public: 00250 QueuedRenderableCollection(); 00251 ~QueuedRenderableCollection(); 00252 00254 void clear(void); 00255 00261 void removePassGroup(Pass* p); 00262 00268 void resetOrganisationModes(void) 00269 { 00270 mOrganisationMode = 0; 00271 } 00272 00278 void addOrganisationMode(OrganisationMode om) 00279 { 00280 mOrganisationMode |= om; 00281 } 00282 00284 void addRenderable(Pass* pass, Renderable* rend); 00285 00289 void sort(const Camera* cam); 00290 00297 void acceptVisitor(QueuedRenderableVisitor* visitor, OrganisationMode om) const; 00298 00301 void merge( const QueuedRenderableCollection& rhs ); 00302 }; 00303 00323 class _OgreExport RenderPriorityGroup : public RenderQueueAlloc 00324 { 00325 protected: 00326 00328 RenderQueueGroup* mParent; 00329 bool mSplitPassesByLightingType; 00330 bool mSplitNoShadowPasses; 00331 bool mShadowCastersNotReceivers; 00333 QueuedRenderableCollection mSolidsBasic; 00335 QueuedRenderableCollection mSolidsDiffuseSpecular; 00337 QueuedRenderableCollection mSolidsDecal; 00339 QueuedRenderableCollection mSolidsNoShadowReceive; 00341 QueuedRenderableCollection mTransparentsUnsorted; 00343 QueuedRenderableCollection mTransparents; 00344 00346 void removePassEntry(Pass* p); 00347 00349 void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap); 00351 void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend); 00353 void addUnsortedTransparentRenderable(Technique* pTech, Renderable* rend); 00355 void addTransparentRenderable(Technique* pTech, Renderable* rend); 00356 00357 public: 00358 RenderPriorityGroup(RenderQueueGroup* parent, 00359 bool splitPassesByLightingType, 00360 bool splitNoShadowPasses, 00361 bool shadowCastersNotReceivers); 00362 00363 ~RenderPriorityGroup() { } 00364 00369 const QueuedRenderableCollection& getSolidsBasic(void) const 00370 { return mSolidsBasic; } 00373 const QueuedRenderableCollection& getSolidsDiffuseSpecular(void) const 00374 { return mSolidsDiffuseSpecular; } 00377 const QueuedRenderableCollection& getSolidsDecal(void) const 00378 { return mSolidsDecal; } 00381 const QueuedRenderableCollection& getSolidsNoShadowReceive(void) const 00382 { return mSolidsNoShadowReceive; } 00384 const QueuedRenderableCollection& getTransparentsUnsorted(void) const 00385 { return mTransparentsUnsorted; } 00387 const QueuedRenderableCollection& getTransparents(void) const 00388 { return mTransparents; } 00389 00390 00397 void resetOrganisationModes(void); 00398 00405 void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om); 00406 00413 void defaultOrganisationMode(void); 00414 00416 void addRenderable(Renderable* pRend, Technique* pTech); 00417 00420 void sort(const Camera* cam); 00421 00424 void clear(void); 00425 00429 void setSplitPassesByLightingType(bool split) 00430 { 00431 mSplitPassesByLightingType = split; 00432 } 00433 00437 void setSplitNoShadowPasses(bool split) 00438 { 00439 mSplitNoShadowPasses = split; 00440 } 00441 00445 void setShadowCastersCannotBeReceivers(bool ind) 00446 { 00447 mShadowCastersNotReceivers = ind; 00448 } 00449 00452 void merge( const RenderPriorityGroup* rhs ); 00453 00454 00455 }; 00456 00457 00465 class _OgreExport RenderQueueGroup : public RenderQueueAlloc 00466 { 00467 public: 00468 typedef map<ushort, RenderPriorityGroup*, std::less<ushort> >::type PriorityMap; 00469 typedef MapIterator<PriorityMap> PriorityMapIterator; 00470 typedef ConstMapIterator<PriorityMap> ConstPriorityMapIterator; 00471 protected: 00472 RenderQueue* mParent; 00473 bool mSplitPassesByLightingType; 00474 bool mSplitNoShadowPasses; 00475 bool mShadowCastersNotReceivers; 00477 PriorityMap mPriorityGroups; 00479 bool mShadowsEnabled; 00481 uint8 mOrganisationMode; 00482 00483 00484 public: 00485 RenderQueueGroup(RenderQueue* parent, 00486 bool splitPassesByLightingType, 00487 bool splitNoShadowPasses, 00488 bool shadowCastersNotReceivers) 00489 : mParent(parent) 00490 , mSplitPassesByLightingType(splitPassesByLightingType) 00491 , mSplitNoShadowPasses(splitNoShadowPasses) 00492 , mShadowCastersNotReceivers(shadowCastersNotReceivers) 00493 , mShadowsEnabled(true) 00494 , mOrganisationMode(0) 00495 { 00496 } 00497 00498 ~RenderQueueGroup() { 00499 // destroy contents now 00500 PriorityMap::iterator i; 00501 for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i) 00502 { 00503 OGRE_DELETE i->second; 00504 } 00505 } 00506 00508 PriorityMapIterator getIterator(void) 00509 { 00510 return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end()); 00511 } 00512 00514 ConstPriorityMapIterator getIterator(void) const 00515 { 00516 return ConstPriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end()); 00517 } 00518 00520 void addRenderable(Renderable* pRend, Technique* pTech, ushort priority) 00521 { 00522 // Check if priority group is there 00523 PriorityMap::iterator i = mPriorityGroups.find(priority); 00524 RenderPriorityGroup* pPriorityGrp; 00525 if (i == mPriorityGroups.end()) 00526 { 00527 // Missing, create 00528 pPriorityGrp = OGRE_NEW RenderPriorityGroup(this, 00529 mSplitPassesByLightingType, 00530 mSplitNoShadowPasses, 00531 mShadowCastersNotReceivers); 00532 if (mOrganisationMode) 00533 { 00534 pPriorityGrp->resetOrganisationModes(); 00535 pPriorityGrp->addOrganisationMode((QueuedRenderableCollection::OrganisationMode)mOrganisationMode); 00536 } 00537 00538 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp)); 00539 } 00540 else 00541 { 00542 pPriorityGrp = i->second; 00543 } 00544 00545 // Add 00546 pPriorityGrp->addRenderable(pRend, pTech); 00547 00548 } 00549 00557 void clear(bool destroy = false) 00558 { 00559 PriorityMap::iterator i, iend; 00560 iend = mPriorityGroups.end(); 00561 for (i = mPriorityGroups.begin(); i != iend; ++i) 00562 { 00563 if (destroy) 00564 OGRE_DELETE i->second; 00565 else 00566 i->second->clear(); 00567 } 00568 00569 if (destroy) 00570 mPriorityGroups.clear(); 00571 00572 } 00573 00586 void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; } 00587 00589 bool getShadowsEnabled(void) const { return mShadowsEnabled; } 00590 00594 void setSplitPassesByLightingType(bool split) 00595 { 00596 mSplitPassesByLightingType = split; 00597 PriorityMap::iterator i, iend; 00598 iend = mPriorityGroups.end(); 00599 for (i = mPriorityGroups.begin(); i != iend; ++i) 00600 { 00601 i->second->setSplitPassesByLightingType(split); 00602 } 00603 } 00608 void setSplitNoShadowPasses(bool split) 00609 { 00610 mSplitNoShadowPasses = split; 00611 PriorityMap::iterator i, iend; 00612 iend = mPriorityGroups.end(); 00613 for (i = mPriorityGroups.begin(); i != iend; ++i) 00614 { 00615 i->second->setSplitNoShadowPasses(split); 00616 } 00617 } 00621 void setShadowCastersCannotBeReceivers(bool ind) 00622 { 00623 mShadowCastersNotReceivers = ind; 00624 PriorityMap::iterator i, iend; 00625 iend = mPriorityGroups.end(); 00626 for (i = mPriorityGroups.begin(); i != iend; ++i) 00627 { 00628 i->second->setShadowCastersCannotBeReceivers(ind); 00629 } 00630 } 00637 void resetOrganisationModes(void) 00638 { 00639 mOrganisationMode = 0; 00640 00641 PriorityMap::iterator i, iend; 00642 iend = mPriorityGroups.end(); 00643 for (i = mPriorityGroups.begin(); i != iend; ++i) 00644 { 00645 i->second->resetOrganisationModes(); 00646 } 00647 } 00648 00655 void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om) 00656 { 00657 mOrganisationMode |= om; 00658 00659 PriorityMap::iterator i, iend; 00660 iend = mPriorityGroups.end(); 00661 for (i = mPriorityGroups.begin(); i != iend; ++i) 00662 { 00663 i->second->addOrganisationMode(om); 00664 } 00665 } 00666 00673 void defaultOrganisationMode(void) 00674 { 00675 mOrganisationMode = 0; 00676 00677 PriorityMap::iterator i, iend; 00678 iend = mPriorityGroups.end(); 00679 for (i = mPriorityGroups.begin(); i != iend; ++i) 00680 { 00681 i->second->defaultOrganisationMode(); 00682 } 00683 } 00684 00687 void merge( const RenderQueueGroup* rhs ) 00688 { 00689 ConstPriorityMapIterator it = rhs->getIterator(); 00690 00691 while( it.hasMoreElements() ) 00692 { 00693 ushort priority = it.peekNextKey(); 00694 RenderPriorityGroup* pSrcPriorityGrp = it.getNext(); 00695 RenderPriorityGroup* pDstPriorityGrp; 00696 00697 // Check if priority group is there 00698 PriorityMap::iterator i = mPriorityGroups.find(priority); 00699 if (i == mPriorityGroups.end()) 00700 { 00701 // Missing, create 00702 pDstPriorityGrp = OGRE_NEW RenderPriorityGroup(this, 00703 mSplitPassesByLightingType, 00704 mSplitNoShadowPasses, 00705 mShadowCastersNotReceivers); 00706 if (mOrganisationMode) 00707 { 00708 pDstPriorityGrp->resetOrganisationModes(); 00709 pDstPriorityGrp->addOrganisationMode((QueuedRenderableCollection::OrganisationMode)mOrganisationMode); 00710 } 00711 00712 mPriorityGroups.insert(PriorityMap::value_type(priority, pDstPriorityGrp)); 00713 } 00714 else 00715 { 00716 pDstPriorityGrp = i->second; 00717 } 00718 00719 // merge 00720 pDstPriorityGrp->merge( pSrcPriorityGrp ); 00721 } 00722 } 00723 }; 00724 00729 } 00730 00731 #endif 00732 00733
Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:25 2012