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(const 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(const Renderable* r) = 0; 00095 00096 00097 }; 00098 00108 class _OgreExport QueuedRenderableCollection 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 (ie 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 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 mTransparents; 00334 00336 void removePassEntry(Pass* p); 00337 00339 void addSolidRenderable(Technique* pTech, Renderable* rend, bool toNoShadowMap); 00341 void addSolidRenderableSplitByLightType(Technique* pTech, Renderable* rend); 00343 void addTransparentRenderable(Technique* pTech, Renderable* rend); 00344 00345 public: 00346 RenderPriorityGroup(RenderQueueGroup* parent, 00347 bool splitPassesByLightingType, 00348 bool splitNoShadowPasses, 00349 bool shadowCastersNotReceivers); 00350 00351 ~RenderPriorityGroup() { } 00352 00357 const QueuedRenderableCollection& getSolidsBasic(void) const 00358 { return mSolidsBasic; } 00361 const QueuedRenderableCollection& getSolidsDiffuseSpecular(void) const 00362 { return mSolidsDiffuseSpecular; } 00365 const QueuedRenderableCollection& getSolidsDecal(void) const 00366 { return mSolidsDecal; } 00369 const QueuedRenderableCollection& getSolidsNoShadowReceive(void) const 00370 { return mSolidsNoShadowReceive; } 00372 const QueuedRenderableCollection& getTransparents(void) const 00373 { return mTransparents; } 00374 00375 00382 void resetOrganisationModes(void); 00383 00390 void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om); 00391 00398 void defaultOrganisationMode(void); 00399 00401 void addRenderable(Renderable* pRend, Technique* pTech); 00402 00405 void sort(const Camera* cam); 00406 00409 void clear(void); 00410 00414 void setSplitPassesByLightingType(bool split) 00415 { 00416 mSplitPassesByLightingType = split; 00417 } 00418 00422 void setSplitNoShadowPasses(bool split) 00423 { 00424 mSplitNoShadowPasses = split; 00425 } 00426 00430 void setShadowCastersCannotBeReceivers(bool ind) 00431 { 00432 mShadowCastersNotReceivers = ind; 00433 } 00434 00435 00436 00437 }; 00438 00439 00447 class _OgreExport RenderQueueGroup 00448 { 00449 public: 00450 typedef std::map<ushort, RenderPriorityGroup*, std::less<ushort> > PriorityMap; 00451 typedef MapIterator<PriorityMap> PriorityMapIterator; 00452 protected: 00453 RenderQueue* mParent; 00454 bool mSplitPassesByLightingType; 00455 bool mSplitNoShadowPasses; 00456 bool mShadowCastersNotReceivers; 00458 PriorityMap mPriorityGroups; 00460 bool mShadowsEnabled; 00461 00462 00463 public: 00464 RenderQueueGroup(RenderQueue* parent, 00465 bool splitPassesByLightingType, 00466 bool splitNoShadowPasses, 00467 bool shadowCastersNotReceivers) 00468 : mParent(parent) 00469 , mSplitPassesByLightingType(splitPassesByLightingType) 00470 , mSplitNoShadowPasses(splitNoShadowPasses) 00471 , mShadowCastersNotReceivers(shadowCastersNotReceivers) 00472 , mShadowsEnabled(true) 00473 { 00474 } 00475 00476 ~RenderQueueGroup() { 00477 // destroy contents now 00478 PriorityMap::iterator i; 00479 for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i) 00480 { 00481 delete i->second; 00482 } 00483 } 00484 00486 PriorityMapIterator getIterator(void) 00487 { 00488 return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end()); 00489 } 00490 00492 void addRenderable(Renderable* pRend, Technique* pTech, ushort priority) 00493 { 00494 // Check if priority group is there 00495 PriorityMap::iterator i = mPriorityGroups.find(priority); 00496 RenderPriorityGroup* pPriorityGrp; 00497 if (i == mPriorityGroups.end()) 00498 { 00499 // Missing, create 00500 pPriorityGrp = new RenderPriorityGroup(this, 00501 mSplitPassesByLightingType, 00502 mSplitNoShadowPasses, 00503 mShadowCastersNotReceivers); 00504 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp)); 00505 } 00506 else 00507 { 00508 pPriorityGrp = i->second; 00509 } 00510 00511 // Add 00512 pPriorityGrp->addRenderable(pRend, pTech); 00513 00514 } 00515 00523 void clear(bool destroy = false) 00524 { 00525 PriorityMap::iterator i, iend; 00526 iend = mPriorityGroups.end(); 00527 for (i = mPriorityGroups.begin(); i != iend; ++i) 00528 { 00529 if (destroy) 00530 delete i->second; 00531 else 00532 i->second->clear(); 00533 } 00534 00535 if (destroy) 00536 mPriorityGroups.clear(); 00537 00538 } 00539 00552 void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; } 00553 00555 bool getShadowsEnabled(void) const { return mShadowsEnabled; } 00556 00560 void setSplitPassesByLightingType(bool split) 00561 { 00562 mSplitPassesByLightingType = split; 00563 PriorityMap::iterator i, iend; 00564 iend = mPriorityGroups.end(); 00565 for (i = mPriorityGroups.begin(); i != iend; ++i) 00566 { 00567 i->second->setSplitPassesByLightingType(split); 00568 } 00569 } 00574 void setSplitNoShadowPasses(bool split) 00575 { 00576 mSplitNoShadowPasses = split; 00577 PriorityMap::iterator i, iend; 00578 iend = mPriorityGroups.end(); 00579 for (i = mPriorityGroups.begin(); i != iend; ++i) 00580 { 00581 i->second->setSplitNoShadowPasses(split); 00582 } 00583 } 00587 void setShadowCastersCannotBeReceivers(bool ind) 00588 { 00589 mShadowCastersNotReceivers = ind; 00590 PriorityMap::iterator i, iend; 00591 iend = mPriorityGroups.end(); 00592 for (i = mPriorityGroups.begin(); i != iend; ++i) 00593 { 00594 i->second->setShadowCastersCannotBeReceivers(ind); 00595 } 00596 } 00603 void resetOrganisationModes(void) 00604 { 00605 PriorityMap::iterator i, iend; 00606 iend = mPriorityGroups.end(); 00607 for (i = mPriorityGroups.begin(); i != iend; ++i) 00608 { 00609 i->second->resetOrganisationModes(); 00610 } 00611 } 00612 00619 void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om) 00620 { 00621 PriorityMap::iterator i, iend; 00622 iend = mPriorityGroups.end(); 00623 for (i = mPriorityGroups.begin(); i != iend; ++i) 00624 { 00625 i->second->addOrganisationMode(om); 00626 } 00627 } 00628 00635 void defaultOrganisationMode(void) 00636 { 00637 PriorityMap::iterator i, iend; 00638 iend = mPriorityGroups.end(); 00639 for (i = mPriorityGroups.begin(); i != iend; ++i) 00640 { 00641 i->second->defaultOrganisationMode(); 00642 } 00643 } 00644 00645 }; 00646 00647 00648 00649 } 00650 00651 #endif 00652 00653
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Thu Dec 27 15:19:16 2007