00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
00331 template<typename Traits1, typename Traits2>
00332 struct OperationTraitsCombiner
00333 {
00334
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
00433 typename RenderTree::ContextNodeArrayIteratorType it = tree.GetContextIterator ();
00434
00435 Implementation::NoOperationBlock<typename RenderTree::ContextNode*> noBlock;
00436
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
00460 typename RenderTree::ContextNodeArrayIteratorType it = tree.GetContextIterator ();
00461
00462
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
00486 typename RenderTree::ContextNodeArrayReverseIteratorType it = tree.GetReverseContextIterator ();
00487
00488 Implementation::NoOperationBlock<typename RenderTree::ContextNode*> noBlock;
00489
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
00513 typename RenderTree::ContextNodeArrayIteratorType it = tree.GetReverseContextIterator ();
00514
00515
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
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
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
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
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