1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
3 // -------------------------------------------------------------------------
4 // File name: statobjmandraw.cpp
6 // Created: 18/12/2002 by Vladimir Kajalin
7 // Compilers: Visual Studio.NET
8 // Description: Visibility areas
9 // -------------------------------------------------------------------------
12 ////////////////////////////////////////////////////////////////////////////
15 #include <CryAnimation/ICryAnimation.h>
20 #include "terrain_sector.h"
22 #include <CryMath/AABBSV.h>
25 #define DEFAULT_INITIAL_PORTALS 1
26 #define DEFAULT_INITIAL_VISAREAS 1
27 #define DEFAULT_INITIAL_OCCLAREAS 1
29 CVisAreaManager::CVisAreaManager()
31 m_pCurPortal
= m_pCurArea
= 0;
32 m_bOutdoorVisible
= false;
33 m_bSkyVisible
= false;
34 m_bSunIsNeeded
= false;
35 m_bOceanVisible
= false;
38 m_visAreas
.PreAllocate(DEFAULT_INITIAL_VISAREAS
);
39 m_visAreaColdData
.PreAllocate(DEFAULT_INITIAL_VISAREAS
);
41 m_portals
.PreAllocate(DEFAULT_INITIAL_PORTALS
);
42 m_portalColdData
.PreAllocate(DEFAULT_INITIAL_PORTALS
);
44 m_occlAreas
.PreAllocate(DEFAULT_INITIAL_OCCLAREAS
);
45 m_occlAreaColdData
.PreAllocate(DEFAULT_INITIAL_OCCLAREAS
);
47 m_segVisAreas
.Clear();
49 m_segOcclAreas
.Clear();
52 void CVisAreaManager::DeleteAllVisAreas()
54 for (int i
= 0; i
< m_lstVisAreas
.Count(); i
++)
56 if (m_visAreas
.Find(m_lstVisAreas
[i
]) >= 0)
58 delete m_lstVisAreas
[i
];
62 delete m_lstVisAreas
[i
]->GetColdData();
63 delete m_lstVisAreas
[i
];
68 m_visAreaColdData
.Clear();
69 m_lstVisAreas
.Clear();
71 for (int i
= 0; i
< m_lstPortals
.Count(); i
++)
73 if (m_portals
.Find(m_lstPortals
[i
]) >= 0)
75 delete m_lstPortals
[i
];
79 delete m_lstPortals
[i
]->GetColdData();
80 delete m_lstPortals
[i
];
85 m_portalColdData
.Clear();
88 for (int i
= 0; i
< m_lstOcclAreas
.Count(); i
++)
90 if (m_occlAreas
.Find(m_lstOcclAreas
[i
]) >= 0)
92 delete m_lstOcclAreas
[i
];
96 delete m_lstOcclAreas
[i
]->GetColdData();
97 delete m_lstOcclAreas
[i
];
102 m_occlAreaColdData
.Clear();
103 m_lstOcclAreas
.Clear();
105 stl::free_container(CVisArea::m_lUnavailableAreas
);
108 void SAABBTreeNode::OffsetPosition(const Vec3
& delta
)
111 if (!nodeAreas
.Count())
113 for (int i
= 0; i
< 2; i
++)
116 arrChilds
[i
]->OffsetPosition(delta
);
121 CVisAreaManager::~CVisAreaManager()
129 SAABBTreeNode::SAABBTreeNode(PodArray
<CVisArea
*>& lstAreas
, AABB box
, int nRecursion
)
131 memset(this, 0, sizeof(*this));
136 if (nRecursion
> 8 || lstAreas
.Count() < 8)
138 nodeAreas
.AddList(lstAreas
);
142 PodArray
<CVisArea
*> lstAreas0
, lstAreas1
;
143 Vec3 vSize
= nodeBox
.GetSize();
144 Vec3 vCenter
= nodeBox
.GetCenter();
146 AABB nodeBox0
= nodeBox
;
147 AABB nodeBox1
= nodeBox
;
149 if (vSize
.x
>= vSize
.y
&& vSize
.x
>= vSize
.z
)
151 nodeBox0
.min
.x
= vCenter
.x
;
152 nodeBox1
.max
.x
= vCenter
.x
;
154 else if (vSize
.y
>= vSize
.x
&& vSize
.y
>= vSize
.z
)
156 nodeBox0
.min
.y
= vCenter
.y
;
157 nodeBox1
.max
.y
= vCenter
.y
;
161 nodeBox0
.min
.z
= vCenter
.z
;
162 nodeBox1
.max
.z
= vCenter
.z
;
165 for (int i
= 0; i
< lstAreas
.Count(); i
++)
167 if (Overlap::AABB_AABB(nodeBox0
, *lstAreas
[i
]->GetAABBox()))
168 lstAreas0
.Add(lstAreas
[i
]);
170 if (Overlap::AABB_AABB(nodeBox1
, *lstAreas
[i
]->GetAABBox()))
171 lstAreas1
.Add(lstAreas
[i
]);
174 if (lstAreas0
.Count())
175 arrChilds
[0] = new SAABBTreeNode(lstAreas0
, nodeBox0
, nRecursion
);
177 if (lstAreas1
.Count())
178 arrChilds
[1] = new SAABBTreeNode(lstAreas1
, nodeBox1
, nRecursion
);
181 SAABBTreeNode::~SAABBTreeNode()
187 SAABBTreeNode
* SAABBTreeNode::GetTopNode(const AABB
& box
, void** pNodeCache
)
190 boxClip
.ClipToBox(nodeBox
);
192 SAABBTreeNode
* pNode
= this;
195 pNode
= (SAABBTreeNode
*)*pNodeCache
;
196 if (!pNode
|| !pNode
->nodeBox
.ContainsBox(boxClip
))
200 // Find top node containing box.
204 for (i
= 0; i
< 2; i
++)
206 if (pNode
->arrChilds
[i
] && pNode
->arrChilds
[i
]->nodeBox
.ContainsBox(boxClip
))
208 pNode
= pNode
->arrChilds
[i
];
217 *(SAABBTreeNode
**)pNodeCache
= pNode
;
221 bool SAABBTreeNode::IntersectsVisAreas(const AABB
& box
)
223 if (nodeBox
.IsIntersectBox(box
))
225 if (nodeAreas
.Count())
228 for (int i
= 0; i
< nodeAreas
.Count(); i
++)
230 if (nodeAreas
[i
]->m_bActive
&& nodeAreas
[i
]->m_boxArea
.IsIntersectBox(box
))
237 for (int i
= 0; i
< 2; i
++)
239 if (arrChilds
[i
]->IntersectsVisAreas(box
))
246 int SAABBTreeNode::ClipOutsideVisAreas(Sphere
& sphere
, Vec3
const& vNormal
)
250 if (sphere
.radius
> FLT_MAX
* 0.01f
|| Overlap::Sphere_AABB(sphere
, nodeBox
))
252 if (nodeAreas
.Count())
255 for (int i
= 0; i
< nodeAreas
.Count(); i
++)
257 if (nodeAreas
[i
]->m_bActive
&& Overlap::Sphere_AABB(sphere
, nodeAreas
[i
]->m_boxArea
))
258 nClipped
+= nodeAreas
[i
]->ClipToVisArea(false, sphere
, vNormal
);
264 for (int i
= 0; i
< 2; i
++)
266 nClipped
+= arrChilds
[i
]->ClipOutsideVisAreas(sphere
, vNormal
);
273 void CVisAreaManager::UpdateAABBTree()
276 PodArray
<CVisArea
*> lstAreas
;
277 lstAreas
.AddList(m_lstPortals
);
278 lstAreas
.AddList(m_lstVisAreas
);
281 nodeBox
.min
= Vec3(1000000, 1000000, 1000000);
282 nodeBox
.max
= -nodeBox
.min
;
283 for (int i
= 0; i
< lstAreas
.Count(); i
++)
284 nodeBox
.Add(*lstAreas
[i
]->GetAABBox());
286 m_pAABBTree
= new SAABBTreeNode(lstAreas
, nodeBox
);
289 bool CVisAreaManager::IsEntityVisible(IRenderNode
* pEnt
) const
291 if (GetCVars()->e_Portals
== 3)
294 if (!pEnt
->GetEntityVisArea())
295 return IsOutdoorAreasVisible();
300 void CVisAreaManager::SetCurAreas(const SRenderingPassInfo
& passInfo
)
305 if (!GetCVars()->e_Portals
)
311 CVisArea
* pFound
= m_pAABBTree
->FindVisarea(passInfo
.GetCamera().GetOccPos());
315 // find camera portal id
316 for (int v
= 0; v
< m_lstPortals
.Count(); v
++)
317 if (m_lstPortals
[v
]->m_bActive
&& m_lstPortals
[v
]->IsPointInsideVisArea(passInfo
.GetCamera().GetOccPos()))
319 m_pCurPortal
= m_lstPortals
[v
];
323 // if not inside any portal - try to find area
326 // int nFoundAreasNum = 0;
329 for (int nVolumeId
= 0; nVolumeId
< m_lstVisAreas
.Count(); nVolumeId
++)
331 if (m_lstVisAreas
[nVolumeId
]->IsPointInsideVisArea(passInfo
.GetCamera().GetOccPos()))
334 m_pCurArea
= m_lstVisAreas
[nVolumeId
];
339 // if(nFoundAreasNum>1) // if more than one area found - set cur area to undefined
341 // todo: try to set joining portal as current
346 assert(pFound
== m_pCurArea
|| pFound
== m_pCurPortal
);
352 if (pFound
->IsPortal())
353 m_pCurPortal
= pFound
;
358 // camera is in outdoors
359 m_lstActiveEntransePortals
.Clear();
360 if (!m_pCurArea
&& !m_pCurPortal
)
361 MakeActiveEntransePortalsList(&passInfo
.GetCamera(), m_lstActiveEntransePortals
, 0, passInfo
);
366 IVisArea * arrAreas[8];
367 int nres = m_pCurArea->GetVisAreaConnections(arrAreas, 8);
372 /* if(GetCVars()->e_Portals == 4)
376 IVisArea * arrAreas[64];
377 int nConnections = m_pCurPortal->GetVisAreaConnections(arrAreas,64);
378 PrintMessage("CurPortal = %s, nConnections = %d", m_pCurPortal->m_sName, nConnections);
383 IVisArea * arrAreas[64];
384 int nConnections = m_pCurArea->GetVisAreaConnections(arrAreas,64);
385 PrintMessage("CurArea = %s, nRes = %d", m_pCurArea->m_sName, nConnections);
390 /*void CVisAreaManager::SetAreaFogVolume(CTerrain * pTerrain, CVisArea * pVisArea)
392 pVisArea->m_pFogVolume=0;
393 for(int f=0; f<Get3DEngine()->GetFogVolumes().Count(); f++)
395 const Vec3 & v1Min = Get3DEngine()->GetFogVolumes()[f].box.min;
396 const Vec3 & v1Max = Get3DEngine()->GetFogVolumes()[f].box.max;
397 const Vec3 & v2Min = pVisArea->m_boxArea.min;
398 const Vec3 & v2Max = pVisArea->m_boxArea.max;
400 if(v1Max.x>v2Min.x && v2Max.x>v1Min.x)
401 if(v1Max.y>v2Min.y && v2Max.y>v1Min.y)
402 if(v1Max.z>v2Min.z && v2Max.z>v1Min.z)
403 if(!Get3DEngine()->GetFogVolumes()[f].bOcean)
407 Vec3(v1Min.x,v1Min.y,v1Min.z),
408 Vec3(v1Min.x,v1Max.y,v1Min.z),
409 Vec3(v1Max.x,v1Min.y,v1Min.z),
410 Vec3(v1Max.x,v1Max.y,v1Min.z),
411 Vec3(v1Min.x,v1Min.y,v1Max.z),
412 Vec3(v1Min.x,v1Max.y,v1Max.z),
413 Vec3(v1Max.x,v1Min.y,v1Max.z),
414 Vec3(v1Max.x,v1Max.y,v1Max.z)
417 bool bIntersect = false;
418 for(int i=0; i<8; i++)
419 if(pVisArea->IsPointInsideVisArea(arrVerts3d[i]))
426 if(pVisArea->IsPointInsideVisArea((v1Min+v1Max)*0.5f))
431 for(int i=0; i<pVisArea->m_lstShapePoints.Count(); i++)
432 if(Get3DEngine()->GetFogVolumes()[f].IsInsideBBox(pVisArea->m_lstShapePoints[i]))
441 Vec3 vCenter = (pVisArea->m_boxArea.min+pVisArea->m_boxArea.max)*0.5f;
442 if(Get3DEngine()->GetFogVolumes()[f].IsInsideBBox(vCenter))
448 pVisArea->m_pFogVolume = &Get3DEngine()->GetFogVolumes()[f];
449 Get3DEngine()->GetFogVolumes()[f].bIndoorOnly = true;
450 pTerrain->UnregisterFogVolumeFromOutdoor(&Get3DEngine()->GetFogVolumes()[f]);
457 void CVisAreaManager::PortalsDrawDebug()
463 for(int p=0; p<m_pCurArea->m_lstConnections.Count(); p++)
465 CVisArea * pPortal = m_pCurArea->m_lstConnections[p];
466 float fBlink = gEnv->pTimer->GetFrameStartTime().GetPeriodicFraction(1.0f)>0.5f ? 1.0f : 0.0f;
467 float fError = pPortal->IsPortalValid() ? 1.0f : fBlink;
468 GetRenderer()->SetMaterialColor(fError,fError*(pPortal->m_lstConnections.Count()<2),0,0.25f);
469 DrawBBox(pPortal->m_boxArea.min, pPortal->m_boxArea.max, DPRIM_SOLID_BOX);
470 GetRenderer()->DrawLabel((pPortal->m_boxArea.min+ pPortal->m_boxArea.max)*0.5f,
477 Vec3
oneVec(1, 1, 1);
478 for (int v
= 0; v
< m_lstVisAreas
.Count(); v
++)
480 DrawBBox(m_lstVisAreas
[v
]->m_boxArea
.min
, m_lstVisAreas
[v
]->m_boxArea
.max
, ColorB(0, 255, 0, 64)); //, DPRIM_SOLID_BOX);
481 IRenderAuxText::DrawLabelEx((m_lstVisAreas
[v
]->m_boxArea
.min
+ m_lstVisAreas
[v
]->m_boxArea
.max
) * 0.5f
, 1, (float*)&oneVec
, 0, 1, m_lstVisAreas
[v
]->GetName());
482 DrawBBox(m_lstVisAreas
[v
]->m_boxStatics
, Col_LightGray
);
485 // debug draw portals
486 for (int v
= 0; v
< m_lstPortals
.Count(); v
++)
488 CVisArea
* pPortal
= m_lstPortals
[v
];
490 float fBlink
= gEnv
->pTimer
->GetFrameStartTime().GetPeriodicFraction(1.0f
) > 0.5f
? 1.0f
: 0.0f
;
491 float fError
= pPortal
->IsPortalValid() ? 1.f
: fBlink
;
494 (int)clamp_tpl(fError
* 255.0f
, 0.0f
, 255.0f
),
495 (int)clamp_tpl(fError
* (pPortal
->m_lstConnections
.Count() < 2) * 255.0f
, 0.0f
, 255.0f
),
498 DrawBBox(pPortal
->m_boxArea
.min
, pPortal
->m_boxArea
.max
, col
);
500 IRenderAuxText::DrawLabelEx((pPortal
->m_boxArea
.min
+ pPortal
->m_boxArea
.max
) * 0.5f
, 1, (float*)&oneVec
, 0, 1, pPortal
->GetName());
502 Vec3 vCenter
= (pPortal
->m_boxArea
.min
+ pPortal
->m_boxArea
.max
) * 0.5f
;
503 DrawBBox(vCenter
- Vec3(0.1f
, 0.1f
, 0.1f
), vCenter
+ Vec3(0.1f
, 0.1f
, 0.1f
));
505 int nConnections
= pPortal
->m_lstConnections
.Count();
506 if (nConnections
== 1)
507 col
= ColorB(0, 255, 0, 64);
509 col
= ColorB(0, 0, 255, 64);
511 for (int i
= 0; i
< nConnections
&& i
< 2; i
++)
512 DrawLine(vCenter
, vCenter
+ pPortal
->m_vConnNormals
[i
], col
);
514 DrawBBox(pPortal
->m_boxStatics
.min
, pPortal
->m_boxStatics
.max
, col
);
518 // debug draw area shape
519 GetRenderer()->SetMaterialColor(0,0,1,0.25f);
520 for(int v=0; v<m_lstVisAreas.Count(); v++)
521 for(int p=0; p<m_lstVisAreas[v]->m_lstShapePoints.Count(); p++)
522 GetRenderer()->DrawLabel(m_lstVisAreas[v]->m_lstShapePoints[p], 2,"%d", p);
523 for(int v=0; v<m_lstPortals.Count(); v++)
524 for(int p=0; p<m_lstPortals[v]->m_lstShapePoints.Count(); p++)
525 GetRenderer()->DrawLabel(m_lstPortals[v]->m_lstShapePoints[p], 2,"%d", p);*/
529 void CVisAreaManager::DrawVisibleSectors(const SRenderingPassInfo
& passInfo
, FrustumMaskType passCullMask
)
531 FUNCTION_PROFILER_3DENGINE
;
533 for (int i
= 0; i
< m_lstVisibleAreas
.Count(); i
++)
535 CVisArea
* pArea
= m_lstVisibleAreas
[i
];
536 Vec3 vAmbColor
= pArea
->GetFinalAmbientColor();
537 if (pArea
->IsObjectsTreeValid())
539 for (int c
= 0; c
< pArea
->m_lstCurCamerasLen
; c
++)
541 passInfo
.GetRendItemSorter().IncreaseOctreeCounter();
542 // create a new RenderingPassInfo object, which a camera matching the visarea
543 pArea
->GetObjectsTree()->Render_Object_Nodes(false, OCTREENODE_RENDER_FLAG_OBJECTS
, vAmbColor
, passCullMask
,
544 SRenderingPassInfo::CreateTempRenderingInfo(CVisArea::s_tmpCameras
[pArea
->m_lstCurCamerasIdx
+ c
], passInfo
));
549 passInfo
.GetRendItemSorter().IncreaseGroupCounter();
552 void CVisAreaManager::PhysicalizeInBox(const AABB
& bbox
)
554 for (int i
= 0; i
< m_lstVisAreas
.Count(); i
++)
556 CVisArea
* pArea
= m_lstVisAreas
[i
];
557 if (pArea
&& pArea
->IsObjectsTreeValid() && Overlap::AABB_AABB(*pArea
->GetAABBox(), bbox
))
559 pArea
->GetObjectsTree()->PhysicalizeInBox(bbox
);
562 for (int i
= 0; i
< m_lstPortals
.Count(); i
++)
564 CVisArea
* pArea
= m_lstPortals
[i
];
565 if (pArea
&& pArea
->IsObjectsTreeValid() && Overlap::AABB_AABB(*pArea
->GetAABBox(), bbox
))
567 pArea
->GetObjectsTree()->PhysicalizeInBox(bbox
);
571 void CVisAreaManager::DephysicalizeInBox(const AABB
& bbox
)
573 for (int i
= 0; i
< m_lstVisAreas
.Count(); i
++)
575 CVisArea
* pArea
= m_lstVisAreas
[i
];
576 if (pArea
&& pArea
->IsObjectsTreeValid() && Overlap::AABB_AABB(*pArea
->GetAABBox(), bbox
))
578 pArea
->GetObjectsTree()->DephysicalizeInBox(bbox
);
581 for (int i
= 0; i
< m_lstPortals
.Count(); i
++)
583 CVisArea
* pArea
= m_lstPortals
[i
];
584 if (pArea
&& pArea
->IsObjectsTreeValid() && Overlap::AABB_AABB(*pArea
->GetAABBox(), bbox
))
586 pArea
->GetObjectsTree()->DephysicalizeInBox(bbox
);
591 void CVisAreaManager::CheckVis(const SRenderingPassInfo
& passInfo
)
593 FUNCTION_PROFILER_3DENGINE
;
594 MEMSTAT_CONTEXT(EMemStatContextType::Other
, "CVisAreaManager::CheckVis");
596 if (passInfo
.IsGeneralPass())
598 m_bOutdoorVisible
= false;
599 m_bSkyVisible
= false;
600 m_bOceanVisible
= false;
601 CVisArea::s_tmpCameras
.Clear();
604 m_lstOutdoorPortalCameras
.Clear();
605 m_lstVisibleAreas
.Clear();
606 m_bSunIsNeeded
= false;
608 SetCurAreas(passInfo
);
610 CCamera camRoot
= passInfo
.GetCamera();
612 camRoot
.m_ScissorInfo
.x1
= 0;
613 camRoot
.m_ScissorInfo
.y1
= 0;
614 camRoot
.m_ScissorInfo
.x2
= camRoot
.GetViewSurfaceX();
615 camRoot
.m_ScissorInfo
.y2
= camRoot
.GetViewSurfaceZ();
617 if (GetCVars()->e_Portals
== 3)
619 // draw everything for debug
620 for (int i
= 0; i
< m_lstVisAreas
.Count(); i
++)
621 if (camRoot
.IsAABBVisible_F(AABB(m_lstVisAreas
[i
]->m_boxArea
.min
, m_lstVisAreas
[i
]->m_boxArea
.max
)))
622 m_lstVisAreas
[i
]->PreRender(0, camRoot
, 0, m_pCurPortal
, &m_bOutdoorVisible
, &m_lstOutdoorPortalCameras
, &m_bSkyVisible
, &m_bOceanVisible
, m_lstVisibleAreas
, passInfo
);
624 for (int i
= 0; i
< m_lstPortals
.Count(); i
++)
625 if (camRoot
.IsAABBVisible_F(AABB(m_lstPortals
[i
]->m_boxArea
.min
, m_lstPortals
[i
]->m_boxArea
.max
)))
626 m_lstPortals
[i
]->PreRender(0, camRoot
, 0, m_pCurPortal
, &m_bOutdoorVisible
, &m_lstOutdoorPortalCameras
, &m_bSkyVisible
, &m_bOceanVisible
, m_lstVisibleAreas
, passInfo
);
630 if (passInfo
.IsRecursivePass())
632 // use another starting point for reflections
633 CVisArea
* pVisArea
= (CVisArea
*)GetVisAreaFromPos(camRoot
.GetOccPos());
635 pVisArea
->PreRender(3, camRoot
, 0, m_pCurPortal
, &m_bOutdoorVisible
, &m_lstOutdoorPortalCameras
, &m_bSkyVisible
, &m_bOceanVisible
, m_lstVisibleAreas
, passInfo
);
639 // camera inside some sector
640 m_pCurArea
->PreRender(GetCVars()->e_PortalsMaxRecursion
, camRoot
, 0, m_pCurPortal
, &m_bOutdoorVisible
, &m_lstOutdoorPortalCameras
, &m_bSkyVisible
, &m_bOceanVisible
, m_lstVisibleAreas
, passInfo
);
642 for (int ii
= 0; ii
< m_lstOutdoorPortalCameras
.Count(); ii
++) // process all exit portals
644 // for each portal build list of potentially visible entrances into other areas
645 MakeActiveEntransePortalsList(&m_lstOutdoorPortalCameras
[ii
], m_lstActiveEntransePortals
, (CVisArea
*)m_lstOutdoorPortalCameras
[ii
].m_pPortal
, passInfo
);
646 for (int i
= 0; i
< m_lstActiveEntransePortals
.Count(); i
++) // entrance into another building is visible
647 m_lstActiveEntransePortals
[i
]->PreRender(i
== 0 ? 5 : 1,
648 m_lstOutdoorPortalCameras
[ii
], 0, m_pCurPortal
, 0, 0, 0, 0, m_lstVisibleAreas
, passInfo
);
651 // reset scissor if skybox is visible also thru skyboxonly portal
652 if (m_bSkyVisible
&& m_lstOutdoorPortalCameras
.Count() == 1)
653 m_lstOutdoorPortalCameras
[0].m_ScissorInfo
.x1
=
654 m_lstOutdoorPortalCameras
[0].m_ScissorInfo
.x2
=
655 m_lstOutdoorPortalCameras
[0].m_ScissorInfo
.y1
=
656 m_lstOutdoorPortalCameras
[0].m_ScissorInfo
.y2
= 0;
658 else if (m_pCurPortal
)
660 // camera inside some portal
661 m_pCurPortal
->PreRender(GetCVars()->e_PortalsMaxRecursion
- 1, camRoot
, 0, m_pCurPortal
, &m_bOutdoorVisible
, &m_lstOutdoorPortalCameras
, &m_bSkyVisible
, &m_bOceanVisible
, m_lstVisibleAreas
, passInfo
);
663 if (m_pCurPortal
->m_lstConnections
.Count() == 1)
664 m_lstOutdoorPortalCameras
.Clear(); // camera in outdoor
666 if (m_pCurPortal
->m_lstConnections
.Count() == 1 || m_lstOutdoorPortalCameras
.Count())
668 // if camera is in exit portal or exit is visible
669 MakeActiveEntransePortalsList(m_lstOutdoorPortalCameras
.Count() ? &m_lstOutdoorPortalCameras
[0] : &camRoot
,
670 m_lstActiveEntransePortals
,
671 m_lstOutdoorPortalCameras
.Count() ? (CVisArea
*)m_lstOutdoorPortalCameras
[0].m_pPortal
: m_pCurPortal
, passInfo
);
672 for (int i
= 0; i
< m_lstActiveEntransePortals
.Count(); i
++) // entrance into another building is visible
673 m_lstActiveEntransePortals
[i
]->PreRender(i
== 0 ? 5 : 1,
674 m_lstOutdoorPortalCameras
.Count() ? m_lstOutdoorPortalCameras
[0] : camRoot
, 0, m_pCurPortal
, 0, 0, 0, 0, m_lstVisibleAreas
, passInfo
);
675 // m_lstOutdoorPortalCameras.Clear(); // otherwise ocean in fleet was not scissored
678 else if (m_lstActiveEntransePortals
.Count())
680 // camera in outdoors - process visible entrance portals
681 for (int i
= 0; i
< m_lstActiveEntransePortals
.Count(); i
++)
682 m_lstActiveEntransePortals
[i
]->PreRender(5, camRoot
, 0, m_lstActiveEntransePortals
[i
], &m_bOutdoorVisible
, &m_lstOutdoorPortalCameras
, &m_bSkyVisible
, &m_bOceanVisible
, m_lstVisibleAreas
, passInfo
);
683 m_lstActiveEntransePortals
.Clear();
685 // do not recurse to another building since we already processed all potential entrances
686 m_lstOutdoorPortalCameras
.Clear(); // use default camera
687 m_bOutdoorVisible
= true;
691 if (GetCVars()->e_Portals
== 2)
694 if (!m_bOutdoorVisible
)
696 if (!m_pCurArea
&& !m_pCurPortal
)
697 m_bOutdoorVisible
= true; // camera not in the areas
698 else if (m_pCurPortal
&& m_pCurPortal
->m_lstConnections
.Count() == 1)
699 m_bOutdoorVisible
= true; // camera is in exit portal
702 // note: outdoor camera is no modified in this case
706 void CVisAreaManager::ActivatePortal(const Vec3
& vPos
, bool bActivate
, const char* szEntityName
)
708 // bool bFound = false;
710 for (int v
= 0; v
< m_lstPortals
.Count(); v
++)
713 aabb
.min
= m_lstPortals
[v
]->m_boxArea
.min
- Vec3(0.5f
, 0.5f
, 0.1f
);
714 aabb
.max
= m_lstPortals
[v
]->m_boxArea
.max
+ Vec3(0.5f
, 0.5f
, 0.0f
);
716 if (Overlap::Point_AABB(vPos
, aabb
))
718 m_lstPortals
[v
]->m_bActive
= bActivate
;
720 // switch to PrintComment once portals activation is working stable
721 PrintMessage("I3DEngine::ActivatePortal(): Portal %s is %s by entity %s at position(%.1f,%.1f,%.1f)",
722 m_lstPortals
[v
]->GetName(), bActivate
? "Enabled" : "Disabled", szEntityName
, vPos
.x
, vPos
.y
, vPos
.z
);
731 PrintComment("I3DEngine::ActivatePortal(): Portal not found for entity %s at position(%.1f,%.1f,%.1f)",
732 szEntityName, vPos.x, vPos.y, vPos.z);
737 void CVisAreaManager::ActivateOcclusionAreas(IVisAreaTestCallback
* pTest
, bool bActivate
)
739 for (int v
= 0; v
< m_lstOcclAreas
.Count(); v
++)
741 if (pTest
->TestVisArea(m_lstOcclAreas
[v
]))
743 m_lstOcclAreas
[v
]->m_bActive
= bActivate
;
748 bool CVisAreaManager::IsValidVisAreaPointer(CVisArea
* pVisArea
)
750 if (m_lstVisAreas
.Find(pVisArea
) < 0 &&
751 m_lstPortals
.Find(pVisArea
) < 0 &&
752 m_lstOcclAreas
.Find(pVisArea
) < 0)
758 //This is only called from the editor, so pVisArea will not be pool allocated by type
759 bool CVisAreaManager::DeleteVisArea(CVisArea
* pVisArea
)
762 if (m_lstVisAreas
.Delete(pVisArea
) || m_lstPortals
.Delete(pVisArea
) || m_lstOcclAreas
.Delete(pVisArea
))
768 m_lstActiveOcclVolumes
.Delete(pVisArea
);
769 m_lstIndoorActiveOcclVolumes
.Delete(pVisArea
);
770 m_lstActiveEntransePortals
.Delete(pVisArea
);
782 /*void CVisAreaManager::LoadVisAreaShapeFromXML(XmlNodeRef pDoc)
784 for(int i=0; i<m_lstVisAreas.Count(); i++)
786 delete m_lstVisAreas[i];
787 m_lstVisAreas.Delete(i);
791 for(int i=0; i<m_lstPortals.Count(); i++)
793 delete m_lstPortals[i];
794 m_lstPortals.Delete(i);
798 // fill list of volumes of shape points
799 XmlNodeRef pObjectsNode = pDoc->findChild("Objects");
802 for (int i = 0; i < pObjectsNode->getChildCount(); i++)
804 XmlNodeRef pNode = pObjectsNode->getChild(i);
805 if (pNode->isTag("Object"))
807 const char * pType = pNode->getAttr("Type");
808 if (strstr(pType,"OccluderArea") || strstr(pType,"VisArea") || strstr(pType,"Portal"))
810 CVisArea * pArea = new CVisArea();
812 pArea->m_boxArea.max=SetMinBB();
813 pArea->m_boxArea.min=SetMaxBB();
816 strcpy(pArea->m_sName, pNode->getAttr("Name"));
817 strlwr(pArea->m_sName);
820 pNode->getAttr("Height",pArea->m_fHeight);
823 pNode->getAttr("AmbientColor", pArea->m_vAmbColor);
825 // set dynamic ambient color
826 // pNode->getAttr("DynAmbientColor", pArea->m_vDynAmbColor);
829 pNode->getAttr("SkyOnly", pArea->m_bSkyOnly);
831 // set AfectedByOutLights flag
832 pNode->getAttr("AffectedBySun", pArea->m_bAfectedByOutLights);
835 pNode->getAttr("ViewDistRatio", pArea->m_fViewDistRatio);
837 // set DoubleSide flag
838 pNode->getAttr("DoubleSide", pArea->m_bDoubleSide);
840 // set UseInIndoors flag
841 pNode->getAttr("UseInIndoors", pArea->m_bUseInIndoors);
843 if(strstr(pType, "OccluderArea"))
844 m_lstOcclAreas.Add(pArea);
845 else if(strstr(pArea->m_sName,"portal") || strstr(pType,"Portal"))
846 m_lstPortals.Add(pArea);
848 m_lstVisAreas.Add(pArea);
851 XmlNodeRef pPointsNode = pNode->findChild("Points");
853 for (int i = 0; i < pPointsNode->getChildCount(); i++)
855 XmlNodeRef pPointNode = pPointsNode->getChild(i);
858 if (pPointNode->isTag("Point") && pPointNode->getAttr("Pos", vPos))
860 pArea->m_lstShapePoints.Add(vPos);
861 pArea->m_boxArea.max.CheckMax(vPos);
862 pArea->m_boxArea.min.CheckMin(vPos);
863 pArea->m_boxArea.max.CheckMax(vPos+Vec3(0,0,pArea->m_fHeight));
864 pArea->m_boxArea.min.CheckMin(vPos+Vec3(0,0,pArea->m_fHeight));
867 pArea->UpdateGeometryBBox();
873 // load area boxes to support old way
874 // LoadVisAreaBoxFromXML(pDoc);
877 //THIS SHOULD ONLY BE CALLED BY THE EDITOR
878 void CVisAreaManager::UpdateVisArea(CVisArea
* pArea
, const Vec3
* pPoints
, int nCount
, const char* szName
, const SVisAreaInfo
& info
)
880 // on first update there will be nothing to delete, area will be added into list only in this function
881 m_lstPortals
.Delete(pArea
);
882 m_lstVisAreas
.Delete(pArea
);
883 m_lstOcclAreas
.Delete(pArea
);
885 SGenericColdData
* pColdData
= pArea
->GetColdData();
886 if (pColdData
!= NULL
)
888 delete pArea
->GetColdData();
889 pArea
->SetColdDataPtr(NULL
);
892 SGenericColdData
* pColdDataPtr
= NULL
;
895 cry_strcpy(sTemp
, szName
);
896 _strlwr_s(sTemp
, sizeof(sTemp
));
899 bool bPortal
= false;
900 bool bVisArea
= false;
901 bool bOcclArea
= false;
903 //TODO: Refactor with code below so it's not horrible
904 if (strstr(sTemp
, "portal"))
906 pColdDataPtr
= new SPortalColdData();
909 else if (strstr(sTemp
, "visarea"))
911 pColdDataPtr
= new SGenericColdData();
914 else if (strstr(sTemp
, "occlarea"))
916 pColdDataPtr
= new SGenericColdData();
921 pColdDataPtr
= new SGenericColdData();
924 assert(pColdDataPtr
);
925 pArea
->SetColdDataPtr(pColdDataPtr
);
927 pArea
->Update(pPoints
, nCount
, sTemp
, info
);
931 if (pArea
->m_lstConnections
.Count() == 1)
932 pArea
->UpdateGeometryBBox();
934 m_lstPortals
.Add(pArea
);
938 m_lstVisAreas
.Add(pArea
);
942 m_lstOcclAreas
.Add(pArea
);
947 // disable terrain culling for tunnels
948 pArea
->UpdateOcclusionFlagInTerrain();
954 void CVisAreaManager::UpdateConnections()
956 // Reset connectivity
957 for (int p
= 0; p
< m_lstPortals
.Count(); p
++)
958 m_lstPortals
[p
]->m_lstConnections
.Clear();
960 for (int v
= 0; v
< m_lstVisAreas
.Count(); v
++)
961 m_lstVisAreas
[v
]->m_lstConnections
.Clear();
963 // Init connectivity - check intersection of all areas and portals
964 for (int p
= 0; p
< m_lstPortals
.Count(); p
++)
966 for (int v
= 0; v
< m_lstVisAreas
.Count(); v
++)
968 if (m_lstVisAreas
[v
]->IsPortalIntersectAreaInValidWay(m_lstPortals
[p
]))
970 // if bboxes intersect
971 m_lstVisAreas
[v
]->m_lstConnections
.Add(m_lstPortals
[p
]);
972 m_lstPortals
[p
]->m_lstConnections
.Add(m_lstVisAreas
[v
]);
974 // set portal direction
975 Vec3 vNormal
= m_lstVisAreas
[v
]->GetConnectionNormal(m_lstPortals
[p
]);
976 if (m_lstPortals
[p
]->m_lstConnections
.Count() <= 2)
977 m_lstPortals
[p
]->m_vConnNormals
[m_lstPortals
[p
]->m_lstConnections
.Count() - 1] = vNormal
;
983 void CVisAreaManager::MoveObjectsIntoList(PodArray
<SRNInfo
>* plstVisAreasEntities
, const AABB
* boxArea
, bool bRemoveObjects
)
985 for (int p
= 0; p
< m_lstPortals
.Count(); p
++)
987 if (m_lstPortals
[p
]->IsObjectsTreeValid() && (!boxArea
|| Overlap::AABB_AABB(m_lstPortals
[p
]->m_boxArea
, *boxArea
)))
989 m_lstPortals
[p
]->GetObjectsTree()->MoveObjectsIntoList(plstVisAreasEntities
, boxArea
, bRemoveObjects
);
993 for (int v
= 0; v
< m_lstVisAreas
.Count(); v
++)
995 if (m_lstVisAreas
[v
]->IsObjectsTreeValid() && (!boxArea
|| Overlap::AABB_AABB(m_lstVisAreas
[v
]->m_boxArea
, *boxArea
)))
997 m_lstVisAreas
[v
]->GetObjectsTree()->MoveObjectsIntoList(plstVisAreasEntities
, boxArea
, bRemoveObjects
);
1002 void CVisAreaManager::CleanUpTrees()
1004 for (int p
= 0; p
< m_lstPortals
.Count(); p
++)
1006 if (m_lstPortals
[p
]->IsObjectsTreeValid())
1008 m_lstPortals
[p
]->GetObjectsTree()->CleanUpTree();
1012 for (int v
= 0; v
< m_lstVisAreas
.Count(); v
++)
1014 if (m_lstVisAreas
[v
]->IsObjectsTreeValid())
1016 m_lstVisAreas
[v
]->GetObjectsTree()->CleanUpTree();
1021 bool CVisAreaManager::IntersectsVisAreas(const AABB
& box
, void** pNodeCache
)
1023 FUNCTION_PROFILER_3DENGINE
;
1027 SAABBTreeNode
* pTopNode
= m_pAABBTree
->GetTopNode(box
, pNodeCache
);
1028 return pTopNode
->IntersectsVisAreas(box
);
1031 bool CVisAreaManager::ClipOutsideVisAreas(Sphere
& sphere
, Vec3
const& vNormal
, void* pNodeCache
)
1033 FUNCTION_PROFILER_3DENGINE
;
1037 AABB
box(sphere
.center
- Vec3(sphere
.radius
), sphere
.center
+ Vec3(sphere
.radius
));
1038 SAABBTreeNode
* pTopNode
= m_pAABBTree
->GetTopNode(box
, &pNodeCache
);
1039 return pTopNode
->ClipOutsideVisAreas(sphere
, vNormal
) > 0;
1042 //This is used by the editor. Use the visareas pool for all areas, so prefetching
1044 CVisArea
* CVisAreaManager::CreateVisArea(VisAreaGUID visGUID
)
1046 return new CVisArea(visGUID
);
1049 bool CVisAreaManager::IsEntityVisAreaVisibleRecursive(const CVisArea
* pVisArea
, int nMaxRecursion
, PodArray
<const CVisArea
*>* pUnavailableAreas
, const SRenderLight
* pLight
, const SRenderingPassInfo
& passInfo
) const
1051 int nAreaId
= pUnavailableAreas
->Count();
1052 pUnavailableAreas
->Add(pVisArea
);
1054 bool bFound
= false;
1057 // check is lsource area was rendered in prev frame
1058 if (abs(pVisArea
->m_nRndFrameId
- passInfo
.GetFrameID()) > 2)
1060 if (nMaxRecursion
> 1)
1062 for (int n
= 0; n
< pVisArea
->m_lstConnections
.Count(); n
++)
1064 // loop other sectors
1065 CVisArea
* pNeibArea
= (CVisArea
*)pVisArea
->m_lstConnections
[n
];
1066 if (-1 == pUnavailableAreas
->Find(pNeibArea
) &&
1067 (!pLight
|| Overlap::Sphere_AABB(Sphere(pLight
->m_Origin
, pLight
->m_fRadius
), *pNeibArea
->GetAABBox())))
1069 if (IsEntityVisAreaVisibleRecursive(pNeibArea
, nMaxRecursion
- 1, pUnavailableAreas
, pLight
, passInfo
))
1081 else if (IsOutdoorAreasVisible()) //Indirect - outdoor can be a problem!
1084 pUnavailableAreas
->Delete(nAreaId
);
1088 bool CVisAreaManager::IsEntityVisAreaVisible(const IRenderNode
* pEnt
, int nMaxReqursion
, const SRenderLight
* pLight
, const SRenderingPassInfo
& passInfo
) const
1093 PodArray
<const CVisArea
*> lUnavailableAreas
;
1095 lUnavailableAreas
.Clear();
1096 lUnavailableAreas
.PreAllocate(nMaxReqursion
, 0);
1098 return IsEntityVisAreaVisibleRecursive((CVisArea
*)pEnt
->GetEntityVisArea(), nMaxReqursion
, &lUnavailableAreas
, pLight
, passInfo
);
1101 int __cdecl
CVisAreaManager__CmpDistToPortal(const void* v1
, const void* v2
)
1103 CVisArea
* p1
= *((CVisArea
**)v1
);
1104 CVisArea
* p2
= *((CVisArea
**)v2
);
1109 if (p1
->m_fDistance
> p2
->m_fDistance
)
1111 else if (p1
->m_fDistance
< p2
->m_fDistance
)
1117 void CVisAreaManager::MakeActiveEntransePortalsList(const CCamera
* pCamera
, PodArray
<CVisArea
*>& lstActiveEntransePortals
, CVisArea
* pThisPortal
, const SRenderingPassInfo
& passInfo
)
1119 lstActiveEntransePortals
.Clear();
1120 float fZoomFactor
= passInfo
.GetZoomFactor();
1122 for (int nPortalId
= 0; nPortalId
< m_lstPortals
.Count(); nPortalId
++)
1124 CVisArea
* pPortal
= m_lstPortals
[nPortalId
];
1126 if (pPortal
->m_lstConnections
.Count() == 1 && pPortal
!= pThisPortal
&& pPortal
->IsActive() && !pPortal
->m_bSkyOnly
)
1128 if (!pCamera
|| pCamera
->IsAABBVisible_F(pPortal
->m_boxStatics
))
1130 Vec3 vNormal
= pPortal
->m_lstConnections
[0]->GetConnectionNormal(pPortal
);
1131 Vec3 vCenter
= (pPortal
->m_boxArea
.min
+ pPortal
->m_boxArea
.max
) * 0.5f
;
1132 if (vNormal
.Dot(vCenter
- (pCamera
? pCamera
->GetPosition() : passInfo
.GetCamera().GetPosition())) < 0)
1137 vNormal = pCurPortal->m_vConnNormals[0];
1138 if(vNormal.Dot(vCenter - curCamera.GetPosition())<0)
1142 pPortal
->m_fDistance
= pPortal
->m_boxArea
.GetDistance(pCamera
? pCamera
->GetPosition() : passInfo
.GetCamera().GetPosition());
1144 float fRadius
= (pPortal
->m_boxArea
.max
- pPortal
->m_boxArea
.min
).GetLength() * 0.5f
;
1145 if (pPortal
->m_fDistance
* fZoomFactor
> fRadius
* pPortal
->m_fViewDistRatio
* GetFloatCVar(e_ViewDistRatioPortals
) / 60.f
)
1148 SPortalColdData
* pColdData
= static_cast<SPortalColdData
*>(pPortal
->GetColdData());
1151 if (GetObjManager()->IsBoxOccluded(pPortal
->m_boxStatics
, pPortal
->m_fDistance
, &pColdData
->m_occlusionTestClient
, false, eoot_PORTAL
, passInfo
))
1154 lstActiveEntransePortals
.Add(pPortal
);
1156 // if(GetCVars()->e_Portals==3)
1157 // DrawBBox(pPortal->m_boxStatics.min, pPortal->m_boxStatics.max);
1163 if (lstActiveEntransePortals
.Count())
1165 qsort(&lstActiveEntransePortals
[0], lstActiveEntransePortals
.Count(),
1166 sizeof(lstActiveEntransePortals
[0]), CVisAreaManager__CmpDistToPortal
);
1167 // m_pCurPortal = lstActiveEntransePortals[0];
1171 void CVisAreaManager::MergeCameras(CCamera
& cam1
, const CCamera
& cam2
, const SRenderingPassInfo
& passInfo
)
1173 assert(0); // under development
1175 float fDotLR1 = cam1.GetFrustumPlane(FR_PLANE_LEFT )->n.Dot(cam1.GetFrustumPlane(FR_PLANE_RIGHT)->n);
1176 float fDotRL2 = cam2.GetFrustumPlane(FR_PLANE_RIGHT)->n.Dot(cam2.GetFrustumPlane(FR_PLANE_LEFT)->n);
1181 float fDotLR
= cam1
.GetFrustumPlane(FR_PLANE_LEFT
)->n
.Dot(cam2
.GetFrustumPlane(FR_PLANE_RIGHT
)->n
);
1182 float fDotRL
= cam1
.GetFrustumPlane(FR_PLANE_RIGHT
)->n
.Dot(cam2
.GetFrustumPlane(FR_PLANE_LEFT
)->n
);
1183 if (fabs(fDotLR
) < fabs(fDotRL
))
1185 cam1
.SetFrustumPlane(FR_PLANE_RIGHT
, *cam2
.GetFrustumPlane(FR_PLANE_RIGHT
));
1186 cam1
.SetPPVertex(2, cam2
.GetPPVertex(2));
1187 cam1
.SetPPVertex(3, cam2
.GetPPVertex(3));
1191 cam1
.SetFrustumPlane(FR_PLANE_LEFT
, *cam2
.GetFrustumPlane(FR_PLANE_LEFT
));
1192 cam1
.SetPPVertex(0, cam2
.GetPPVertex(0));
1193 cam1
.SetPPVertex(1, cam2
.GetPPVertex(1));
1198 float fDotLR1 = cam1.GetFrustumPlane(FR_PLANE_LEFT )->n.Dot(cam1.GetFrustumPlane(FR_PLANE_RIGHT)->n);
1199 float fDotRL2 = cam2.GetFrustumPlane(FR_PLANE_RIGHT)->n.Dot(cam2.GetFrustumPlane(FR_PLANE_LEFT)->n);
1204 float fDotTB = cam1.GetFrustumPlane(FR_PLANE_TOP )->n.Dot(cam2.GetFrustumPlane(FR_PLANE_BOTTOM)->n);
1205 float fDotBT = cam1.GetFrustumPlane(FR_PLANE_BOTTOM)->n.Dot(cam2.GetFrustumPlane(FR_PLANE_TOP )->n);
1208 cam1.SetFrustumPlane(FR_PLANE_BOTTOM, *cam2.GetFrustumPlane(FR_PLANE_BOTTOM));
1210 cam1.SetFrustumPlane(FR_PLANE_TOP, *cam2.GetFrustumPlane(FR_PLANE_TOP));
1212 cam1
.SetFrustumPlane(FR_PLANE_NEAR
, *passInfo
.GetCamera().GetFrustumPlane(FR_PLANE_NEAR
));
1213 cam1
.SetFrustumPlane(FR_PLANE_FAR
, *passInfo
.GetCamera().GetFrustumPlane(FR_PLANE_FAR
));
1215 cam1
.SetFrustumPlane(FR_PLANE_TOP
, *passInfo
.GetCamera().GetFrustumPlane(FR_PLANE_TOP
));
1216 cam1
.SetFrustumPlane(FR_PLANE_BOTTOM
, *passInfo
.GetCamera().GetFrustumPlane(FR_PLANE_BOTTOM
));
1218 //cam1.UpdateFrustum();
1220 if(GetCVars()->e_Portals==4)
1222 GetRenderer()->SetMaterialColor(1,1,1,1);
1223 DrawBBox(pVerts[0],pVerts[1],DPRIM_LINE);
1224 GetRenderer()->DrawLabel(pVerts[0],2,"0");
1225 DrawBBox(pVerts[1],pVerts[2],DPRIM_LINE);
1226 GetRenderer()->DrawLabel(pVerts[1],2,"1");
1227 DrawBBox(pVerts[2],pVerts[3],DPRIM_LINE);
1228 GetRenderer()->DrawLabel(pVerts[2],2,"2");
1229 DrawBBox(pVerts[3],pVerts[0],DPRIM_LINE);
1230 GetRenderer()->DrawLabel(pVerts[3],2,"3");
1234 void CVisAreaManager::DrawOcclusionAreasIntoCBuffer(const SRenderingPassInfo
& passInfo
)
1236 FUNCTION_PROFILER_3DENGINE
;
1238 m_lstActiveOcclVolumes
.Clear();
1239 m_lstIndoorActiveOcclVolumes
.Clear();
1241 float fDistRatio
= GetFloatCVar(e_OcclusionVolumesViewDistRatio
) * passInfo
.GetInverseZoomFactor();
1243 if (GetCVars()->e_OcclusionVolumes
)
1244 for (int i
= 0; i
< m_lstOcclAreas
.Count(); i
++)
1246 CVisArea
* pArea
= m_lstOcclAreas
[i
];
1247 if (pArea
->m_bActive
&& passInfo
.GetCamera().IsAABBVisible_E(pArea
->m_boxArea
))
1249 float fRadius
= (pArea
->m_boxArea
.min
- pArea
->m_boxArea
.max
).GetLength();
1250 Vec3 vPos
= (pArea
->m_boxArea
.min
+ pArea
->m_boxArea
.max
) * 0.5f
;
1251 float fDist
= passInfo
.GetCamera().GetPosition().GetDistance(vPos
);
1252 if (fDist
< fRadius
* pArea
->m_fViewDistRatio
* fDistRatio
&& pArea
->m_lstShapePoints
.Count() >= 2)
1254 int nRecursiveLevel
= passInfo
.GetRecursiveLevel();
1255 if (!pArea
->m_arrOcclCamera
[nRecursiveLevel
])
1256 pArea
->m_arrOcclCamera
[nRecursiveLevel
] = new CCamera
;
1257 *pArea
->m_arrOcclCamera
[nRecursiveLevel
] = passInfo
.GetCamera();
1259 SActiveVerts activeVerts
;
1261 if (pArea
->m_lstShapePoints
.Count() == 4)
1263 activeVerts
.arrvActiveVerts
[0] = pArea
->m_lstShapePoints
[0];
1264 activeVerts
.arrvActiveVerts
[1] = pArea
->m_lstShapePoints
[1];
1265 activeVerts
.arrvActiveVerts
[2] = pArea
->m_lstShapePoints
[2];
1266 activeVerts
.arrvActiveVerts
[3] = pArea
->m_lstShapePoints
[3];
1270 CRY_ASSERT(pArea
->m_lstShapePoints
.Count() == 2, "Occlusion area only supports planes or quads");
1272 activeVerts
.arrvActiveVerts
[0] = pArea
->m_lstShapePoints
[0];
1273 activeVerts
.arrvActiveVerts
[1] = pArea
->m_lstShapePoints
[0] + Vec3(0, 0, pArea
->m_fHeight
);
1274 activeVerts
.arrvActiveVerts
[2] = pArea
->m_lstShapePoints
[1] + Vec3(0, 0, pArea
->m_fHeight
);
1275 activeVerts
.arrvActiveVerts
[3] = pArea
->m_lstShapePoints
[1];
1279 plane
.SetPlane(activeVerts
.arrvActiveVerts
[0], activeVerts
.arrvActiveVerts
[2], activeVerts
.arrvActiveVerts
[1]);
1281 if (plane
.DistFromPlane(passInfo
.GetCamera().GetPosition()) < 0)
1283 std::swap(activeVerts
.arrvActiveVerts
[0], activeVerts
.arrvActiveVerts
[3]);
1284 std::swap(activeVerts
.arrvActiveVerts
[1], activeVerts
.arrvActiveVerts
[2]);
1286 else if (!pArea
->m_bDoubleSide
)
1289 // GetRenderer()->SetMaterialColor(1,0,0,1);
1290 pArea
->UpdatePortalCameraPlanes(*pArea
->m_arrOcclCamera
[passInfo
.GetRecursiveLevel()], activeVerts
.arrvActiveVerts
, false, passInfo
);
1292 // make far plane never clip anything
1295 newNearPlane
.SetPlane(activeVerts
.arrvActiveVerts
[0], activeVerts
.arrvActiveVerts
[2], activeVerts
.arrvActiveVerts
[1]);
1296 pArea
->m_arrOcclCamera
[passInfo
.GetRecursiveLevel()]->SetFrustumPlane(FR_PLANE_NEAR
, newNearPlane
);
1299 newFarPlane
.SetPlane(Vec3(0, 1, -1024), Vec3(1, 0, -1024), Vec3(0, 0, -1024));
1300 pArea
->m_arrOcclCamera
[passInfo
.GetRecursiveLevel()]->SetFrustumPlane(FR_PLANE_FAR
, newFarPlane
);
1301 //pArea->m_arrOcclCamera[m_nRenderStackLevel]->UpdateFrustum();
1303 m_lstActiveOcclVolumes
.Add(pArea
);
1304 pArea
->m_fDistance
= fDist
;
1309 if (m_lstActiveOcclVolumes
.Count())
1311 // sort occluders by distance to the camera
1312 qsort(&m_lstActiveOcclVolumes
[0], m_lstActiveOcclVolumes
.Count(),
1313 sizeof(m_lstActiveOcclVolumes
[0]), CVisAreaManager__CmpDistToPortal
);
1315 // remove occluded occluders
1316 for (int i
= m_lstActiveOcclVolumes
.Count() - 1; i
>= 0; i
--)
1318 CVisArea
* pArea
= m_lstActiveOcclVolumes
[i
];
1319 AABB extrudedBox
= pArea
->m_boxStatics
;
1320 extrudedBox
.min
-= Vec3(VEC_EPSILON
, VEC_EPSILON
, VEC_EPSILON
);
1321 extrudedBox
.max
+= Vec3(VEC_EPSILON
, VEC_EPSILON
, VEC_EPSILON
);
1322 if (IsOccludedByOcclVolumes(extrudedBox
, passInfo
))
1323 m_lstActiveOcclVolumes
.Delete(i
);
1326 // put indoor occluders into separate list
1327 for (int i
= m_lstActiveOcclVolumes
.Count() - 1; i
>= 0; i
--)
1329 CVisArea
* pArea
= m_lstActiveOcclVolumes
[i
];
1330 if (pArea
->m_bUseInIndoors
)
1331 m_lstIndoorActiveOcclVolumes
.Add(pArea
);
1334 if (GetCVars()->e_Portals
== 4)
1336 // show really active occluders
1337 for (int i
= 0; i
< m_lstActiveOcclVolumes
.Count(); i
++)
1339 CVisArea
* pArea
= m_lstActiveOcclVolumes
[i
];
1340 DrawBBox(pArea
->m_boxStatics
.min
, pArea
->m_boxStatics
.max
, ColorB(0, 255, 0));
1347 void CVisAreaManager::CompileObjects()
1350 for(int v=0; v<m_lstVisAreas.Count(); v++)
1351 m_lstVisAreas[v]->CompileObjects(STATIC_OBJECTS);
1354 for(int v=0; v<m_lstPortals.Count(); v++)
1355 m_lstPortals[v]->CompileObjects(STATIC_OBJECTS);
1359 void CVisAreaManager::CheckUnload()
1364 for(int v=0; v<m_lstVisAreas.Count(); v++)
1365 m_nLoadedSectors += m_lstVisAreas[v]->CheckUnload();
1368 for(int v=0; v<m_lstPortals.Count(); v++)
1369 m_nLoadedSectors += m_lstPortals[v]->CheckUnload();
1372 void CVisAreaManager::GetStreamingStatus(int& nLoadedSectors
, int& nTotalSectors
)
1374 nLoadedSectors
= 0;//m_nLoadedSectors;
1375 nTotalSectors
= m_lstPortals
.Count() + m_lstVisAreas
.Count();
1378 void CVisAreaManager::GetMemoryUsage(ICrySizer
* pSizer
) const
1381 for (int v
= 0; v
< m_lstVisAreas
.Count(); v
++)
1382 m_lstVisAreas
[v
]->GetMemoryUsage(pSizer
);
1385 for (int v
= 0; v
< m_lstPortals
.Count(); v
++)
1386 m_lstPortals
[v
]->GetMemoryUsage(pSizer
);
1389 for (int v
= 0; v
< m_lstOcclAreas
.Count(); v
++)
1390 m_lstOcclAreas
[v
]->GetMemoryUsage(pSizer
);
1392 pSizer
->AddObject(this, sizeof(*this));
1395 void CVisAreaManager::PrecacheLevel(bool bPrecacheAllVisAreas
, Vec3
* pPrecachePoints
, int nPrecachePointsNum
)
1397 CryLog("Precaching the level ...");
1398 // gEnv->pLog->UpdateLoadingScreen(0);
1400 #if !defined(EXCLUDE_NORMAL_LOG)
1401 float fPrecacheTimeStart
= GetTimer()->GetAsyncCurTime();
1404 int nRenderingFlags
= SHDF_ZPASS
| SHDF_ALLOWHDR
| SHDF_ALLOWPOSTPROCESS
| SHDF_ALLOW_WATER
| SHDF_ALLOW_AO
| SHDF_ALLOW_SKY
;
1406 GetRenderer()->EnableSwapBuffers((GetCVars()->e_PrecacheLevel
>= 2) ? true : false);
1408 uint32 dwPrecacheLocations
= 0;
1420 //loop over all sectors and place a light in the middle of the sector
1421 for (int v
= 0; v
< m_lstVisAreas
.Count() && bPrecacheAllVisAreas
; v
++)
1423 GetRenderer()->EF_Query(EFQ_IncrementFrameID
);
1425 ++dwPrecacheLocations
;
1427 // find real geometry bbox
1428 /* bool bGeomFound = false;
1429 Vec3 vBoxMin(100000.f,100000.f,100000.f);
1430 Vec3 vBoxMax(-100000.f,-100000.f,-100000.f);
1431 for(int s=0; s<ENTITY_LISTS_NUM; s++)
1432 for(int e=0; e<m_lstVisAreas[v]->m_lstEntities[s].Count(); e++)
1434 AABB aabbBox = m_lstVisAreas[v]->m_lstEntities[s][e].aabbBox;
1435 vBoxMin.CheckMin(aabbBox.min);
1436 vBoxMax.CheckMax(aabbBox.max);
1440 Vec3 vAreaCenter
= m_lstVisAreas
[v
]->m_boxArea
.GetCenter();
1441 CryLog(" Precaching VisArea %s", m_lstVisAreas
[v
]->GetName());
1443 //place camera in the middle of a sector and render sector from different directions
1444 for (int i
= 0; i
< 6 /*&& bGeomFound*/; i
++)
1447 CCamera cam
= gEnv
->pSystem
->GetViewCamera();
1448 Matrix33 mat
= Matrix33::CreateRotationVDir(arrCamDir
[i
], 0);
1450 cam
.SetPosition(vAreaCenter
);
1451 cam
.SetFrustum(GetRenderer()->GetOverlayWidth(), GetRenderer()->GetOverlayHeight(), gf_PI
/ 2, cam
.GetNearPlane(), cam
.GetFarPlane());
1452 // Get3DEngine()->SetupCamera(cam);
1454 GetRenderer()->BeginFrame({}, SGraphicsPipelineKey::BaseGraphicsPipelineKey
);
1455 Get3DEngine()->RenderWorld(nRenderingFlags
, SRenderingPassInfo::CreateGeneralPassRenderingInfo(SGraphicsPipelineKey::BaseGraphicsPipelineKey
, cam
), "PrecacheVisAreas");
1456 GetRenderer()->RenderDebug();
1457 GetRenderer()->EndFrame();
1459 if (GetCVars()->e_PrecacheLevel
>= 2)
1464 CryLog("Precached %u visarea sectors", dwPrecacheLocations
);
1466 //--------------------------------------------------------------------------------------
1467 //---- PRE-FETCHING OF RENDER-DATA IN OUTDOORS ----
1468 //--------------------------------------------------------------------------------------
1470 // loop over all cam-position in the level and render this part of the level from 6 different directions
1471 for (int p
= 0; pPrecachePoints
&& p
< nPrecachePointsNum
; p
++) //loop over outdoor-camera position
1473 CryLog(" Precaching PrecacheCamera point %d of %d", p
, nPrecachePointsNum
);
1474 for (int i
= 0; i
< 6; i
++) //loop over 6 camera orientations
1477 CCamera cam
= gEnv
->pSystem
->GetViewCamera();
1478 Matrix33 mat
= Matrix33::CreateRotationVDir(arrCamDir
[i
], 0);
1480 cam
.SetPosition(pPrecachePoints
[p
]);
1481 cam
.SetFrustum(GetRenderer()->GetOverlayWidth(), GetRenderer()->GetOverlayHeight(), gf_PI
/ 2, cam
.GetNearPlane(), cam
.GetFarPlane());
1483 GetRenderer()->BeginFrame({}, SGraphicsPipelineKey::BaseGraphicsPipelineKey
);
1484 Get3DEngine()->RenderWorld(nRenderingFlags
, SRenderingPassInfo::CreateGeneralPassRenderingInfo(SGraphicsPipelineKey::BaseGraphicsPipelineKey
, cam
), "PrecacheOutdoor");
1485 GetRenderer()->RenderDebug();
1486 GetRenderer()->EndFrame();
1488 if (GetCVars()->e_PrecacheLevel
>= 2)
1493 CryLog("Precached %d PrecacheCameraXX points", nPrecachePointsNum
);
1495 GetRenderer()->EnableSwapBuffers(true);
1497 #if !defined(EXCLUDE_NORMAL_LOG)
1498 float fPrecacheTime
= GetTimer()->GetAsyncCurTime() - fPrecacheTimeStart
;
1499 CryLog("Level Precache finished in %.2f seconds", fPrecacheTime
);
1503 void CVisAreaManager::GetObjectsAround(Vec3 vExploPos
, float fExploRadius
, PodArray
<SRNInfo
>* pEntList
, bool bSkip_ERF_NO_DECALNODE_DECALS
, bool bSkipDynamicObjects
)
1505 AABB
aabbBox(vExploPos
- Vec3(fExploRadius
, fExploRadius
, fExploRadius
), vExploPos
+ Vec3(fExploRadius
, fExploRadius
, fExploRadius
));
1507 CVisArea
* pVisArea
= (CVisArea
*)GetVisAreaFromPos(vExploPos
);
1509 if (pVisArea
&& pVisArea
->IsObjectsTreeValid())
1511 pVisArea
->GetObjectsTree()->MoveObjectsIntoList(pEntList
, &aabbBox
, false, true, bSkip_ERF_NO_DECALNODE_DECALS
, bSkipDynamicObjects
);
1515 // find static objects around
1516 for(int i=0; pVisArea && i<pVisArea->m_lstEntities[STATIC_OBJECTS].Count(); i++)
1518 IRenderNode * pRenderNode = pVisArea->m_lstEntities[STATIC_OBJECTS][i].pNode;
1519 if(bSkip_ERF_NO_DECALNODE_DECALS && pRenderNode->GetRndFlags()&ERF_NO_DECALNODE_DECALS)
1522 if(pRenderNode->GetRenderNodeType() == eERType_Decal)
1525 if(Overlap::Sphere_AABB(Sphere(vExploPos,fExploRadius), pRenderNode->GetBBox()))
1526 if(pEntList->Find(pRenderNode)<0)
1527 pEntList->Add(pRenderNode);
1531 void CVisAreaManager::IntersectWithBox(const AABB
& aabbBox
, PodArray
<CVisArea
*>* plstResult
, bool bOnlyIfVisible
)
1533 for (int p
= 0; p
< m_lstPortals
.Count(); p
++)
1535 if (m_lstPortals
[p
]->m_boxArea
.min
.x
<aabbBox
.max
.x
&& m_lstPortals
[p
]->m_boxArea
.max
.x
> aabbBox
.min
.x
&&
1536 m_lstPortals
[p
]->m_boxArea
.min
.y
<aabbBox
.max
.y
&& m_lstPortals
[p
]->m_boxArea
.max
.y
> aabbBox
.min
.y
)
1538 plstResult
->Add(m_lstPortals
[p
]);
1542 for (int v
= 0; v
< m_lstVisAreas
.Count(); v
++)
1544 if (m_lstVisAreas
[v
]->m_boxArea
.min
.x
<aabbBox
.max
.x
&& m_lstVisAreas
[v
]->m_boxArea
.max
.x
> aabbBox
.min
.x
&&
1545 m_lstVisAreas
[v
]->m_boxArea
.min
.y
<aabbBox
.max
.y
&& m_lstVisAreas
[v
]->m_boxArea
.max
.y
> aabbBox
.min
.y
)
1547 plstResult
->Add(m_lstVisAreas
[v
]);
1552 int CVisAreaManager::GetNumberOfVisArea() const
1554 return m_lstPortals
.size() + m_lstVisAreas
.size();
1557 IVisArea
* CVisAreaManager::GetVisAreaById(int nID
) const
1562 if (nID
< (int)m_lstPortals
.size())
1564 return m_lstPortals
[nID
];
1566 nID
-= m_lstPortals
.size();
1567 if (nID
< (int)m_lstVisAreas
.size())
1569 return m_lstVisAreas
[nID
];
1575 //////////////////////////////////////////////////////////////////////////
1576 void CVisAreaManager::AddListener(IVisAreaCallback
* pListener
)
1578 if (m_lstCallbacks
.Find(pListener
) < 0)
1579 m_lstCallbacks
.Add(pListener
);
1582 //////////////////////////////////////////////////////////////////////////
1583 void CVisAreaManager::RemoveListener(IVisAreaCallback
* pListener
)
1585 m_lstCallbacks
.Delete(pListener
);
1588 void CVisAreaManager::CloneRegion(const AABB
& region
, const Vec3
& offset
, float zRotation
)
1590 PodArray
<Vec3
> points
;
1592 PodArray
<CVisArea
*> visAreas
;
1593 IntersectWithBox(region
, &visAreas
, false);
1595 Vec3 localOrigin
= region
.GetCenter();
1596 Matrix34
l2w(Matrix33::CreateRotationZ(zRotation
));
1597 l2w
.SetTranslation(offset
);
1599 int numAreas
= visAreas
.size();
1600 for (int i
= 0; i
< numAreas
; ++i
)
1602 CVisArea
* pSrcArea
= visAreas
[i
];
1603 CVisArea
* pCloneArea
= CreateVisArea(0);
1606 info
.fHeight
= pSrcArea
->m_fHeight
;
1607 info
.vAmbientColor
= pSrcArea
->m_vAmbientColor
;
1608 info
.bAffectedByOutLights
= pSrcArea
->m_bAffectedByOutLights
;
1609 info
.bIgnoreSkyColor
= pSrcArea
->m_bIgnoreSky
;
1610 info
.bSkyOnly
= pSrcArea
->m_bSkyOnly
;
1611 info
.fViewDistRatio
= pSrcArea
->m_fViewDistRatio
;
1612 info
.bDoubleSide
= pSrcArea
->m_bDoubleSide
;
1613 info
.bUseDeepness
= pSrcArea
->m_bUseDeepness
;
1614 info
.bUseInIndoors
= pSrcArea
->m_bUseInIndoors
;
1615 info
.bOceanIsVisible
= pSrcArea
->m_bOceanVisible
;
1616 info
.bIgnoreGI
= pSrcArea
->m_bIgnoreGI
;
1617 info
.bIgnoreOutdoorAO
= pSrcArea
->m_bIgnoreOutdoorAO
;
1619 points
= pSrcArea
->m_lstShapePoints
;
1620 int numPoints
= points
.size();
1621 for (int p
= 0; p
< numPoints
; ++p
)
1623 Vec3
& point
= points
[p
];
1625 point
-= localOrigin
;
1626 point
= l2w
* point
;
1629 const char* pName
= pSrcArea
->m_pVisAreaColdData
->m_sName
;
1631 UpdateVisArea(pCloneArea
, &points
[0], numPoints
, pName
, info
);
1635 void CVisAreaManager::ClearRegion(const AABB
& region
)
1637 PodArray
<CVisArea
*> visAreas
;
1638 IntersectWithBox(region
, &visAreas
, false);
1640 bool updated
= false;
1642 // What we're doing here is basically just what's done in DeleteVisArea, but this
1643 // should be a pooled vis area, so we don't want to actually delete it. Instead we
1644 // just unregister them and let the pool cleanup actually destruct them.
1645 int numAreas
= visAreas
.size();
1646 for (int i
= 0; i
< numAreas
; ++i
)
1648 CVisArea
* pVisArea
= visAreas
[i
];
1650 // IntersectWithBox only checks x and y, but we want to also make sure it's in the z
1651 if (pVisArea
->m_boxArea
.min
.z
< region
.max
.z
&& pVisArea
->m_boxArea
.max
.z
> region
.min
.z
)
1653 bool deletedVis
= m_lstVisAreas
.Delete(pVisArea
);
1654 bool deletedPortal
= m_lstPortals
.Delete(pVisArea
);
1655 bool deletedOccluder
= m_lstOcclAreas
.Delete(pVisArea
);
1657 CRY_ASSERT(!deletedVis
|| (m_visAreas
.Find(pVisArea
) >= 0), "Should only clear pooled vis areas, going to leak");
1658 CRY_ASSERT(!deletedPortal
|| (m_portals
.Find(pVisArea
) >= 0), "Should only clear pooled portals, going to leak");
1659 CRY_ASSERT(!deletedOccluder
|| (m_occlAreas
.Find(pVisArea
) >= 0), "Should only clear pooled occluders, going to leak");
1661 if (deletedVis
|| deletedPortal
|| deletedOccluder
)
1666 m_lstActiveOcclVolumes
.Delete(pVisArea
);
1667 m_lstIndoorActiveOcclVolumes
.Delete(pVisArea
);
1668 m_lstActiveEntransePortals
.Delete(pVisArea
);
1675 m_pCurPortal
= NULL
;
1676 UpdateConnections();
1685 inline void HelperMarkAllSectorsAsUncompiled(PodArray
<CVisArea
*>& arrayVisArea
)
1687 int s
= arrayVisArea
.Count();
1688 for (int i
= 0; i
< s
; ++i
)
1690 if (arrayVisArea
[i
]->IsObjectsTreeValid())
1692 arrayVisArea
[i
]->GetObjectsTree()->MarkAsUncompiled();
1697 inline void HelperActivateObjectsLayer(PodArray
<CVisArea
*>& arrayVisArea
, uint16 nLayerId
, bool bActivate
, bool bPhys
, IGeneralMemoryHeap
* pHeap
, const AABB
& layerBox
)
1699 int s
= arrayVisArea
.Count();
1700 for (int i
= 0; i
< s
; ++i
)
1702 if (arrayVisArea
[i
]->IsObjectsTreeValid())
1704 arrayVisArea
[i
]->GetObjectsTree()->ActivateObjectsLayer(nLayerId
, bActivate
, bPhys
, pHeap
, layerBox
);
1709 inline void HelperGetObjects(PodArray
<CVisArea
*>& arrayVisArea
, PodArray
<IRenderNode
*>& lstObjects
, const AABB
* pBBox
)
1711 int s
= arrayVisArea
.Count();
1712 for (int i
= 0; i
< s
; ++i
)
1714 if (arrayVisArea
[i
]->IsObjectsTreeValid())
1716 arrayVisArea
[i
]->GetObjectsTree()->GetObjects(lstObjects
, pBBox
);
1721 inline void HelperGetObjectsByFlags(PodArray
<CVisArea
*>& arrayVisArea
, uint dwFlags
, PodArray
<IRenderNode
*>& lstObjects
)
1723 int s
= arrayVisArea
.Count();
1724 for (int i
= 0; i
< s
; ++i
)
1726 if (arrayVisArea
[i
]->IsObjectsTreeValid())
1728 arrayVisArea
[i
]->GetObjectsTree()->GetObjectsByFlags(dwFlags
, lstObjects
);
1733 inline void HelperGenerateStatObjAndMatTables(PodArray
<CVisArea
*>& arrayVisArea
, std::vector
<IStatObj
*>* pStatObjTable
, std::vector
<IMaterial
*>* pMatTable
, std::vector
<IStatInstGroup
*>* pStatInstGroupTable
, SHotUpdateInfo
* pExportInfo
)
1735 int s
= arrayVisArea
.Count();
1736 for (int i
= 0; i
< s
; ++i
)
1738 if (arrayVisArea
[i
]->IsObjectsTreeValid())
1740 arrayVisArea
[i
]->GetObjectsTree()->GenerateStatObjAndMatTables(pStatObjTable
, pMatTable
, pStatInstGroupTable
, pExportInfo
);
1746 void CVisAreaManager::MarkAllSectorsAsUncompiled()
1748 HelperMarkAllSectorsAsUncompiled(m_lstPortals
);
1749 HelperMarkAllSectorsAsUncompiled(m_lstVisAreas
);
1752 void CVisAreaManager::ActivateObjectsLayer(uint16 nLayerId
, bool bActivate
, bool bPhys
, IGeneralMemoryHeap
* pHeap
, const AABB
& layerBox
)
1754 HelperActivateObjectsLayer(m_lstVisAreas
, nLayerId
, bActivate
, bPhys
, pHeap
, layerBox
);
1755 HelperActivateObjectsLayer(m_lstPortals
, nLayerId
, bActivate
, bPhys
, pHeap
, layerBox
);
1758 void CVisAreaManager::GetObjects(PodArray
<IRenderNode
*>& lstObjects
, const AABB
* pBBox
)
1760 HelperGetObjects(m_lstVisAreas
, lstObjects
, pBBox
);
1761 HelperGetObjects(m_lstPortals
, lstObjects
, pBBox
);
1764 void CVisAreaManager::GetObjectsByFlags(uint dwFlags
, PodArray
<IRenderNode
*>& lstObjects
)
1766 HelperGetObjectsByFlags(m_lstVisAreas
, dwFlags
, lstObjects
);
1767 HelperGetObjectsByFlags(m_lstPortals
, dwFlags
, lstObjects
);
1770 void CVisAreaManager::GenerateStatObjAndMatTables(std::vector
<IStatObj
*>* pStatObjTable
, std::vector
<IMaterial
*>* pMatTable
, std::vector
<IStatInstGroup
*>* pStatInstGroupTable
, SHotUpdateInfo
* pExportInfo
)
1772 HelperGenerateStatObjAndMatTables(m_lstVisAreas
, pStatObjTable
, pMatTable
, pStatInstGroupTable
, pExportInfo
);
1773 HelperGenerateStatObjAndMatTables(m_lstPortals
, pStatObjTable
, pMatTable
, pStatInstGroupTable
, pExportInfo
);
1776 bool CVisAreaManager::IsAABBVisibleFromPoint(AABB
& box
, Vec3 pos
) const
1778 CVisArea
* pAreaBox
= (CVisArea
*)GetVisAreaFromPos(box
.GetCenter());
1779 CVisArea
* pAreaPos
= (CVisArea
*)GetVisAreaFromPos(pos
);
1781 if (!pAreaBox
&& !pAreaPos
)
1782 return true; // no indoors involved
1784 PodArray
<CVisArea
*> arrPortals
;
1787 NAABB_SV::AABB_ReceiverShadowVolume(pos
, box
, sv
);
1789 bool bRes
= FindShortestPathToVisArea(pAreaPos
, pAreaBox
, arrPortals
, nRecursion
, sv
);
1791 IRenderAuxText::DrawLabelF(box
.GetCenter(), 2, "-%s-", bRes
? "Y" : "N");
1792 IRenderAuxText::DrawLabel(pos
, 2, "-X-");
1793 DrawLine(pos
, box
.GetCenter());
1794 DrawBBox(box
, bRes
? Col_White
: Col_NavyBlue
);
1799 bool CVisAreaManager::FindShortestPathToVisArea(CVisArea
* pThisArea
, CVisArea
* pTargetArea
, PodArray
<CVisArea
*>& arrVisitedAreas
, int& nRecursion
, const Shadowvolume
& sv
) const
1801 // skip double processing
1802 if (arrVisitedAreas
.Find(pThisArea
) >= 0)
1805 // check if point to box frustum intersects pThisArea visarea
1806 if (pThisArea
&& !NAABB_SV::Is_AABB_In_ShadowVolume(sv
, *pThisArea
->GetAABBox()))
1809 // check if box visarea reached
1810 if (pThisArea
== pTargetArea
)
1813 // register as already processed
1814 arrVisitedAreas
.Add(pThisArea
);
1816 // recurse to connections
1819 for (int p
= 0; p
< pThisArea
->m_lstConnections
.Count(); p
++)
1820 if (FindShortestPathToVisArea(pThisArea
->m_lstConnections
[p
], pTargetArea
, arrVisitedAreas
, nRecursion
, sv
))
1823 if (pThisArea
->IsPortal() && pThisArea
->m_lstConnections
.Count() == 1 && !pThisArea
->m_bSkyOnly
)
1824 if (FindShortestPathToVisArea(NULL
, pTargetArea
, arrVisitedAreas
, nRecursion
, sv
))
1829 for (int p
= 0; p
< m_lstPortals
.Count(); p
++)
1830 if (m_lstPortals
[p
]->IsPortal() && m_lstPortals
[p
]->m_lstConnections
.Count() == 1 && !m_lstPortals
[p
]->m_bSkyOnly
)
1831 if (FindShortestPathToVisArea(m_lstPortals
[p
], pTargetArea
, arrVisitedAreas
, nRecursion
, sv
))
1838 CVisArea
* CVisAreaManager::CreateTypeVisArea()
1840 CVisArea
* pNewVisArea
= new CVisArea();
1841 SGenericColdData
* pColdData
= &m_visAreaColdData
.AddNew();
1843 m_visAreas
.Add(pNewVisArea
);
1844 pColdData
->ResetGenericData();
1845 pNewVisArea
->SetColdDataPtr(pColdData
);
1850 CVisArea
* CVisAreaManager::CreateTypePortal()
1852 CVisArea
* pNewPortal
= new CVisArea();
1853 SPortalColdData
* pColdData
= &m_portalColdData
.AddNew();
1855 m_portals
.Add(pNewPortal
);
1856 pColdData
->ResetPortalData();
1857 pNewPortal
->SetColdDataPtr(pColdData
);
1862 CVisArea
* CVisAreaManager::CreateTypeOcclArea()
1864 CVisArea
* pNewOcclArea
= new CVisArea();
1865 SGenericColdData
* pColdData
= &m_occlAreaColdData
.AddNew();
1867 m_occlAreas
.Add(pNewOcclArea
);
1868 pColdData
->ResetGenericData();
1869 pNewOcclArea
->SetColdDataPtr(pColdData
);
1871 return pNewOcclArea
;
1874 void CVisAreaManager::InitAABBTree()
1876 IF (!m_pAABBTree
, 0)
1882 CVisArea
* CVisAreaManager::FindVisAreaByGuid(VisAreaGUID guid
, PodArray
<CVisArea
*>& lstVisAreas
)
1886 for (int i
= 0; i
< lstVisAreas
.Count(); i
++)
1888 if (lstVisAreas
[i
] && guid
== lstVisAreas
[i
]->m_nVisGUID
)
1889 return lstVisAreas
[i
];
1896 void CVisAreaManager::OffsetPosition(const Vec3
& delta
)
1898 for (int i
= 0; i
< m_lstVisAreas
.Count(); i
++)
1899 m_lstVisAreas
[i
]->OffsetPosition(delta
);
1901 for (int i
= 0; i
< m_lstPortals
.Count(); i
++)
1902 m_lstPortals
[i
]->OffsetPosition(delta
);
1904 for (int i
= 0; i
< m_lstOcclAreas
.Count(); i
++)
1905 m_lstOcclAreas
[i
]->OffsetPosition(delta
);
1908 m_pAABBTree
->OffsetPosition(delta
);