00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_CSPLUGINCOMMON_RENDERMANAGER_PORTALSETUP_H__
00020 #define __CS_CSPLUGINCOMMON_RENDERMANAGER_PORTALSETUP_H__
00021
00026 #include "iengine/movable.h"
00027 #include "iengine/portal.h"
00028 #include "iengine/portalcontainer.h"
00029 #include "iengine/sector.h"
00030 #include "csgeom/math3d.h"
00031 #include "csgeom/polyclip.h"
00032 #include "csgfx/renderbuffer.h"
00033 #include "csgfx/shadervarcontext.h"
00034 #include "cstool/rbuflock.h"
00035
00036 #include "csplugincommon/rendermanager/renderview.h"
00037 #include "csplugincommon/rendermanager/svsetup.h"
00038 #include "csplugincommon/rendermanager/texturecache.h"
00039
00040 namespace CS
00041 {
00042 namespace RenderManager
00043 {
00049 class CS_CRYSTALSPACE_EXPORT StandardPortalSetup_Base
00050 {
00051 public:
00057 struct CS_CRYSTALSPACE_EXPORT PersistentData
00058 {
00059
00063 struct PortalBuffers
00064 {
00065 csRef<iRenderBuffer> coordBuf;
00066 csRef<iRenderBuffer> tcBuf;
00067 csRef<iRenderBuffer> indexBuf;
00068 csRef<csRenderBufferHolder> holder;
00069 };
00070
00074 struct CS_CRYSTALSPACE_EXPORT PortalBufferConstraint
00075 {
00076 typedef size_t KeyType;
00077
00078 static bool IsEqual (const PortalBuffers& b1,
00079 const PortalBuffers& b2);
00080 static bool IsLargerEqual (const PortalBuffers& b1,
00081 const PortalBuffers& b2);
00082
00083 static bool IsEqual (const PortalBuffers& b1,
00084 const KeyType& s2);
00085 static bool IsLargerEqual (const PortalBuffers& b1,
00086 const KeyType& s2);
00087 static bool IsLargerEqual (const KeyType& s1,
00088 const PortalBuffers& b2);
00089 };
00090 CS::Utility::GenericResourceCache<PortalBuffers, csTicks,
00091 PortalBufferConstraint> bufCache;
00092
00093 struct BoxClipperCacheRefCounted;
00097 struct CS_CRYSTALSPACE_EXPORT csBoxClipperCached : public csBoxClipper
00098 {
00099 BoxClipperCacheRefCounted* owningCache;
00100
00101 csBoxClipperCached (BoxClipperCacheRefCounted* owningCache,
00102 const csBox2& box) : csBoxClipper (box),
00103 owningCache (owningCache)
00104 { }
00105
00106 void operator delete (void* p, void* q);
00107 void operator delete (void* p);
00108 };
00109 struct csBoxClipperCachedStore
00110 {
00111 uint bytes[(sizeof(csBoxClipperCached) + sizeof (uint) - 1)/sizeof(uint)];
00112
00113 csBoxClipperCachedStore()
00114 {
00115
00116 memset (bytes, 0, sizeof (bytes));
00117 }
00118 };
00119 typedef CS::Utility::GenericResourceCache<csBoxClipperCachedStore, csTicks,
00120 CS::Utility::ResourceCache::SortingNone,
00121 CS::Utility::ResourceCache::ReuseConditionFlagged> BoxClipperCacheType;
00122 struct BoxClipperCacheRefCounted : public BoxClipperCacheType,
00123 public CS::Utility::FastRefCount<BoxClipperCacheRefCounted>
00124 {
00125 BoxClipperCacheRefCounted (
00126 const CS::Utility::ResourceCache::ReuseConditionFlagged& reuse,
00127 const CS::Utility::ResourceCache::PurgeConditionAfterTime<uint>& purge)
00128 : BoxClipperCacheType (reuse, purge) {}
00129
00130 void FreeCachedClipper (csBoxClipperCached* bcc);
00131 };
00132 csRef<BoxClipperCacheRefCounted> boxClipperCache;
00133
00134 CS::ShaderVarStringID svNameTexPortal;
00135 #ifdef CS_DEBUG
00136 csFrameDataHolder<csStringBase> stringHolder;
00137 #endif
00138
00139 TextureCache texCache;
00140
00141
00142
00143 int fixedTexCacheWidth;
00144 int fixedTexCacheHeight;
00145
00147 iTextureHandle* QueryUnusedTexture (int width, int height,
00148 int& real_w, int& real_h)
00149 {
00150 if (fixedTexCacheWidth > 0)
00151 width = fixedTexCacheWidth;
00152 if (fixedTexCacheHeight > 0)
00153 height = fixedTexCacheHeight;
00154
00155 return texCache.QueryUnusedTexture (width, height,
00156 real_w, real_h);
00157 }
00158
00159 uint dbgDrawPortalOutlines;
00160 uint dbgDrawPortalPlanes;
00161 uint dbgShowPortalTextures;
00162
00164 PersistentData(int textCachOptions = TextureCache::tcachePowerOfTwo);
00165
00170 void Initialize (iShaderManager* shmgr, iGraphics3D* g3d,
00171 RenderTreeBase::DebugPersistent& dbgPersist);
00172
00177 void UpdateNewFrame ()
00178 {
00179 csTicks time = csGetTicks ();
00180 texCache.AdvanceFrame (time);
00181 bufCache.AdvanceTime (time);
00182 boxClipperCache->AdvanceTime (time);
00183 }
00184 };
00185
00186 StandardPortalSetup_Base (PersistentData& persistentData)
00187 : persistentData (persistentData)
00188 {}
00189 protected:
00190 PersistentData& persistentData;
00191
00192 void PortalDebugDraw (RenderTreeBase& renderTree,
00193 iPortal* portal,
00194 size_t count, const csVector2* portalVerts2d,
00195 const csVector3* portalVerts3d,
00196 int screenH,
00197 bool isSimple, int skipRec);
00198
00200 csPtr<iClipper2D> CreateBoxClipper(const csBox2& box);
00201
00203 void SetupProjectionShift (iCustomMatrixCamera* newCam,
00204 iCamera* inewcam,
00205 int sb_minX, int sb_minY,
00206 int txt_h,
00207 int real_w, int real_h,
00208 int screenW, int screenH);
00213 void FudgeTargetCamera (iCamera* inewcam, iCamera* cam,
00214 iPortal* portal, const csFlags& portalFlags,
00215 size_t count, const csVector2* portalVerts2d,
00216 const csVector3* portalVerts3d,
00217 int screenW, int screenH);
00218
00220 csPtr<csRenderBufferHolder> GetPortalBuffers (size_t count,
00221 const csVector2* portalVerts2d,
00222 const csVector3* portalVerts3d,
00223 bool withTCs = false,
00224 int txt_h = 0,
00225 int real_w = 0, int real_h = 0,
00226 int sb_minX = 0, int sb_minY = 0);
00227
00229 csRenderMesh* SetupPortalRM (csRenderMesh* rm,
00230 iPortal* portal, iSector* sector,
00231 size_t count, RenderView* rview);
00232 };
00233
00278 template<typename RenderTreeType, typename ContextSetup>
00279 class StandardPortalSetup : public StandardPortalSetup_Base
00280 {
00281 public:
00282 typedef StandardPortalSetup<RenderTreeType, ContextSetup> ThisType;
00283
00288 struct ContextSetupData
00289 {
00290 typename RenderTreeType::ContextNode* lastSimplePortalCtx;
00291
00293 ContextSetupData (typename RenderTreeType::ContextNode* last = 0)
00294 : lastSimplePortalCtx (last)
00295 {}
00296 };
00297
00299 StandardPortalSetup (PersistentData& persistentData, ContextSetup& cfun)
00300 : StandardPortalSetup_Base (persistentData), contextFunction (cfun)
00301 {}
00302
00307 void operator() (typename RenderTreeType::ContextNode& context,
00308 ContextSetupData& setupData)
00309 {
00310 RenderView* rview = context.renderView;
00311 RenderTreeType& renderTree = context.owner;
00312 int screenW, screenH;
00313 if (!context.GetTargetDimensions (screenW, screenH))
00314 {
00315 screenW = rview->GetGraphics3D()->GetWidth();
00316 screenH = rview->GetGraphics3D()->GetHeight();
00317 }
00318
00319 bool debugDraw =
00320 renderTree.IsDebugFlagEnabled (persistentData.dbgDrawPortalOutlines)
00321 || renderTree.IsDebugFlagEnabled (persistentData.dbgDrawPortalPlanes);
00322
00323 csDirtyAccessArray<csVector2> allPortalVerts2d (64);
00324 csDirtyAccessArray<csVector3> allPortalVerts3d (64);
00325 csDirtyAccessArray<size_t> allPortalVertsNums;
00326
00327 for (size_t pc = 0; pc < context.allPortals.GetSize (); ++pc)
00328 {
00329 typename RenderTreeType::ContextNode::PortalHolder& holder = context.allPortals[pc];
00330 const size_t portalCount = holder.portalContainer->GetPortalCount ();
00331
00332 size_t allPortalVertices = holder.portalContainer->GetTotalVertexCount ();
00333 allPortalVerts2d.SetSize (allPortalVertices * 3);
00334 allPortalVerts3d.SetSize (allPortalVertices * 3);
00335 allPortalVertsNums.SetSize (portalCount);
00336
00337 csVector2* portalVerts2d = allPortalVerts2d.GetArray();
00338 csVector3* portalVerts3d = allPortalVerts3d.GetArray();
00339
00340 holder.portalContainer->ComputeScreenPolygons (rview,
00341 portalVerts2d, portalVerts3d,
00342 allPortalVerts2d.GetSize(), allPortalVertsNums.GetArray(),
00343 screenW, screenH);
00344
00345 for (size_t pi = 0; pi < portalCount; ++pi)
00346 {
00347 iPortal* portal = holder.portalContainer->GetPortal (int (pi));
00348 const csFlags portalFlags (portal->GetFlags());
00349
00350
00351 if (!portal->CompleteSector (rview))
00352 continue;
00353
00354 size_t count = allPortalVertsNums[pi];
00355 if (count == 0) continue;
00356
00357 iSector* sector = portal->GetSector ();
00358 bool skipRec = sector->GetRecLevel() >= portal->GetMaximumSectorVisit();
00359
00360 if (debugDraw)
00361 {
00362 bool isSimple = IsSimplePortal (portalFlags);
00363 PortalDebugDraw (renderTree, portal,
00364 count, portalVerts2d, portalVerts3d,
00365 screenH, isSimple, skipRec);
00366 }
00367
00368 if (!skipRec)
00369 {
00370 sector->IncRecLevel();
00371 if (IsSimplePortal (portalFlags))
00372 {
00373 SetupSimplePortal (context, setupData, portal, sector,
00374 portalVerts2d, portalVerts3d, count, screenW, screenH, holder);
00375 }
00376 else
00377 {
00378 SetupHeavyPortal (context, setupData, portal, sector,
00379 portalVerts2d, portalVerts3d, count, screenW, screenH, holder);
00380 }
00381 sector->DecRecLevel();
00382 }
00383
00384 portalVerts2d += count;
00385 portalVerts3d += count;
00386 }
00387 }
00388 }
00389
00390 private:
00391 ContextSetup& contextFunction;
00392
00393 bool IsSimplePortal (const csFlags& portalFlags)
00394 {
00395 return (portalFlags.Get() & (CS_PORTAL_CLIPDEST
00396 | CS_PORTAL_CLIPSTRADDLING
00397 | CS_PORTAL_ZFILL
00398 | CS_PORTAL_MIRROR
00399 | CS_PORTAL_FLOAT)) == 0;
00400 }
00401
00402 void ComputeVector2BoundingBox (const csVector2* verts, size_t count,
00403 csBox2& box)
00404 {
00405 if (count == 0)
00406 {
00407 box.StartBoundingBox ();
00408 return;
00409 }
00410 box.StartBoundingBox (verts[0]);
00411 for (size_t i = 1; i < count; i++)
00412 box.AddBoundingVertexSmart (verts[i]);
00413 }
00414
00415 void SetupWarp (iCamera* inewcam, iMovable* movable, iPortal* portal)
00416 {
00417 const csReversibleTransform& movtrans = movable->GetFullTransform();
00418 bool mirror = inewcam->IsMirrored ();
00419 csReversibleTransform warp_wor;
00420 portal->ObjectToWorld (movtrans, warp_wor);
00421 portal->WarpSpace (warp_wor, inewcam->GetTransform (), mirror);
00422 inewcam->SetMirrored (mirror);
00423 }
00424
00425 void SetupSimplePortal (
00426 typename RenderTreeType::ContextNode& context,
00427 ContextSetupData& setupData, iPortal* portal, iSector* sector,
00428 const csVector2* portalVerts2d, const csVector3* portalVerts3d, size_t count,
00429 int screenW, int screenH,
00430 typename RenderTreeType::ContextNode::PortalHolder& holder)
00431 {
00432 RenderView* rview = context.renderView;
00433 RenderTreeType& renderTree = context.owner;
00434 const csFlags portalFlags (portal->GetFlags());
00435
00436
00437 rview->CreateRenderContext ();
00438 rview->SetLastPortal (portal);
00439 rview->SetPreviousSector (rview->GetThisSector ());
00440 rview->SetThisSector (sector);
00441 csPolygonClipper newView (portalVerts2d, count);
00442 rview->SetViewDimensions (screenW, screenH);
00443 rview->SetClipper (&newView);
00444
00445 if (portalFlags.Check (CS_PORTAL_WARP))
00446 {
00447 iCamera *inewcam = rview->CreateNewCamera ();
00448 SetupWarp (inewcam, holder.meshWrapper->GetMovable(), portal);
00449 }
00450
00451 typename RenderTreeType::ContextNode* portalCtx =
00452 renderTree.CreateContext (rview, setupData.lastSimplePortalCtx);
00453 setupData.lastSimplePortalCtx = portalCtx;
00454
00455
00456 for (int a = 0; a < rtaNumAttachments; a++)
00457 portalCtx->renderTargets[a] = context.renderTargets[a];
00458 portalCtx->perspectiveFixup = context.perspectiveFixup;
00459
00460
00461 contextFunction (*portalCtx, setupData);
00462
00463 rview->RestoreRenderContext ();
00464
00465
00466
00467 if (rview->GetThisSector()->HasFog())
00468 {
00469
00470 bool meshCreated;
00471 csRenderMesh* rm = renderTree.GetPersistentData().rmHolder.GetUnusedMesh (
00472 meshCreated, rview->GetCurrentFrameNumber());
00473 SetupPortalRM (rm, portal, sector, count, rview);
00474 rm->buffers = GetPortalBuffers (count, portalVerts2d, portalVerts3d,
00475 false);
00476 rm->variablecontext.Invalidate();
00477
00478 typename RenderTreeType::MeshNode::SingleMesh sm;
00479 sm.meshObjSVs = 0;
00480
00481 CS::Graphics::RenderPriority renderPrio =
00482 holder.meshWrapper->GetRenderPriority ();
00483 context.AddRenderMesh (rm, renderPrio, sm);
00484 }
00485 }
00486
00487 void SetupHeavyPortal (
00488 typename RenderTreeType::ContextNode& context,
00489 ContextSetupData& setupData, iPortal* portal, iSector* sector,
00490 csVector2* portalVerts2d, csVector3* portalVerts3d, size_t count,
00491 int screenW, int screenH,
00492 typename RenderTreeType::ContextNode::PortalHolder& holder)
00493 {
00494 RenderView* rview = context.renderView;
00495 RenderTreeType& renderTree = context.owner;
00496 const csFlags portalFlags (portal->GetFlags());
00497
00498
00499 csBox2 screenBox;
00500 ComputeVector2BoundingBox (portalVerts2d, count, screenBox);
00501
00502
00503 int sb_minX = int (screenBox.MinX());
00504 int sb_minY = int (screenBox.MinY());
00505 int txt_w = int (ceil (screenBox.MaxX() - screenBox.MinX()));
00506 int txt_h = int (ceil (screenBox.MaxY() - screenBox.MinY()));
00507 int real_w, real_h;
00508 csRef<iTextureHandle> tex = persistentData.QueryUnusedTexture (txt_w, txt_h,
00509 real_w, real_h);
00510
00511 if (renderTree.IsDebugFlagEnabled (persistentData.dbgShowPortalTextures))
00512 renderTree.AddDebugTexture (tex, (float)real_w/(float)real_h);
00513
00514 iCamera* cam = rview->GetCamera();
00515
00516 csRef<CS::RenderManager::RenderView> newRenderView;
00517 csRef<iCustomMatrixCamera> newCam (rview->GetEngine()->CreateCustomMatrixCamera (cam));
00518 iCamera* inewcam = newCam->GetCamera();
00519 newRenderView = renderTree.GetPersistentData().renderViews.GetRenderView (rview, portal, inewcam);
00520 newRenderView->SetEngine (rview->GetEngine ());
00521
00522 if (portalFlags.Check (CS_PORTAL_WARP))
00523 {
00524 SetupWarp (inewcam, holder.meshWrapper->GetMovable(), portal);
00525 }
00526
00527 SetupProjectionShift (newCam, inewcam, sb_minX, sb_minY, txt_h,
00528 real_w, real_h, screenW, screenH);
00529 FudgeTargetCamera (inewcam, cam,
00530 portal, portalFlags, count, portalVerts2d, portalVerts3d,
00531 screenW, screenH);
00532
00533
00534
00535 newRenderView->SetLastPortal (portal);
00536 newRenderView->SetPreviousSector (rview->GetThisSector ());
00537 newRenderView->SetThisSector (sector);
00538 newRenderView->SetViewDimensions (real_w, real_h);
00539
00540
00541 csBox2 clipBox (0, real_h - (txt_h+1), txt_w+1, real_h);
00542 csRef<iClipper2D> newView (CreateBoxClipper (clipBox));
00543
00544
00545
00546
00547
00548 newRenderView->SetClipper (newView);
00549
00550 typename RenderTreeType::ContextNode* portalCtx =
00551 renderTree.CreateContext (newRenderView);
00552 portalCtx->renderTargets[rtaColor0].texHandle = tex;
00553
00554
00555 ContextSetupData newSetup (portalCtx);
00556 contextFunction (*portalCtx, newSetup);
00557
00558
00559 csRef<csShaderVariableContext> svc;
00560 svc.AttachNew (new csShaderVariableContext);
00561 csRef<csShaderVariable> svTexPortal =
00562 svc->GetVariableAdd (persistentData.svNameTexPortal);
00563 svTexPortal->SetValue (tex);
00564
00565 bool meshCreated;
00566 csRenderMesh* rm = renderTree.GetPersistentData().rmHolder.GetUnusedMesh (
00567 meshCreated, rview->GetCurrentFrameNumber());
00568 SetupPortalRM (rm, portal, sector, count, rview);
00569 rm->buffers = GetPortalBuffers (count, portalVerts2d, portalVerts3d,
00570 true, txt_h, real_w, real_h,
00571 sb_minX, sb_minY);
00572 rm->variablecontext = svc;
00573
00574 typename RenderTreeType::MeshNode::SingleMesh sm;
00575 sm.meshObjSVs = 0;
00576
00577 CS::Graphics::RenderPriority renderPrio =
00578 holder.meshWrapper->GetRenderPriority ();
00579 context.AddRenderMesh (rm, renderPrio, sm);
00580 }
00581
00582 };
00583
00584 }
00585 }
00586
00587 #endif // __CS_CSPLUGINCOMMON_RENDERMANAGER_CONTEXT_H__
00588