CrystalSpace

Public API Reference

csplugincommon/rendermanager/operations.h
Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2007-2008 by Marten Svanfeldt
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public
00015     License along with this library; if not, write to the Free
00016     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 #ifndef __CS_CSPLUGINCOMMON_RENDERMANAGER_OPERATIONS_H__
00020 #define __CS_CSPLUGINCOMMON_RENDERMANAGER_OPERATIONS_H__
00021 
00027 #include "csplugincommon/rendermanager/rendertree.h"
00028 #include "csutil/set.h"
00029 #include "csutil/compositefunctor.h"
00030 
00031 namespace CS
00032 {
00033 namespace RenderManager
00034 {
00035   //-- Tags for information about operations
00037   struct OperationUnordered {};
00039   struct OperationNumbered {};
00041   struct OperationUnorderedParallel {};
00043   struct OperationNumberedParallel {};
00044   
00045 
00046   namespace Implementation
00047   {
00052     template<typename IterationObject>
00053     struct NoOperationBlock
00054     {
00055       void Reset () const
00056       {}
00057 
00058       bool operator() (IterationObject) const
00059       {
00060         return false;
00061       }
00062     };
00063 
00068     template<typename IterationObject>
00069     struct OnceOperationBlock
00070     {     
00071       void Reset ()
00072       {
00073         objectSet.Empty ();
00074       }
00075 
00076       bool operator() (IterationObject obj)
00077       {
00078         if (objectSet.In (obj))
00079           return true;
00080 
00081         objectSet.AddNoTest (obj);
00082         return false;
00083       }
00084 
00085       csSet<IterationObject> objectSet;
00086     };
00087 
00092     template<typename IterationObject>
00093     struct OnceOperationBlockRef
00094     {     
00095       OnceOperationBlockRef (csSet<IterationObject>& set)
00096         : objectSet (set)
00097       {}
00098 
00099       void Reset ()
00100       {
00101         objectSet.Empty ();
00102       }
00103 
00104       bool operator() (IterationObject obj)
00105       {
00106         if (objectSet.In (obj))
00107           return true;
00108 
00109         objectSet.AddNoTest (obj);
00110         return false;
00111       }
00112 
00113       csSet<IterationObject>& objectSet;
00114     };
00115 
00120 #if defined (CS_COMPILER_MSVC) && _MSC_VER < 1310
00121     template<typename Fn, typename OperationBlock>
00122     struct OperationCallerWorkAround
00123     {
00124 
00128       template<typename Type>
00129       struct OperationCaller {};
00130 
00134       template<>
00135       struct OperationCaller<OperationUnordered>
00136       {
00137         OperationCaller (Fn& fn, OperationBlock& block)
00138           : function (fn), block (block)
00139         {}
00140 
00141         template<typename ObjectType>
00142         void operator() (const ObjectType& context)
00143         {
00144           if (!block (context))
00145             function (context);
00146         }
00147 
00148         Fn& function;
00149         OperationBlock block;
00150       };
00151 
00155       template<>
00156       struct OperationCaller<OperationNumbered>
00157       {
00158         OperationCaller (Fn& fn, OperationBlock& block)
00159           : function (fn), block (block), index (0)
00160         {}
00161 
00162         template<typename ObjectType>
00163         void operator() (const ObjectType& context)
00164         {          
00165           if (!block (context))
00166             function (index, context);
00167           index++;
00168         }
00169 
00170         Fn& function;
00171         OperationBlock block;
00172         size_t index;
00173       };
00174 
00175 
00176 
00180       template<>
00181       struct OperationCaller<OperationUnorderedParallel>
00182       {
00183         OperationCaller (Fn& fn, OperationBlock& block)
00184           : function (fn), block (block)
00185         {}
00186 
00187         template<typename ObjectType>
00188         void operator() (const ObjectType& context)
00189         {
00190           if (!block (context))
00191             function (context);
00192         }
00193 
00194         Fn& function;
00195         OperationBlock block;
00196       };
00197 
00201       template<>
00202       struct OperationCaller<OperationNumberedParallel>
00203       {
00204         OperationCaller (Fn& fn, OperationBlock& block)
00205           : function (fn), block (block), index (0)
00206         {}
00207 
00208         template<typename ObjectType>
00209         void operator() (const ObjectType& context)
00210         {          
00211           if (!block (context))
00212             function (index, context);
00213           index++;
00214         }
00215 
00216         Fn& function;
00217         OperationBlock block;
00218         size_t index;
00219       };
00220 
00221 
00222     };
00223 
00224     template<typename Fn, typename OperationBlock, typename Type>
00225     struct OperationCaller : 
00226       public OperationCallerWorkAround<Fn, OperationBlock>::OperationCaller<Type>
00227     {
00228       OperationCaller (Fn& fn, OperationBlock& block)
00229         : OperationCallerWorkAround<Fn, OperationBlock>::OperationCaller<Type> (fn, block)
00230       {}
00231     };
00232 #else
00233 
00236     template<typename Fn, typename OperationBlock, typename Type>
00237     struct OperationCaller
00238     {};
00239 
00243     template<typename Fn, typename OperationBlock>
00244     struct OperationCaller<Fn, OperationBlock, OperationUnordered>
00245     {
00246       OperationCaller (Fn& fn, OperationBlock& block)
00247         : function (fn), block (block)
00248       {}
00249 
00250       template<typename ObjectType>
00251       void operator() (const ObjectType& context)
00252       {
00253         if (!block (context))
00254           function (context);
00255       }
00256 
00257       Fn& function;
00258       OperationBlock block;
00259     };
00260 
00264     template<typename Fn, typename OperationBlock>
00265     struct OperationCaller<Fn, OperationBlock, OperationNumbered>
00266     {
00267       OperationCaller (Fn& fn, OperationBlock& block)
00268         : function (fn), block (block), index (0)
00269       {}
00270 
00271       template<typename ObjectType>
00272       void operator() (const ObjectType& context)
00273       {          
00274         if (!block (context))
00275           function (index, context);
00276         index++;
00277       }
00278 
00279       Fn& function;
00280       OperationBlock block;
00281       size_t index;
00282     };
00283 
00287     template<typename Fn, typename OperationBlock>
00288     struct OperationCaller<Fn, OperationBlock, OperationUnorderedParallel>
00289     {
00290       OperationCaller (Fn& fn, OperationBlock& block)
00291         : function (fn), block (block)
00292       {}
00293 
00294       template<typename ObjectType>
00295       void operator() (const ObjectType& context)
00296       {
00297         if (!block (context))
00298           function (context);
00299       }
00300 
00301       Fn& function;
00302       OperationBlock block;
00303     };
00304 
00308     template<typename Fn, typename OperationBlock>
00309     struct OperationCaller<Fn, OperationBlock, OperationNumberedParallel>
00310     {
00311       OperationCaller (Fn& fn, OperationBlock& block)
00312         : function (fn), block (block), index (0)
00313       {}
00314 
00315       template<typename ObjectType>
00316       void operator() (const ObjectType& context)
00317       {          
00318         if (!block (context))
00319           function (index, context);
00320         index++;
00321       }
00322 
00323       Fn& function;
00324       OperationBlock block;
00325       size_t index;
00326     };
00327 
00328 #endif
00329     
00330     // Helper lookups.. oh god save me from this code...
00331     template<typename Traits1, typename Traits2>
00332     struct OperationTraitsCombiner
00333     {
00334       // Invalid combination
00335     };
00336 
00337     template<>
00338     struct OperationTraitsCombiner<OperationUnordered, OperationUnordered>
00339     {
00340       typedef OperationUnordered Result;
00341     };
00342 
00343     template<>
00344     struct OperationTraitsCombiner<OperationNumbered, OperationNumbered>
00345     {
00346       typedef OperationNumbered Result;
00347     };
00348 
00349     template<>
00350     struct OperationTraitsCombiner<OperationUnorderedParallel, OperationUnorderedParallel>
00351     {
00352       typedef OperationUnorderedParallel Result;
00353     };
00354 
00355     template<>
00356     struct OperationTraitsCombiner<OperationNumberedParallel, OperationNumberedParallel>
00357     {
00358       typedef OperationNumberedParallel Result;
00359     };
00360 
00361     template<>
00362     struct OperationTraitsCombiner<OperationUnorderedParallel, OperationUnordered>
00363     {
00364       typedef OperationUnordered Result;
00365     };
00366     template<>
00367     struct OperationTraitsCombiner<OperationUnordered, OperationUnorderedParallel>
00368     {
00369       typedef OperationUnordered Result;
00370     };
00371 
00372     template<>
00373     struct OperationTraitsCombiner<OperationNumberedParallel, OperationNumbered>
00374     {
00375       typedef OperationNumbered Result;
00376     };
00377     template<>
00378     struct OperationTraitsCombiner<OperationNumbered, OperationNumberedParallel>
00379     {
00380       typedef OperationNumbered Result;
00381     };    
00382   }
00383   
00388   template<typename T>
00389   struct OperationTraits
00390   {
00391     typedef OperationUnordered Ordering;
00392   };
00393 
00395 
00398   template<typename Fn1, typename Fn2>
00399   struct OperationTraits<CS::Meta::CompositeFunctorType2<Fn1, Fn2> >
00400   {
00401     typedef typename Implementation::OperationTraitsCombiner<
00402       typename OperationTraits<Fn1>::Ordering, typename OperationTraits<Fn2>::Ordering
00403     >::Result Ordering;
00404   };
00405 
00409   template<typename Fn1, typename Fn2, typename Fn3>
00410   struct OperationTraits<CS::Meta::CompositeFunctorType3<Fn1, Fn2, Fn3> >
00411   {
00412     typedef typename Implementation::OperationTraitsCombiner<
00413       typename OperationTraits<Fn1>::Ordering, typename OperationTraits<Fn2>::Ordering
00414     >::Result Ordering1;
00415 
00416     typedef typename Implementation::OperationTraitsCombiner<
00417       Ordering1, typename OperationTraits<Fn3>::Ordering
00418     >::Result Ordering;
00419   };
00421 
00422 
00424 
00429   template<typename RenderTree, typename Fn>
00430   void ForEachContext (RenderTree& tree, Fn& fn)
00431   {
00432     // Iterate over all contexts, calling the functor for each one
00433     typename RenderTree::ContextNodeArrayIteratorType it = tree.GetContextIterator ();
00434 
00435     Implementation::NoOperationBlock<typename RenderTree::ContextNode*> noBlock;
00436     // Helper object for calling function
00437     Implementation::OperationCaller<
00438       Fn, 
00439       Implementation::NoOperationBlock<typename RenderTree::ContextNode*>,
00440       typename OperationTraits<Fn>::Ordering
00441     > caller (fn, noBlock);
00442 
00443     while (it.HasNext ())
00444     {
00445       typename RenderTree::ContextNode* context = it.Next ();
00446       CS_ASSERT_MSG("Null context encountered, should not be possible", context);      
00447 
00448       caller (context);
00449     }
00450   }
00451 
00456   template<typename RenderTree, typename Fn, typename Blocker>
00457   void ForEachContext (RenderTree& tree, Fn& fn, Blocker& block)
00458   {
00459     // Iterate over all contexts, calling the functor for each one
00460     typename RenderTree::ContextNodeArrayIteratorType it = tree.GetContextIterator ();
00461 
00462     // Helper object for calling function
00463     Implementation::OperationCaller<
00464       Fn, 
00465       Blocker,
00466       typename OperationTraits<Fn>::Ordering
00467     > caller (fn, block);
00468 
00469     while (it.HasNext ())
00470     {
00471       typename RenderTree::ContextNode* context = it.Next ();
00472       CS_ASSERT_MSG("Null context encountered, should not be possible", context);      
00473 
00474       caller (context);
00475     }
00476   }
00477 
00482   template<typename RenderTree, typename Fn>
00483   void ForEachContextReverse (RenderTree& tree, Fn& fn)
00484   {
00485     // Iterate over all contexts, calling the functor for each one
00486     typename RenderTree::ContextNodeArrayReverseIteratorType it = tree.GetReverseContextIterator ();
00487 
00488     Implementation::NoOperationBlock<typename RenderTree::ContextNode*> noBlock;
00489     // Helper object for calling function
00490     Implementation::OperationCaller<
00491       Fn, 
00492       Implementation::NoOperationBlock<typename RenderTree::ContextNode*>,
00493       typename OperationTraits<Fn>::Ordering
00494     > caller (fn, noBlock);
00495 
00496     while (it.HasNext ())
00497     {
00498       typename RenderTree::ContextNode* context = it.Next ();
00499       CS_ASSERT_MSG("Null context encountered, should not be possible", context);      
00500 
00501       caller (context);
00502     }
00503   }
00504 
00509   template<typename RenderTree, typename Fn, typename Blocker>
00510   void ForEachContextReverse (RenderTree& tree, Fn& fn, Blocker& block)
00511   {
00512     // Iterate over all contexts, calling the functor for each one
00513     typename RenderTree::ContextNodeArrayIteratorType it = tree.GetReverseContextIterator ();
00514 
00515     // Helper object for calling function
00516     Implementation::OperationCaller<
00517       Fn, 
00518       Blocker,
00519       typename OperationTraits<Fn>::Ordering
00520     > caller (fn, block);
00521 
00522     while (it.HasNext ())
00523     {
00524       typename RenderTree::ContextNode* context = it.Next ();
00525       CS_ASSERT_MSG("Null context encountered, should not be possible", context);      
00526 
00527       caller (context);
00528     }
00529   }
00530 
00532 
00534 
00538   template<typename ContextType, typename Fn>
00539   void ForEachMeshNode (ContextType& context, Fn& fn)
00540   {
00541     typename ContextType::TreeType::MeshNodeTreeIteratorType it = context.meshNodes.GetIterator ();
00542 
00543     Implementation::NoOperationBlock<typename ContextType::TreeType::MeshNode*> noBlock;
00544     // Helper object for calling function
00545     Implementation::OperationCaller<
00546       Fn, 
00547       Implementation::NoOperationBlock<typename ContextType::TreeType::MeshNode*>,
00548       typename OperationTraits<Fn>::Ordering
00549     > caller (fn, noBlock);
00550 
00551     while (it.HasNext ())
00552     {
00553       typename ContextType::TreeType::MeshNode* node = it.Next ();
00554       CS_ASSERT_MSG("Null node encountered, should not be possible", node);
00555 
00556       caller (node);
00557     }
00558   }
00559 
00564   template<typename ContextType, typename Fn, typename Blocker>
00565   void ForEachMeshNode (ContextType& context, Fn& fn, Blocker& blocker)
00566   {
00567     typename ContextType::TreeType::MeshNodeTreeIteratorType it = context.meshNodes.GetIterator ();
00568 
00569     // Helper object for calling function
00570     Implementation::OperationCaller<
00571       Fn, 
00572       Blocker,
00573       typename OperationTraits<Fn>::Ordering
00574     > caller (fn, blocker);
00575 
00576     while (it.HasNext ())
00577     {
00578       typename ContextType::TreeType::MeshNode* node = it.Next ();
00579       CS_ASSERT_MSG("Null node encountered, should not be possible", node);
00580 
00581       caller (node);
00582     }
00583   }
00584 
00589   template<typename ContextType, typename Fn>
00590   void ForEachMeshNodeReverse (ContextType& context, Fn& fn)
00591   {
00592     typename ContextType::TreeType::MeshNodeTreeIteratorType it = context.meshNodes.GetReverseIterator ();
00593 
00594     Implementation::NoOperationBlock<typename ContextType::TreeType::MeshNode*> noBlock;
00595     // Helper object for calling function
00596     Implementation::OperationCaller<
00597       Fn, 
00598       Implementation::NoOperationBlock<typename ContextType::TreeType::MeshNode*>,
00599       typename OperationTraits<Fn>::Ordering
00600     > caller (fn, noBlock);
00601 
00602     while (it.HasNext ())
00603     {
00604       typename ContextType::TreeType::MeshNode* node = it.Next ();
00605       CS_ASSERT_MSG("Null node encountered, should not be possible", node);
00606 
00607       caller (node);
00608     }
00609   }
00610 
00615   template<typename ContextType, typename Fn, typename Blocker>
00616   void ForEachMeshNodeReverse (ContextType& context, Fn& fn, Blocker& blocker)
00617   {
00618     typename ContextType::TreeType::MeshNodeTreeIteratorType it = context.meshNodes.GetReverseIterator ();
00619 
00620     // Helper object for calling function
00621     Implementation::OperationCaller<
00622       Fn, 
00623       Blocker,
00624       typename OperationTraits<Fn>::Ordering
00625     > caller (fn, blocker);
00626 
00627     while (it.HasNext ())
00628     {
00629       typename ContextType::TreeType::MeshNode* node = it.Next ();
00630       CS_ASSERT_MSG("Null node encountered, should not be possible", node);
00631 
00632       caller (node);
00633     }
00634   }
00635 
00636   namespace Implementation
00637   {
00638     template<typename ContextType, typename MeshFn, typename Blocker>
00639     struct MeshContextTraverser
00640     {
00641       MeshContextTraverser (MeshFn& fn, Blocker& blocker)
00642         : fn (fn), blocker (blocker)
00643       {}
00644 
00645       void operator() (ContextType* context)
00646       {
00647         ForEachMeshNode (*context, fn, blocker);
00648       }
00649 
00650       MeshFn& fn;
00651       Blocker& blocker;
00652     };
00653   }
00654 
00656  
00657 
00658 
00659 
00661 
00665   template<typename RenderTree>
00666   class SingleMeshContextNumbering
00667   {
00668   public:
00669     SingleMeshContextNumbering ()
00670       : meshIndex (0)
00671     {}
00672 
00673     void operator () (size_t, typename RenderTree::MeshNode* node)
00674     {
00675       for (size_t i = 0; i < node->meshes.GetSize(); ++i)
00676       {
00677         node->meshes[i].contextLocalId = meshIndex++;
00678       }
00679     }
00680 
00681   private:
00682     size_t meshIndex;
00683   };
00684 
00685   template<typename RenderTree>
00686   struct OperationTraits<SingleMeshContextNumbering<RenderTree> >
00687   {
00688     typedef OperationNumbered Ordering;
00689   };
00691 
00692 }
00693 }
00694 
00695 
00696 
00697 #endif

Generated for Crystal Space 2.0 by doxygen 1.7.6.1