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-2006 Torus Knot Software Ltd 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 You may alternatively use this source under the terms of a specific version of 00025 the OGRE Unrestricted License provided you have obtained such a license from 00026 Torus Knot Software Ltd. 00027 ----------------------------------------------------------------------------- 00028 */ 00029 #ifndef __RenderQueueSortingGrouping_H__ 00030 #define __RenderQueueSortingGrouping_H__ 00031 00032 // Precompiler options 00033 #include "OgrePrerequisites.h" 00034 #include "OgreIteratorWrappers.h" 00035 #include "OgreMaterial.h" 00036 #include "OgreTechnique.h" 00037 #include "OgrePass.h" 00038 #include "OgreRadixSort.h" 00039 00040 namespace Ogre { 00041 00046 struct RenderablePass 00047 { 00049 Renderable* renderable; 00051 Pass* pass; 00052 00053 RenderablePass(Renderable* rend, Pass* p) :renderable(rend), pass(p) {} 00054 }; 00055 00056 00064 class _OgreExport QueuedRenderableVisitor 00065 { 00066 public: 00067 QueuedRenderableVisitor() {} 00068 virtual ~QueuedRenderableVisitor() {} 00069 00076 virtual void visit(RenderablePass* rp) = 0; 00077 00078 /* When visiting a collection grouped by pass, this is 00079 called when the grouping pass changes. 00080 @remarks 00081 If this method is called, the RenderablePass visit 00082 method will not be called for this collection. The 00083 Renderable visit method will be called for each item 00084 underneath the pass grouping level. 00085 @returns True to continue, false to skip the Renderables underneath 00086 */ 00087 virtual bool visit(const Pass* p) = 0; 00094 virtual void visit(Renderable* r) = 0; 00095 00096 00097 }; 00098 00108 class _OgreExport QueuedRenderableCollection : public RenderQueueAlloc 00109 { 00110 public: 00119 enum OrganisationMode 00120 { 00122 OM_PASS_GROUP = 1, 00124 OM_SORT_DESCENDING = 2, 00128 OM_SORT_ASCENDING = 6 00129 }; 00130 00131 protected: 00133 struct PassGroupLess 00134 { 00135 bool _OgreExport operator()(const Pass* a, const Pass* b) const 00136 { 00137 // Sort by passHash, which is pass, then texture unit changes 00138 uint32 hasha = a->getHash(); 00139 uint32 hashb = b->getHash(); 00140 if (hasha == hashb) 00141 { 00142 // Must differentTransparentQueueItemLessiate by pointer incase 2 passes end up with the same hash 00143 return a < b; 00144 } 00145 else 00146 { 00147 return hasha < hashb; 00148 } 00149 } 00150 }; 00152 struct DepthSortDescendingLess 00153 { 00154 const Camera* camera; 00155 00156 DepthSortDescendingLess(const Camera* cam) 00157 : camera(cam) 00158 { 00159 } 00160 00161 bool _OgreExport operator()(const RenderablePass& a, const RenderablePass& b) const 00162 { 00163 if (a.renderable == b.renderable) 00164 { 00165 // Same renderable, sort by pass hash 00166 return a.pass->getHash() < b.pass->getHash(); 00167 } 00168 else 00169 { 00170 // Different renderables, sort by depth 00171 Real adepth = a.renderable->getSquaredViewDepth(camera); 00172 Real bdepth = b.renderable->getSquaredViewDepth(camera); 00173 if (Math::RealEqual(adepth, bdepth)) 00174 { 00175 // Must return deterministic result, doesn't matter what 00176 return a.pass < b.pass; 00177 } 00178 else 00179 { 00180 // Sort DESCENDING by depth (i.e. far objects first) 00181 return (adepth > bdepth); 00182 } 00183 } 00184 00185 } 00186 }; 00187 00191 typedef std::vector<RenderablePass> RenderablePassList; 00192 typedef std::vector<Renderable*> RenderableList; 00194 typedef std::map<Pass*, RenderableList*, PassGroupLess> PassGroupRenderableMap; 00195 00197 struct RadixSortFunctorPass 00198 { 00199 uint32 operator()(const RenderablePass& p) const 00200 { 00201 return p.pass->getHash(); 00202 } 00203 }; 00204 00206 static RadixSort<RenderablePassList, RenderablePass, uint32> msRadixSorter1; 00207 00209 struct RadixSortFunctorDistance 00210 { 00211 const Camera* camera; 00212 00213 RadixSortFunctorDistance(const Camera* cam) 00214 : camera(cam) 00215 { 00216 } 00217 00218 float operator()(const RenderablePass& p) const 00219 { 00220 // Sort DESCENDING by depth (ie far objects first), use negative distance 00221 // here because radix sorter always dealing with accessing sort 00222 return static_cast<float>(- p.renderable->getSquaredViewDepth(camera)); 00223 } 00224 }; 00225 00227 static RadixSort<RenderablePassList, RenderablePass, float> msRadixSorter2; 00228 00230 uint8 mOrganisationMode; 00231 00233 PassGroupRenderableMap mGrouped; 00235 RenderablePassList mSortedDescending; 00236 00238 void acceptVisitorGrouped(QueuedRenderableVisitor* visitor) const; 00240 void acceptVisitorDescending(QueuedRenderableVisitor* visitor) const; 00242 void acceptVisitorAscending(QueuedRenderableVisitor* visitor) const; 00243 00244 public: 00245 QueuedRenderableCollection(); 00246 ~QueuedRenderableCollection(); 00247 00249 void clear(void); 00250 00256 void removePassGroup(Pass* p); 00257 00263 void resetOrganisationModes(void) 00264 { 00265 mOrganisationMode = 0; 00266 } 00267 00273 void addOrganisationMode(OrganisationMode om) 00274 { 00275 mOrganisationMode |= om; 00276 } 00277 00279 void addRenderable(Pass* pass, Renderable* rend); 00280 00284 void sort(const Camera* cam); 00285 00292 void acceptVisitor(QueuedRenderableVisitor* visitor, OrganisationMode om) const; 00293 00294 }; 00295 00315 class _OgreExport RenderPriorityGroup : public RenderQueueAlloc 00316 { 00317 protected: 00318 00320 RenderQueueGroup* mParent; 00321 bool mSplitPassesByLightingType; 00322 bool mSplitNoShadowPasses; 00323 bool mShadowCastersNotReceivers; 00325 QueuedRenderableCollection mSolidsBasic; 00327 QueuedRenderableCollection mSolidsDiffuseSpecular; 00329 QueuedRenderableCollection mSolidsDecal; 00331 QueuedRenderableCollection mSolidsNoShadowReceive; 00333 QueuedRenderableCollection mTransparentsUnsorted; 00335 QueuedRenderableCollection mTransparents; 00336 00338 void removePassEntry(Pass* p); 00339 00341 void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap); 00343 void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend); 00345 void addUnsortedTransparentRenderable(Technique* pTech, Renderable* rend); 00347 void addTransparentRenderable(Technique* pTech, Renderable* rend); 00348 00349 public: 00350 RenderPriorityGroup(RenderQueueGroup* parent, 00351 bool splitPassesByLightingType, 00352 bool splitNoShadowPasses, 00353 bool shadowCastersNotReceivers); 00354 00355 ~RenderPriorityGroup() { } 00356 00361 const QueuedRenderableCollection& getSolidsBasic(void) const 00362 { return mSolidsBasic; } 00365 const QueuedRenderableCollection& getSolidsDiffuseSpecular(void) const 00366 { return mSolidsDiffuseSpecular; } 00369 const QueuedRenderableCollection& getSolidsDecal(void) const 00370 { return mSolidsDecal; } 00373 const QueuedRenderableCollection& getSolidsNoShadowReceive(void) const 00374 { return mSolidsNoShadowReceive; } 00376 const QueuedRenderableCollection& getTransparentsUnsorted(void) const 00377 { return mTransparentsUnsorted; } 00379 const QueuedRenderableCollection& getTransparents(void) const 00380 { return mTransparents; } 00381 00382 00389 void resetOrganisationModes(void); 00390 00397 void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om); 00398 00405 void defaultOrganisationMode(void); 00406 00408 void addRenderable(Renderable* pRend, Technique* pTech); 00409 00412 void sort(const Camera* cam); 00413 00416 void clear(void); 00417 00421 void setSplitPassesByLightingType(bool split) 00422 { 00423 mSplitPassesByLightingType = split; 00424 } 00425 00429 void setSplitNoShadowPasses(bool split) 00430 { 00431 mSplitNoShadowPasses = split; 00432 } 00433 00437 void setShadowCastersCannotBeReceivers(bool ind) 00438 { 00439 mShadowCastersNotReceivers = ind; 00440 } 00441 00442 00443 00444 }; 00445 00446 00454 class _OgreExport RenderQueueGroup : public RenderQueueAlloc 00455 { 00456 public: 00457 typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap; 00458 typedef MapIterator<PriorityMap> PriorityMapIterator; 00459 protected: 00460 RenderQueue* mParent; 00461 bool mSplitPassesByLightingType; 00462 bool mSplitNoShadowPasses; 00463 bool mShadowCastersNotReceivers; 00465 PriorityMap mPriorityGroups; 00467 bool mShadowsEnabled; 00469 uint8 mOrganisationMode; 00470 00471 00472 public: 00473 RenderQueueGroup(RenderQueue* parent, 00474 bool splitPassesByLightingType, 00475 bool splitNoShadowPasses, 00476 bool shadowCastersNotReceivers) 00477 : mParent(parent) 00478 , mSplitPassesByLightingType(splitPassesByLightingType) 00479 , mSplitNoShadowPasses(splitNoShadowPasses) 00480 , mShadowCastersNotReceivers(shadowCastersNotReceivers) 00481 , mShadowsEnabled(true) 00482 , mOrganisationMode(0) 00483 { 00484 } 00485 00486 ~RenderQueueGroup() { 00487 // destroy contents now 00488 PriorityMap::iterator i; 00489 for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i) 00490 { 00491 OGRE_DELETE i->second; 00492 } 00493 } 00494 00496 PriorityMapIterator getIterator(void) 00497 { 00498 return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end()); 00499 } 00500 00502 void addRenderable(Renderable* pRend, Technique* pTech, ushort priority) 00503 { 00504 // Check if priority group is there 00505 PriorityMap::iterator i = mPriorityGroups.find(priority); 00506 RenderPriorityGroup* pPriorityGrp; 00507 if (i == mPriorityGroups.end()) 00508 { 00509 // Missing, create 00510 pPriorityGrp = OGRE_NEW RenderPriorityGroup(this, 00511 mSplitPassesByLightingType, 00512 mSplitNoShadowPasses, 00513 mShadowCastersNotReceivers); 00514 if (mOrganisationMode) 00515 { 00516 pPriorityGrp->resetOrganisationModes(); 00517 pPriorityGrp->addOrganisationMode((QueuedRenderableCollection::OrganisationMode)mOrganisationMode); 00518 } 00519 00520 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp)); 00521 } 00522 else 00523 { 00524 pPriorityGrp = i->second; 00525 } 00526 00527 // Add 00528 pPriorityGrp->addRenderable(pRend, pTech); 00529 00530 } 00531 00539 void clear(bool destroy = false) 00540 { 00541 PriorityMap::iterator i, iend; 00542 iend = mPriorityGroups.end(); 00543 for (i = mPriorityGroups.begin(); i != iend; ++i) 00544 { 00545 if (destroy) 00546 OGRE_DELETE i->second; 00547 else 00548 i->second->clear(); 00549 } 00550 00551 if (destroy) 00552 mPriorityGroups.clear(); 00553 00554 } 00555 00568 void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; } 00569 00571 bool getShadowsEnabled(void) const { return mShadowsEnabled; } 00572 00576 void setSplitPassesByLightingType(bool split) 00577 { 00578 mSplitPassesByLightingType = split; 00579 PriorityMap::iterator i, iend; 00580 iend = mPriorityGroups.end(); 00581 for (i = mPriorityGroups.begin(); i != iend; ++i) 00582 { 00583 i->second->setSplitPassesByLightingType(split); 00584 } 00585 } 00590 void setSplitNoShadowPasses(bool split) 00591 { 00592 mSplitNoShadowPasses = split; 00593 PriorityMap::iterator i, iend; 00594 iend = mPriorityGroups.end(); 00595 for (i = mPriorityGroups.begin(); i != iend; ++i) 00596 { 00597 i->second->setSplitNoShadowPasses(split); 00598 } 00599 } 00603 void setShadowCastersCannotBeReceivers(bool ind) 00604 { 00605 mShadowCastersNotReceivers = ind; 00606 PriorityMap::iterator i, iend; 00607 iend = mPriorityGroups.end(); 00608 for (i = mPriorityGroups.begin(); i != iend; ++i) 00609 { 00610 i->second->setShadowCastersCannotBeReceivers(ind); 00611 } 00612 } 00619 void resetOrganisationModes(void) 00620 { 00621 mOrganisationMode = 0; 00622 00623 PriorityMap::iterator i, iend; 00624 iend = mPriorityGroups.end(); 00625 for (i = mPriorityGroups.begin(); i != iend; ++i) 00626 { 00627 i->second->resetOrganisationModes(); 00628 } 00629 } 00630 00637 void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om) 00638 { 00639 mOrganisationMode |= om; 00640 00641 PriorityMap::iterator i, iend; 00642 iend = mPriorityGroups.end(); 00643 for (i = mPriorityGroups.begin(); i != iend; ++i) 00644 { 00645 i->second->addOrganisationMode(om); 00646 } 00647 } 00648 00655 void defaultOrganisationMode(void) 00656 { 00657 mOrganisationMode = 0; 00658 00659 PriorityMap::iterator i, iend; 00660 iend = mPriorityGroups.end(); 00661 for (i = mPriorityGroups.begin(); i != iend; ++i) 00662 { 00663 i->second->defaultOrganisationMode(); 00664 } 00665 } 00666 00667 }; 00668 00669 00670 00671 } 00672 00673 #endif 00674 00675
Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 27 22:02:25 2009