00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_CSPLUGINCOMMON_RENDERMANAGER_RENDERTREE_H__
00020 #define __CS_CSPLUGINCOMMON_RENDERMANAGER_RENDERTREE_H__
00021
00026 #include "iengine/camera.h"
00027 #include "csplugincommon/rendermanager/standardtreetraits.h"
00028 #include "csutil/dirtyaccessarray.h"
00029 #include "csutil/metautils.h"
00030 #include "csutil/redblacktree.h"
00031 #include "cstool/rendermeshholder.h"
00032
00033 struct iMeshWrapper;
00034 struct iPortalContainer;
00035
00036 namespace CS
00037 {
00038 namespace RenderManager
00039 {
00040 class PostEffectManager;
00041
00046 class CS_CRYSTALSPACE_EXPORT RenderTreeBase
00047 {
00048 public:
00049 struct CS_CRYSTALSPACE_EXPORT DebugPersistent
00050 {
00051 DebugPersistent ();
00052
00053 uint RegisterDebugFlag (const char* string);
00054 uint QueryDebugFlag (const char* string);
00055
00056 bool IsDebugFlagEnabled (uint flag);
00057 void EnableDebugFlag (uint flag, bool state);
00058 protected:
00059 uint nextDebugId;
00060 csHash<uint, csString> debugIdMappings;
00061 csHash<csArray<uint>, uint> debugIdChildren;
00062 csBitArray debugFlags;
00063 };
00064
00065 protected:
00066 struct DebugTexture
00067 {
00068 csRef<iTextureHandle> texh;
00069 float aspect;
00070 };
00071 csArray<DebugTexture> debugTextures;
00072 DebugPersistent& debugPersist;
00073
00074 RenderTreeBase (DebugPersistent& debugPersist)
00075 : debugPersist (debugPersist) {}
00076 public:
00085 uint RegisterDebugFlag (const char* string)
00086 { return debugPersist.RegisterDebugFlag (string); }
00091 uint QueryDebugFlag (const char* string)
00092 { return debugPersist.QueryDebugFlag (string); }
00093
00095 bool IsDebugFlagEnabled (uint flag) const
00096 { return debugPersist.IsDebugFlagEnabled (flag); }
00103 void EnableDebugFlag (uint flag, bool state)
00104 { debugPersist.EnableDebugFlag (flag, state); }
00111 void EnableDebugFlag (const char* flagStr, bool state)
00112 {
00113 uint flag = RegisterDebugFlag (flagStr);
00114 EnableDebugFlag (flag, state);
00115 }
00124 void AddDebugTexture (iTextureHandle* tex, float aspect = 1.0f);
00129 void RenderDebugTextures (iGraphics3D* g3d);
00131
00133
00136
00137 void AddDebugLine3D (const csVector3& v1, const csVector3& v2,
00138 const csColor& color1, const csColor& color2);
00143 void AddDebugLine3DTF (const csVector3& v1, const csVector3& v2,
00144 const csTransform& toWorldSpace,
00145 const csColor& color1, const csColor& color2);
00150 void AddDebugBBox (const csBox3& box,
00151 const csTransform& toWorldSpace,
00152 const csColor& col);
00157 void AddDebugPlane (const csPlane3& _plane,
00158 const csTransform& toWorldSpace,
00159 const csColor& col,
00160 const csVector3& linesOrg = csVector3 (0));
00164 void AddDebugClipPlanes (RenderView* view);
00165
00166 struct DebugLines
00167 {
00168 csDirtyAccessArray<csVector3> verts;
00169 csDirtyAccessArray<csVector4> colors;
00170 };
00172 const DebugLines& GetDebugLines () const { return debugLines; }
00177 void SetDebugLines (const DebugLines& lines) { debugLines = lines; }
00179
00180
00182
00188 void AddDebugLineScreen (const csVector2& v1, const csVector2& v2,
00189 csRGBcolor color);
00191
00196 void DrawDebugLines (iGraphics3D* g3d, RenderView* view);
00197 protected:
00198 DebugLines debugLines;
00199 struct DebugLineScreen
00200 {
00201 csVector2 v1, v2;
00202 csRGBcolor color;
00203 };
00204 csArray<DebugLineScreen> debugLinesScreen;
00205 };
00206
00219 template<typename TreeTraits = RenderTreeStandardTraits>
00220 class RenderTree : public RenderTreeBase
00221 {
00222 public:
00223
00224 struct MeshNode;
00225 struct ContextNode;
00226 struct ContextsContainer;
00227
00228
00229 typedef TreeTraits TreeTraitsType;
00230 typedef RenderTree<TreeTraitsType> ThisType;
00231 typedef RenderTree<TreeTraitsType> RealTreeType;
00232
00233
00234 typedef csFixedSizeAllocator<
00235 csRedBlackTreeMap<typename TreeTraitsType::MeshNodeKeyType,
00236 MeshNode*>::allocationUnitSize> MeshNodeTreeBlockAlloc;
00237 typedef CS::Memory::AllocatorRef<MeshNodeTreeBlockAlloc>
00238 MeshNodeTreeBlockRefAlloc;
00239 typedef csRedBlackTreeMap<typename TreeTraitsType::MeshNodeKeyType, MeshNode*,
00240 MeshNodeTreeBlockRefAlloc> MeshNodeTreeType;
00241 typedef typename MeshNodeTreeType::Iterator MeshNodeTreeIteratorType;
00242 typedef csArray<ContextNode*> ContextNodeArrayType;
00243 typedef typename ContextNodeArrayType::Iterator ContextNodeArrayIteratorType;
00244 typedef typename ContextNodeArrayType::ReverseIterator ContextNodeArrayReverseIteratorType;
00245
00246
00252 struct PersistentData :
00253 public CS::Meta::EBOptHelper<typename TreeTraitsType::PersistentDataExtraDataType>
00254 {
00260 void Initialize (iShaderManager* shmgr)
00261 {
00262 svObjectToWorldName =
00263 shmgr->GetSVNameStringset()->Request ("object2world transform");
00264 svObjectToWorldInvName =
00265 shmgr->GetSVNameStringset()->Request ("object2world transform inverse");
00266 svFogplaneName =
00267 shmgr->GetSVNameStringset()->Request ("fogplane");
00268
00269 dbgDebugClearScreen = debugPersist.RegisterDebugFlag ("debugclear");
00270 }
00271
00272 void Clear ()
00273 {
00274
00275 contextNodeAllocator.Empty ();
00276 meshNodeAllocator.Empty ();
00277 }
00278
00279 csBlockAllocator<MeshNode> meshNodeAllocator;
00280 csBlockAllocator<ContextNode> contextNodeAllocator;
00281 MeshNodeTreeBlockAlloc meshNodeTreeAlloc;
00282
00283 CS::ShaderVarStringID svObjectToWorldName;
00284 CS::ShaderVarStringID svObjectToWorldInvName;
00285 CS::ShaderVarStringID svFogplaneName;
00286
00287 CS::RenderManager::RenderViewCache renderViews;
00288 csRenderMeshHolder rmHolder;
00289
00290 DebugPersistent debugPersist;
00291 uint dbgDebugClearScreen;
00292 };
00293
00298 struct MeshNode :
00299 public CS::Meta::EBOptHelper<typename TreeTraitsType::MeshNodeExtraDataType>
00300 {
00304 struct SingleMesh :
00305 public CS::Meta::EBOptHelper<typename TreeTraitsType::MeshExtraDataType>
00306 {
00308 iMeshWrapper* meshWrapper;
00310 csRenderMesh* renderMesh;
00312 csZBufMode zmode;
00314 iShaderVariableContext* meshObjSVs;
00316 csRef<csShaderVariable> svObjectToWorld;
00318 csRef<csShaderVariable> svObjectToWorldInv;
00320 csFlags meshFlags;
00321
00323 size_t contextLocalId;
00324
00329
00330 size_t preCopyNum;
00332 csRenderTargetAttachment preCopyAttachments[rtaNumAttachments];
00334 iTextureHandle* preCopyTextures[rtaNumAttachments];
00337 SingleMesh () : preCopyNum (0) {}
00338 };
00339
00340
00341 typedef RealTreeType TreeType;
00342 typedef typename TreeType::ContextNode ContextNodeType;
00343
00344
00345 typedef csArray<SingleMesh> MeshArrayType;
00346 typedef typename MeshArrayType::Iterator MeshArrayIteratorType;
00347
00349 ContextNode& GetOwner() const { return *owner; }
00350
00352 typename TreeTraitsType::MeshNodeKeyType key;
00353
00355 int sorting;
00356
00358 MeshArrayType meshes;
00359
00360 MeshNode (ContextNode& owner)
00361 : owner (&owner)
00362 {}
00363 protected:
00364 ContextNode* owner;
00365
00366 friend struct ContextNode;
00367 };
00368
00375 struct ContextNode : public CS::Meta::EBOptHelper<typename TreeTraits::ContextNodeExtraDataType>
00376 {
00380 struct PortalHolder
00381 {
00382 #ifdef CS_DEBUG
00383
00384 const char* db_mesh_name;
00385 #endif
00386
00387 iPortalContainer* portalContainer;
00389 iMeshWrapper* meshWrapper;
00390 };
00391
00392
00393 typedef RealTreeType TreeType;
00394
00396 TreeType& owner;
00397
00399 csRef<RenderView> renderView;
00401 struct TargetTexture
00402 {
00404 iTextureHandle* texHandle;
00406 int subtexture;
00407
00408 TargetTexture() : texHandle (0), subtexture (0) {}
00409 };
00411 TargetTexture renderTargets[rtaNumAttachments];
00416 CS::Math::Matrix4 perspectiveFixup;
00418 csReversibleTransform cameraTransform;
00420 int drawFlags;
00422 iSector* sector;
00424 csRef<csShaderVariable> svFogplane;
00426 csRef<iShaderVariableContext> shadervars;
00428 CS::RenderPriorityGrouping renderGrouping;
00429
00431 csRef<PostEffectManager> postEffects;
00432
00434 MeshNodeTreeType meshNodes;
00435
00437 csArray<PortalHolder> allPortals;
00438
00440 SVArrayHolder svArrays;
00441
00443 csDirtyAccessArray<iShader*> shaderArray;
00445 csArray<size_t> ticketArray;
00446
00448 size_t totalRenderMeshes;
00449
00450 ContextNode(TreeType& owner, MeshNodeTreeBlockAlloc& meshNodeAlloc)
00451 : owner (owner), drawFlags (0),
00452 renderGrouping (CS::rpgByLayer),
00453 meshNodes (MeshNodeTreeBlockRefAlloc (meshNodeAlloc)),
00454 totalRenderMeshes (0)
00455 {}
00456
00460 void AddRenderMesh (csRenderMesh* rm,
00461 CS::Graphics::RenderPriority renderPrio,
00462 typename MeshNode::SingleMesh& singleMeshTemplate)
00463 {
00464 typename TreeTraits::MeshNodeKeyType meshKey =
00465 TreeTraits::GetMeshNodeKey (renderPrio, *rm, owner.GetPersistentData ());
00466
00467
00468 MeshNode* meshNode = meshNodes.Get (meshKey, 0);
00469 if (!meshNode)
00470 {
00471
00472 meshNode = owner.CreateMeshNode (*this, meshKey);
00473
00474 RenderTree::TreeTraitsType::SetupMeshNode(*meshNode, renderPrio, *rm,
00475 owner.GetPersistentData ());
00476 meshNodes.Put (meshKey, meshNode);
00477 }
00478
00479 csRef<csShaderVariable> svObjectToWorld;
00480 svObjectToWorld.AttachNew (new csShaderVariable (
00481 owner.GetPersistentData ().svObjectToWorldName));
00482 svObjectToWorld->SetValue (rm->object2world);
00483 csRef<csShaderVariable> svObjectToWorldInv;
00484 svObjectToWorldInv.AttachNew (new csShaderVariable (
00485 owner.GetPersistentData ().svObjectToWorldInvName));
00486 svObjectToWorldInv->SetValue (rm->object2world.GetInverse());
00487
00488 typename MeshNode::SingleMesh sm (singleMeshTemplate);
00489 sm.renderMesh = rm;
00490 sm.svObjectToWorld = svObjectToWorld;
00491 sm.svObjectToWorldInv = svObjectToWorldInv;
00492 if (rm->z_buf_mode != (csZBufMode)~0)
00493 sm.zmode = rm->z_buf_mode;
00494
00495 meshNode->meshes.Push (sm);
00496 totalRenderMeshes++;
00497 }
00498
00499 void MoveRenderMeshes (MeshNodeTreeIteratorType& sourceMeshNode,
00500 ContextNode* targetContext)
00501 {
00502 typename TreeTraits::MeshNodeKeyType srcKey;
00503 MeshNode* srcNode = sourceMeshNode.PeekNext (srcKey);
00504
00505 CS_ASSERT(!targetContext->meshNodes.Get (srcKey, nullptr));
00506 size_t nodeMeshes = srcNode->meshes.GetSize ();
00507 srcNode->owner = targetContext;
00508 targetContext->meshNodes.Put (srcKey, srcNode);
00509 totalRenderMeshes -= nodeMeshes;
00510 targetContext->totalRenderMeshes += nodeMeshes;
00511
00512 meshNodes.Delete (sourceMeshNode);
00513 }
00514
00516 void InsertLayer (size_t after)
00517 {
00518 const size_t layerCount = shaderArray.GetSize() / totalRenderMeshes;
00519 shaderArray.SetSize (shaderArray.GetSize() + totalRenderMeshes);
00520 const size_t layerOffsetNew = (after + 1) * totalRenderMeshes;
00521 memmove (shaderArray.GetArray() + layerOffsetNew + totalRenderMeshes,
00522 shaderArray.GetArray() + layerOffsetNew,
00523 totalRenderMeshes * (layerCount - after - 1) * sizeof(csShaderVariable*));
00524 memset (shaderArray.GetArray() + layerOffsetNew, 0,
00525 totalRenderMeshes * sizeof(csShaderVariable*));
00526
00527 svArrays.InsertLayer (after, after);
00528 }
00529
00534 void CopyLayerShader (size_t meshId, size_t fromLayer, size_t toLayer)
00535 {
00536 const size_t fromLayerOffset = fromLayer * totalRenderMeshes;
00537 const size_t toLayerOffset = toLayer * totalRenderMeshes;
00538 shaderArray[toLayerOffset + meshId] =
00539 shaderArray[fromLayerOffset + meshId];
00540 }
00541
00545 bool GetTargetDimensions (int& renderW, int& renderH)
00546 {
00547 for (int a = 0; a < rtaNumAttachments; a++)
00548 {
00549 if (renderTargets[a].texHandle != 0)
00550 {
00551 renderTargets[a].texHandle->GetRendererDimensions (
00552 renderW, renderH);
00553 return true;
00554 }
00555 }
00556 if (renderView.IsValid())
00557 {
00558 iGraphics3D* g3d = renderView->GetGraphics3D();
00559 if (g3d)
00560 {
00561 renderW = g3d->GetWidth();
00562 renderH = g3d->GetHeight();
00563 }
00564 }
00565 return false;
00566 }
00567 };
00568
00569
00570
00571 RenderTree (PersistentData& dataStorage)
00572 : RenderTreeBase (dataStorage.debugPersist), persistentData (dataStorage)
00573 {
00574 }
00575
00576 ~RenderTree ()
00577 {
00578 persistentData.Clear ();
00579 }
00580
00588 ContextNode* CreateContext (RenderView* rw, ContextNode* insertAfter = 0)
00589 {
00590
00591 ContextNode* newCtx = persistentData.contextNodeAllocator.Alloc (*this,
00592 persistentData.meshNodeTreeAlloc);
00593 newCtx->renderView = rw;
00594 newCtx->cameraTransform = rw->GetCamera ()->GetTransform ();
00595 newCtx->sector = rw->GetThisSector();
00596
00597 if (insertAfter)
00598 {
00599 size_t n = contexts.Find (insertAfter);
00600 CS_ASSERT(n != csArrayItemNotFound);
00601 contexts.Insert (n+1, newCtx);
00602 }
00603 else
00604 {
00605 contexts.Push (newCtx);
00606 }
00607
00608 return newCtx;
00609 }
00610
00614 void DestroyContext (ContextNode* context)
00615 {
00616 CS_ASSERT(contexts.Find (context) != csArrayItemNotFound);
00617 contexts.Delete (context);
00618
00619 persistentData.contextNodeAllocator.Free (context);
00620 }
00621
00626 ContextNode* CloneContext (ContextNode* context)
00627 {
00628
00629 ContextNode* newCtx = persistentData.contextNodeAllocator.Alloc (*this,
00630 persistentData.meshNodeTreeAlloc);
00631 newCtx->renderView = context->renderView;
00632 memcpy (newCtx->renderTargets, context->renderTargets, sizeof (newCtx->renderTargets));
00633 newCtx->perspectiveFixup = context->perspectiveFixup;
00634 newCtx->cameraTransform = context->cameraTransform;
00635 newCtx->drawFlags = context->drawFlags;
00636 newCtx->renderGrouping = context->renderGrouping;
00637 newCtx->sector = context->sector;
00638 newCtx->svFogplane = context->svFogplane;
00639 newCtx->shadervars = context->shadervars;
00640 newCtx->postEffects = context->postEffects;
00641
00642 size_t n = contexts.Find (context);
00643 CS_ASSERT(n != csArrayItemNotFound);
00644 contexts.Insert (n, newCtx);
00645
00646 return newCtx;
00647 }
00648
00652 ContextNodeArrayIteratorType GetContextIterator ()
00653 {
00654 return contexts.GetIterator ();
00655 }
00656
00660 ContextNodeArrayReverseIteratorType GetReverseContextIterator ()
00661 {
00662 return contexts.GetReverseIterator ();
00663 }
00664
00668 MeshNode* CreateMeshNode (ContextNode& context,
00669 const typename TreeTraitsType::MeshNodeKeyType& key)
00670 {
00671 MeshNode* newNode = persistentData.meshNodeAllocator.Alloc (context);
00672 newNode->key = key;
00673
00674 return newNode;
00675 }
00676
00677
00681 void DestroyMeshNode (MeshNode* meshNode)
00682 {
00683 meshNode->owner.meshNodes.Delete (meshNode->key);
00684 persistentData.meshNodeAllocator.Free (meshNode);
00685 }
00686
00687
00689 bool IsDebugClearEnabled () const
00690 {
00691 return IsDebugFlagEnabled (persistentData.dbgDebugClearScreen);
00692 }
00693
00694 PersistentData& GetPersistentData()
00695 {
00696 return persistentData;
00697 }
00698 const PersistentData& GetPersistentData() const
00699 {
00700 return persistentData;
00701 }
00702
00703 protected:
00704 PersistentData& persistentData;
00705 ContextNodeArrayType contexts;
00706 };
00707
00708 }
00709 }
00710
00711
00712
00713 #endif