csplugincommon/rendermanager/operations.h Source File (Crystal Space 2.0 Public API Reference)

| ## Public API Reference

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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