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; 00468 00469 00470 public: 00471 RenderQueueGroup(RenderQueue* parent, 00472 bool splitPassesByLightingType, 00473 bool splitNoShadowPasses, 00474 bool shadowCastersNotReceivers) 00475 : mParent(parent) 00476 , mSplitPassesByLightingType(splitPassesByLightingType) 00477 , mSplitNoShadowPasses(splitNoShadowPasses) 00478 , mShadowCastersNotReceivers(shadowCastersNotReceivers) 00479 , mShadowsEnabled(true) 00480 { 00481 } 00482 00483 ~RenderQueueGroup() { 00484 // destroy contents now 00485 PriorityMap::iterator i; 00486 for (i = mPriorityGroups.begin(); i != mPriorityGroups.end(); ++i) 00487 { 00488 OGRE_DELETE i->second; 00489 } 00490 } 00491 00493 PriorityMapIterator getIterator(void) 00494 { 00495 return PriorityMapIterator(mPriorityGroups.begin(), mPriorityGroups.end()); 00496 } 00497 00499 void addRenderable(Renderable* pRend, Technique* pTech, ushort priority) 00500 { 00501 // Check if priority group is there 00502 PriorityMap::iterator i = mPriorityGroups.find(priority); 00503 RenderPriorityGroup* pPriorityGrp; 00504 if (i == mPriorityGroups.end()) 00505 { 00506 // Missing, create 00507 pPriorityGrp = OGRE_NEW RenderPriorityGroup(this, 00508 mSplitPassesByLightingType, 00509 mSplitNoShadowPasses, 00510 mShadowCastersNotReceivers); 00511 mPriorityGroups.insert(PriorityMap::value_type(priority, pPriorityGrp)); 00512 } 00513 else 00514 { 00515 pPriorityGrp = i->second; 00516 } 00517 00518 // Add 00519 pPriorityGrp->addRenderable(pRend, pTech); 00520 00521 } 00522 00530 void clear(bool destroy = false) 00531 { 00532 PriorityMap::iterator i, iend; 00533 iend = mPriorityGroups.end(); 00534 for (i = mPriorityGroups.begin(); i != iend; ++i) 00535 { 00536 if (destroy) 00537 OGRE_DELETE i->second; 00538 else 00539 i->second->clear(); 00540 } 00541 00542 if (destroy) 00543 mPriorityGroups.clear(); 00544 00545 } 00546 00559 void setShadowsEnabled(bool enabled) { mShadowsEnabled = enabled; } 00560 00562 bool getShadowsEnabled(void) const { return mShadowsEnabled; } 00563 00567 void setSplitPassesByLightingType(bool split) 00568 { 00569 mSplitPassesByLightingType = split; 00570 PriorityMap::iterator i, iend; 00571 iend = mPriorityGroups.end(); 00572 for (i = mPriorityGroups.begin(); i != iend; ++i) 00573 { 00574 i->second->setSplitPassesByLightingType(split); 00575 } 00576 } 00581 void setSplitNoShadowPasses(bool split) 00582 { 00583 mSplitNoShadowPasses = split; 00584 PriorityMap::iterator i, iend; 00585 iend = mPriorityGroups.end(); 00586 for (i = mPriorityGroups.begin(); i != iend; ++i) 00587 { 00588 i->second->setSplitNoShadowPasses(split); 00589 } 00590 } 00594 void setShadowCastersCannotBeReceivers(bool ind) 00595 { 00596 mShadowCastersNotReceivers = ind; 00597 PriorityMap::iterator i, iend; 00598 iend = mPriorityGroups.end(); 00599 for (i = mPriorityGroups.begin(); i != iend; ++i) 00600 { 00601 i->second->setShadowCastersCannotBeReceivers(ind); 00602 } 00603 } 00610 void resetOrganisationModes(void) 00611 { 00612 PriorityMap::iterator i, iend; 00613 iend = mPriorityGroups.end(); 00614 for (i = mPriorityGroups.begin(); i != iend; ++i) 00615 { 00616 i->second->resetOrganisationModes(); 00617 } 00618 } 00619 00626 void addOrganisationMode(QueuedRenderableCollection::OrganisationMode om) 00627 { 00628 PriorityMap::iterator i, iend; 00629 iend = mPriorityGroups.end(); 00630 for (i = mPriorityGroups.begin(); i != iend; ++i) 00631 { 00632 i->second->addOrganisationMode(om); 00633 } 00634 } 00635 00642 void defaultOrganisationMode(void) 00643 { 00644 PriorityMap::iterator i, iend; 00645 iend = mPriorityGroups.end(); 00646 for (i = mPriorityGroups.begin(); i != iend; ++i) 00647 { 00648 i->second->defaultOrganisationMode(); 00649 } 00650 } 00651 00652 }; 00653 00654 00655 00656 } 00657 00658 #endif 00659 00660
Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Tue Nov 4 11:02:32 2008