csplugincommon/rendermanager/rendertree.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_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 //---- Forward declarations 00224 struct MeshNode; 00225 struct ContextNode; 00226 struct ContextsContainer; 00227 00228 //---- Type definitions 00229 typedef TreeTraits TreeTraitsType; 00230 typedef RenderTree<TreeTraitsType> ThisType; 00231 typedef RenderTree<TreeTraitsType> RealTreeType; 00232 00233 //---- Internal types 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 // Clean up the persistent data 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 //-- Types 00341 typedef RealTreeType TreeType; 00342 typedef typename TreeType::ContextNode ContextNodeType; 00343 00344 //-- Some local types 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 00384 const char* db_mesh_name; 00385 #endif 00387 iPortalContainer* portalContainer; 00389 iMeshWrapper* meshWrapper; 00390 }; 00391 00392 //-- Types 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 // Get the mesh node 00468 MeshNode* meshNode = meshNodes.Get (meshKey, 0); 00469 if (!meshNode) 00470 { 00471 // Get a new one 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 //---- Methods 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 // Create an initial context 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 // Create an initial context 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; // should that be copied? 00639 newCtx->shadervars = context->shadervars; // should that be copied? 00640 newCtx->postEffects = context->postEffects; // should that be copied? 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
Generated for Crystal Space 2.0 by doxygen 1.6.1