/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // Description : visibility areas header #ifndef CRYINCLUDE_CRY3DENGINE_VISAREAS_H #define CRYINCLUDE_CRY3DENGINE_VISAREAS_H #pragma once #include "BasicArea.h" #include "CullBuffer.h" // Unique identifier for each VisArea instance typedef unsigned int VisAreaId; typedef uint64 VisAreaGUID; #define ReservedVisAreaBytes 384 struct ITerrainNode; enum EVisAreaColdDataType { eCDT_Generic = 0, eCDT_Portal }; struct SGenericColdData { SGenericColdData() { m_dataType = eCDT_Generic; } ILINE void ResetGenericData() { m_dataType = eCDT_Generic; } EVisAreaColdDataType m_dataType; char m_sName[64]; }; struct SPortalColdData : public SGenericColdData { SPortalColdData() { m_dataType = eCDT_Portal; m_pRNTmpData = NULL; } ILINE void ResetPortalData() { m_dataType = eCDT_Portal; } struct CRNTmpData* m_pRNTmpData; }; struct CVisArea : public IVisArea , public CBasicArea { static void StaticReset(); // editor interface virtual void Update(const Vec3* pPoints, int nCount, const char* szName, const SVisAreaInfo& info); CVisArea(); CVisArea(VisAreaGUID visGUID); virtual ~CVisArea(); bool operator ==(const CVisArea& v1) const { return &v1 == this; } void Init(); ILINE SGenericColdData* GetColdData() { return m_pVisAreaColdData; } ILINE void SetColdDataPtr(SGenericColdData* pColdData) { m_pVisAreaColdData = pColdData; } bool IsSphereInsideVisArea(const Vec3& vPos, const f32 fRadius); bool IsPointInsideVisArea(const Vec3& vPos) const; bool IsBoxOverlapVisArea(const AABB& objBox); bool ClipToVisArea(bool bInside, Sphere& sphere, Vec3 const& vNormal); bool FindVisArea(IVisArea* pAnotherArea, int nMaxRecursion, bool bSkipDisabledPortals); bool FindVisAreaReqursive(IVisArea* pAnotherArea, int nMaxReqursion, bool bSkipDisabledPortals, StaticDynArray& arrVisitedParents); bool GetDistanceThruVisAreas(AABB vCurBoxIn, IVisArea* pTargetArea, const AABB& targetBox, int nMaxReqursion, float& fResDist); bool GetDistanceThruVisAreasReq(AABB vCurBoxIn, float fCurDistIn, IVisArea* pTargetArea, const AABB& targetBox, int nMaxReqursion, float& fResDist, CVisArea* pPrevArea, int nCallID); void FindSurroundingVisArea(int nMaxReqursion, bool bSkipDisabledPortals, PodArray* pVisitedAreas = NULL, int nMaxVisitedAreas = 0, int nDeepness = 0); void FindSurroundingVisAreaReqursive(int nMaxReqursion, bool bSkipDisabledPortals, PodArray* pVisitedAreas, int nMaxVisitedAreas, int nDeepness, PodArray* pUnavailableAreas); int GetVisFrameId(); Vec3 GetConnectionNormal(CVisArea* pPortal); void PreRender(int nReqursionLevel, CCamera CurCamera, CVisArea* pParent, CVisArea* pCurPortal, bool* pbOutdoorVisible, PodArray* plstOutPortCameras, bool* pbSkyVisible, bool* pbOceanVisible, PodArray& lstVisibleAreas, const SRenderingPassInfo& passInfo); void UpdatePortalCameraPlanes(CCamera& cam, Vec3* pVerts, bool bMergeFrustums, const SRenderingPassInfo& passInfo); int GetVisAreaConnections(IVisArea** pAreas, int nMaxConnNum, bool bSkipDisabledPortals = false); int GetRealConnections(IVisArea** pAreas, int nMaxConnNum, bool bSkipDisabledPortals = false); bool IsPortalValid(); bool IsPortalIntersectAreaInValidWay(CVisArea* pPortal); bool IsPortal() const; bool IsShapeClockwise(); bool IsAffectedByOutLights() const { return m_bAffectedByOutLights; } bool IsActive() { return m_bActive || (GetCVars()->e_Portals == 4); } void UpdateGeometryBBox(); void UpdateClipVolume(); void UpdatePortalBlendInfo(); void DrawAreaBoundsIntoCBuffer(class CCullBuffer* pCBuffer); void ClipPortalVerticesByCameraFrustum(PodArray* pPolygon, const CCamera& cam); void GetMemoryUsage(ICrySizer* pSizer); bool IsConnectedToOutdoor() const; bool IsIgnoringGI() const { return m_bIgnoreGI; } bool IsIgnoringOutdoorAO() const { return m_bIgnoreOutdoorAO; } const char* GetName() { return m_pVisAreaColdData->m_sName; } # if ENGINE_ENABLE_COMPILATION int SaveHeader(byte*& pData, int& nDataSize); int SaveObjectsTree(byte*& pData, int& nDataSize, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, std::vector* pStatInstGroupTable, EEndian eEndian, SHotUpdateInfo* pExportInfo, byte* pHead); int GetData(byte*& pData, int& nDataSize, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, std::vector* pStatInstGroupTable, EEndian eEndian, SHotUpdateInfo* pExportInfo); int GetSegmentData(byte*& pData, int& nDataSize, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, std::vector* pStatInstGroupTable, EEndian eEndian, SHotUpdateInfo* pExportInfo); # endif template int LoadHeader_T(T& f, int& nDataSizeLeft, EEndian eEndian, int& objBlockSize); template int LoadObjectsTree_T(T& f, int& nDataSizeLeft, int nSID, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, EEndian eEndian, SHotUpdateInfo* pExportInfo, const int objBlockSize); template int Load_T(T& f, int& nDataSize, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, EEndian eEndian, SHotUpdateInfo* pExportInfo); int Load(byte*& f, int& nDataSizeLeft, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, EEndian eEndian, SHotUpdateInfo* pExportInfo); int Load(AZ::IO::HandleType& fileHandle, int& nDataSizeLeft, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, EEndian eEndian, SHotUpdateInfo* pExportInfo); const AABB* GetAABBox() const; const AABB* GetStaticObjectAABBox() const; void AddConnectedAreas(PodArray& lstAreas, int nMaxRecursion); void GetShapePoints(const Vec3*& pPoints, size_t& nPoints); float GetHeight(); float CalcSignedArea(); bool CalcPortalBlendPlanes(Vec3 camPos); virtual void GetClipVolumeMesh(_smart_ptr& renderMesh, Matrix34& worldTM) const; virtual AABB GetClipVolumeBBox() const { return *GetStaticObjectAABBox(); } virtual uint8 GetStencilRef() const { return m_nStencilRef; } virtual uint GetClipVolumeFlags() const; virtual bool IsPointInsideClipVolume(const Vec3& vPos) const { return IsPointInsideVisArea(vPos); } void OffsetPosition(const Vec3& delta); static VisAreaGUID GetGUIDFromFile(byte* f, EEndian eEndian); VisAreaGUID GetGUID() const { return m_nVisGUID; } static PodArray m_lUnavailableAreas; static PodArray s_tmpLstPortVertsClipped; static PodArray s_tmpLstPortVertsSS; static PodArray s_tmpPolygonA; static PodArray s_tmpLstLights; static PodArray s_tmpLstTerrainNodeResult; static CPolygonClipContext s_tmpClipContext; static PodArray s_tmpCameras; static int s_nGetDistanceThruVisAreasCallCounter; VisAreaGUID m_nVisGUID; PodArray m_lstConnections; Vec3 m_vConnNormals[2]; int m_nRndFrameId; float m_fGetDistanceThruVisAreasMinDistance; int m_nGetDistanceThruVisAreasLastCallID; float m_fPortalBlending; PodArray m_lstShapePoints; float m_fHeight; _smart_ptr m_pClipVolumeMesh; Vec3 m_vAmbientColor; float m_fDistance; float m_fViewDistRatio; CCamera* m_arrOcclCamera[MAX_RECURSION_LEVELS]; int m_lstCurCamerasLen; int m_lstCurCamerasCap; int m_lstCurCamerasIdx; uint8 m_nStencilRef; SGenericColdData* m_pVisAreaColdData; bool m_bAffectedByOutLights; bool m_bSkyOnly; bool m_bOceanVisible; bool m_bDoubleSide; bool m_bUseDeepness; bool m_bUseInIndoors; bool m_bThisIsPortal; bool m_bIgnoreSky; bool m_bActive; bool m_bIgnoreGI; bool m_bIgnoreOutdoorAO; }; struct CSWVisArea : public CVisArea , public _i_reference_target_t { CSWVisArea() : CVisArea() , m_nSlotID(-1) {} ~CSWVisArea() {} void Release() { --m_nRefCounter; if (m_nRefCounter < 0) { assert(0); CryFatalError("Deleting Reference Counted Object Twice"); } } int Load(byte*& f, int& nDataSizeLeft, int nSID, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, EEndian eEndian, SHotUpdateInfo* pExportInfo, const Vec2& indexOffset); int m_nSlotID; }; struct SAABBTreeNode { SAABBTreeNode(PodArray& lstAreas, AABB box, int nMaxRecursion = 0); ~SAABBTreeNode(); CVisArea* FindVisarea(const Vec3& vPos); SAABBTreeNode* GetTopNode(const AABB& box, void** pNodeCache); bool IntersectsVisAreas(const AABB& box); int ClipOutsideVisAreas(Sphere& sphere, Vec3 const& vNormal); void OffsetPosition(const Vec3& delta); AABB nodeBox; PodArray nodeAreas; SAABBTreeNode* arrChilds[2]; }; struct TTopologicalSorter; struct CVisAreaSegmentData { // active vis areas in current segment std::vector m_visAreaIndices; }; struct CVisAreaManager : public IVisAreaManager , Cry3DEngineBase { CVisArea* m_pCurArea, * m_pCurPortal; PodArray m_lstActiveEntransePortals; PodArray m_lstVisAreas; PodArray m_lstPortals; PodArray m_lstOcclAreas; PodArray m_segVisAreas; PodArray m_segPortals; PodArray m_segOcclAreas; PodArray m_lstActiveOcclVolumes; PodArray m_lstIndoorActiveOcclVolumes; PodArray m_lstVisibleAreas; PodArray m_tmpLstUnavailableAreas; PodArray m_tmpLstLightBoxAreas; bool m_bOutdoorVisible; bool m_bSkyVisible; bool m_bOceanVisible; bool m_bSunIsNeeded; PodArray m_lstOutdoorPortalCameras; PodArray m_lstCallbacks; SAABBTreeNode* m_pAABBTree; CVisAreaManager(); ~CVisAreaManager(); void UpdateAABBTree(); void SetCurAreas(const SRenderingPassInfo& passInfo); PodArray* GetActiveEntransePortals() { return &m_lstActiveEntransePortals; } void PortalsDrawDebug(); bool IsEntityVisible(IRenderNode* pEnt); bool IsOutdoorAreasVisible() override; bool IsSkyVisible(); bool IsOceanVisible(); CVisArea* CreateVisArea(VisAreaGUID visGUID); bool DeleteVisArea(CVisArea* pVisArea); bool SetEntityArea(IRenderNode* pEnt, const AABB& objBox, const float fObjRadiusSqr); void CheckVis(const SRenderingPassInfo& passInfo); void DrawVisibleSectors(const SRenderingPassInfo& passInfo, SRendItemSorter& rendItemSorter); void ActivatePortal(const Vec3& vPos, bool bActivate, const char* szEntityName); void UpdateVisArea(CVisArea* pArea, const Vec3* pPoints, int nCount, const char* szName, const SVisAreaInfo& info); virtual void UpdateConnections(); void MoveObjectsIntoList(PodArray* plstVisAreasEntities, const AABB& boxArea, bool bRemoveObjects = false); IVisArea* GetVisAreaFromPos(const Vec3& vPos); bool IntersectsVisAreas(const AABB& box, void** pNodeCache = 0); bool ClipOutsideVisAreas(Sphere& sphere, Vec3 const& vNormal, void* pNodeCache = 0); bool IsEntityVisAreaVisible(IRenderNode* pEnt, int nMaxReqursion, const CDLight* pLight, const SRenderingPassInfo& passInfo); void MakeActiveEntransePortalsList(const CCamera* pCamera, PodArray& lstActiveEntransePortals, CVisArea* pThisPortal, const SRenderingPassInfo& passInfo); void DrawOcclusionAreasIntoCBuffer(CCullBuffer* pCBuffer, const SRenderingPassInfo& passInfo); bool IsValidVisAreaPointer(CVisArea* pVisArea); void GetStreamingStatus(int& nLoadedSectors, int& nTotalSectors); void GetMemoryUsage(ICrySizer* pSizer) const; bool IsOccludedByOcclVolumes(const AABB& objBox, const SRenderingPassInfo& passInfo, bool bCheckOnlyIndoorVolumes = false); void GetObjectsAround(Vec3 vExploPos, float fExploRadius, PodArray* pEntList, bool bSkip_ERF_NO_DECALNODE_DECALS = false, bool bSkipDynamicObjects = false); void IntersectWithBox(const AABB& aabbBox, PodArray* plstResult, bool bOnlyIfVisible); template bool Load_T(T& f, int& nDataSize, struct SVisAreaManChunkHeader* pVisAreaManagerChunkHeader, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, bool bHotUpdate, SHotUpdateInfo* pExportInfo); virtual bool Load(AZ::IO::HandleType& fileHandle, int& nDataSize, struct SVisAreaManChunkHeader* pVisAreaManagerChunkHeader, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable); virtual bool SetCompiledData(byte* pData, int nDataSize, std::vector** ppStatObjTable, std::vector<_smart_ptr>** ppMatTable, bool bHotUpdate, SHotUpdateInfo* pExportInfo); virtual bool GetCompiledData(byte* pData, int nDataSize, std::vector** ppStatObjTable, std::vector<_smart_ptr>** ppMatTable, std::vector** ppStatInstGroupTable, EEndian eEndian, SHotUpdateInfo* pExportInfo); virtual int GetCompiledDataSize(SHotUpdateInfo* pExportInfo); void UnregisterEngineObjectsInArea(const SHotUpdateInfo* pExportInfo, PodArray& arrUnregisteredObjects, bool bOnlyEngineObjects); void PrecacheLevel(bool bPrecacheAllVisAreas, Vec3* pPrecachePoints, int nPrecachePointsNum); bool IsEntityVisAreaVisibleReqursive(CVisArea* pVisArea, int nMaxReqursion, PodArray* pUnavailableAreas, const CDLight* pLight, const SRenderingPassInfo& passInfo); bool IsAABBVisibleFromPoint(AABB& aabb, Vec3 vPos); bool FindShortestPathToVisArea(CVisArea* pThisArea, CVisArea* pTargetArea, PodArray& arrVisitedAreas, int& nRecursion, const struct Shadowvolume& sv); int GetNumberOfVisArea() const; // the function give back the accumlated number of visareas and portals IVisArea* GetVisAreaById(int nID) const; // give back the visarea interface based on the id (0..GetNumberOfVisArea()) it can be a visarea or a portal virtual void AddListener(IVisAreaCallback* pListener); virtual void RemoveListener(IVisAreaCallback* pListener); virtual void CloneRegion(const AABB& region, const Vec3& offset, float zRotation); virtual void ClearRegion(const AABB& region); //! Clears terrain nodes from vis area octree. Call when Terrain is destroyed. void ClearTerrainNodes() override; void MarkAllSectorsAsUncompiled(const IRenderNode* pRenderNode = NULL); void InitAABBTree(); // ------------------------------------- void GetObjectsByType(PodArray& lstObjects, EERType objType, const AABB* pBBox, ObjectTreeQueryFilterCallback filterCallback = nullptr) override; void GetObjectsByFlags(uint dwFlags, PodArray& lstObjects); void GetNearestCubeProbe(float& fMinDistance, int& nMaxPriority, CLightEntity*& pNearestLight, const AABB* pBBox, bool bGetFirstProbe = true); void GetObjects(PodArray& lstObjects, const AABB* pBBox); CVisArea* GetCurVisArea() { return m_pCurArea ? m_pCurArea : m_pCurPortal; } void GenerateStatObjAndMatTables(std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, std::vector* pStatInstGroupTable, SHotUpdateInfo* pExportInfo); void OnVisAreaDeleted(IVisArea* pArea); void ActivateObjectsLayer(uint16 nLayerId, bool bActivate, bool bPhys, IGeneralMemoryHeap* pHeap); virtual void PrepareSegmentData(const AABB& box); virtual void ReleaseInactiveSegments(); virtual bool CreateSegment(int nSID); virtual bool DeleteSegment(int nSID, bool bDeleteNow); virtual bool StreamCompiledData(uint8* pData, int nDataSize, int nSID, std::vector* pStatObjTable, std::vector<_smart_ptr>* pMatTable, std::vector* pStatInstGroupTable, const Vec2& vIndexOffset); virtual void OffsetPosition(const Vec3& delta); private: void DeleteAllVisAreas(); CVisArea* CreateTypeVisArea(); CVisArea* CreateTypePortal(); CVisArea* CreateTypeOcclArea(); void DeleteVisAreaSegment(int nSID, PodArray& visAreaSegmentData, PodArray& lstVisAreas, PodArray& visAreas, PodArray& deletedVisAreas); CVisArea* FindVisAreaByGuid(VisAreaGUID guid, PodArray& lstVisAreas); CSWVisArea* FindFreeVisAreaFromPool(PodArray& visAreas); template CSWVisArea* CreateVisAreaFromPool(PodArray& lstVisAreas, PodArray& visAreas, PodArray& visAreaColdData, bool bIsPortal); template void ResetVisAreaList(PodArray& lstVisAreas, PodArray& visAreas, PodArray& visAreaColdData); template CSWVisArea* CreateTypeArea(PodArray& visAreas, PodArray& visAreaColdData, bool bIsPortal); PodArray m_portals; PodArray m_visAreas; PodArray m_occlAreas; PodArray m_visAreaColdData; PodArray m_portalColdData; PodArray m_occlAreaColdData; PodArray m_visAreaSegmentData; PodArray m_portalSegmentData; PodArray m_occlAreaSegmentData; PodArray m_arrDeletedVisArea; PodArray m_arrDeletedPortal; PodArray m_arrDeletedOcclArea; struct SActiveVerts { Vec3 arrvActiveVerts[4]; }; #if defined(OCCLUSIONCULLER_W) std::vector m_allActiveVerts; #endif }; #endif // CRYINCLUDE_CRY3DENGINE_VISAREAS_H