/* * 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 : check vis #include "StdAfx.h" #include "ObjMan.h" #include "VisAreas.h" bool CVisAreaManager::GetCompiledData(byte* pData, int nDataSize, std::vector<struct IStatObj*>** ppStatObjTable, std::vector<_smart_ptr<IMaterial>>** ppMatTable, std::vector<struct IStatInstGroup*>** ppStatInstGroupTable, EEndian eEndian, SHotUpdateInfo* pExportInfo) { # if !ENGINE_ENABLE_COMPILATION CryFatalError("serialization code removed, please enable 3DENGINE_ENABLE_COMPILATION in Cry3DEngine/StdAfx.h"); return false; # else float fStartTime = GetCurAsyncTimeSec(); bool bHMap(!pExportInfo || pExportInfo->nHeigtmap); bool bObjs(!pExportInfo || pExportInfo->nObjTypeMask); // PrintMessage("Exporting indoor data (%s, %.2f MB) ...", // (bHMap && bObjs) ? "Objects and heightmap" : (bHMap ? "Heightmap" : (bObjs ? "Objects" : "Nothing")), ((float)nDataSize)/1024.f/1024.f); // write header SVisAreaManChunkHeader* pVisAreaManagerChunkHeader = (SVisAreaManChunkHeader*)pData; pVisAreaManagerChunkHeader->nVersion = VISAREAMANAGER_CHUNK_VERSION; pVisAreaManagerChunkHeader->nDummy = 0; pVisAreaManagerChunkHeader->nFlags = (eEndian == eBigEndian) ? SERIALIZATION_FLAG_BIG_ENDIAN : 0; pVisAreaManagerChunkHeader->nFlags2 = 0; pVisAreaManagerChunkHeader->nChunkSize = nDataSize; SwapEndian(*pVisAreaManagerChunkHeader, eEndian); UPDATE_PTR_AND_SIZE(pData, nDataSize, sizeof(SVisAreaManChunkHeader)); pVisAreaManagerChunkHeader->nVisAreasNum = m_lstVisAreas.Count(); pVisAreaManagerChunkHeader->nPortalsNum = m_lstPortals.Count(); pVisAreaManagerChunkHeader->nOcclAreasNum = m_lstOcclAreas.Count(); for (int i = 0; i < m_lstVisAreas.Count(); i++) { m_lstVisAreas[i]->GetData(pData, nDataSize, *ppStatObjTable, *ppMatTable, *ppStatInstGroupTable, eEndian, pExportInfo); } for (int i = 0; i < m_lstPortals.Count(); i++) { m_lstPortals[i]->GetData(pData, nDataSize, *ppStatObjTable, *ppMatTable, *ppStatInstGroupTable, eEndian, pExportInfo); } for (int i = 0; i < m_lstOcclAreas.Count(); i++) { m_lstOcclAreas[i]->GetData(pData, nDataSize, *ppStatObjTable, *ppMatTable, *ppStatInstGroupTable, eEndian, pExportInfo); } SAFE_DELETE(*ppStatObjTable); SAFE_DELETE(*ppMatTable); SAFE_DELETE(*ppStatInstGroupTable); if (!pExportInfo) { PrintMessagePlus(" done in %.2f sec", GetCurAsyncTimeSec() - fStartTime); } assert(nDataSize == 0); return nDataSize == 0; # endif } int CVisAreaManager::GetCompiledDataSize(SHotUpdateInfo* pExportInfo) { # if !ENGINE_ENABLE_COMPILATION CryFatalError("serialization code removed, please enable 3DENGINE_ENABLE_COMPILATION in Cry3DEngine/StdAfx.h"); return 0; # else int nDataSize = 0; byte* pData = NULL; // get header size nDataSize += sizeof(SVisAreaManChunkHeader); for (int i = 0; i < m_lstVisAreas.Count(); i++) { m_lstVisAreas[i]->GetData(pData, nDataSize, NULL, NULL, NULL, eLittleEndian, pExportInfo); } for (int i = 0; i < m_lstPortals.Count(); i++) { m_lstPortals[i]->GetData(pData, nDataSize, NULL, NULL, NULL, eLittleEndian, pExportInfo); } for (int i = 0; i < m_lstOcclAreas.Count(); i++) { m_lstOcclAreas[i]->GetData(pData, nDataSize, NULL, NULL, NULL, eLittleEndian, pExportInfo); } return nDataSize; # endif } bool CVisAreaManager::Load(AZ::IO::HandleType& fileHandle, int& nDataSize, struct SVisAreaManChunkHeader* pVisAreaManagerChunkHeader, std::vector<struct IStatObj*>* pStatObjTable, std::vector<_smart_ptr<IMaterial>>* pMatTable) { bool bRes; // in case of small data amount (console game) load entire file into memory in single operation if (nDataSize < 4 * 1024 * 1024) { _smart_ptr<IMemoryBlock> pMemBlock = gEnv->pCryPak->PoolAllocMemoryBlock(nDataSize + 8, "LoadIndoors"); byte* pPtr = (byte*)pMemBlock->GetData(); while (UINT_PTR(pPtr) & 3) { pPtr++; } if (GetPak()->FReadRaw(pPtr, 1, nDataSize - sizeof(SVisAreaManChunkHeader), fileHandle) != nDataSize - sizeof(SVisAreaManChunkHeader)) { return false; } bRes = Load_T(pPtr, nDataSize, pVisAreaManagerChunkHeader, pStatObjTable, pMatTable, false, NULL); } else { bRes = Load_T(fileHandle, nDataSize, pVisAreaManagerChunkHeader, pStatObjTable, pMatTable, false, NULL); } return bRes; } bool CVisAreaManager::SetCompiledData(byte* pData, int nDataSize, std::vector<struct IStatObj*>** ppStatObjTable, std::vector<_smart_ptr<IMaterial>>** ppMatTable, bool bHotUpdate, SHotUpdateInfo* pExportInfo) { SVisAreaManChunkHeader* pChunkHeader = (SVisAreaManChunkHeader*)pData; pData += sizeof(SVisAreaManChunkHeader); SwapEndian(*pChunkHeader, eLittleEndian); bool bRes = Load_T(pData, nDataSize, pChunkHeader, *ppStatObjTable, *ppMatTable, bHotUpdate, pExportInfo); SAFE_DELETE(*ppStatObjTable); SAFE_DELETE(*ppMatTable); return bRes; } void CVisAreaManager::UnregisterEngineObjectsInArea(const SHotUpdateInfo* pExportInfo, PodArray<IRenderNode*>& arrUnregisteredObjects, bool bOnlyEngineObjects) { for (int i = 0; i < m_lstVisAreas.Count(); i++) { if (m_lstVisAreas[i]->m_pObjectsTree) { m_lstVisAreas[i]->m_pObjectsTree->UnregisterEngineObjectsInArea(pExportInfo, arrUnregisteredObjects, bOnlyEngineObjects); } } for (int i = 0; i < m_lstPortals.Count(); i++) { if (m_lstPortals[i]->m_pObjectsTree) { m_lstPortals[i]->m_pObjectsTree->UnregisterEngineObjectsInArea(pExportInfo, arrUnregisteredObjects, bOnlyEngineObjects); } } for (int i = 0; i < m_lstOcclAreas.Count(); i++) { if (m_lstOcclAreas[i]->m_pObjectsTree) { m_lstOcclAreas[i]->m_pObjectsTree->UnregisterEngineObjectsInArea(pExportInfo, arrUnregisteredObjects, bOnlyEngineObjects); } } } void CVisAreaManager::OnVisAreaDeleted(IVisArea* pArea) { for (int i = 0, num = m_lstCallbacks.size(); i < num; i++) { m_lstCallbacks[i]->OnVisAreaDeleted(pArea); } m_lstActiveOcclVolumes.Delete((CVisArea*)pArea); m_lstIndoorActiveOcclVolumes.Delete((CVisArea*)pArea); m_lstActiveEntransePortals.Delete((CVisArea*)pArea); } template <class T> bool CVisAreaManager::Load_T(T& f, int& nDataSize, SVisAreaManChunkHeader* pVisAreaManagerChunkHeader, std::vector<IStatObj*>* pStatObjTable, std::vector<_smart_ptr<IMaterial>>* pMatTable, bool bHotUpdate, SHotUpdateInfo* pExportInfo) { if (pVisAreaManagerChunkHeader->nVersion != VISAREAMANAGER_CHUNK_VERSION) { Error("CVisAreaManager::SetCompiledData: version of file is %d, expected version is %d", pVisAreaManagerChunkHeader->nVersion, (int)VISAREAMANAGER_CHUNK_VERSION); return 0; } if (pVisAreaManagerChunkHeader->nChunkSize != nDataSize) { Error("CVisAreaManager::SetCompiledData: data size mismatch (%d != %d)", pVisAreaManagerChunkHeader->nChunkSize, nDataSize); return 0; } bool bHMap(!pExportInfo || pExportInfo->nHeigtmap); bool bObjs(!pExportInfo || pExportInfo->nObjTypeMask); AABB* pBox = (pExportInfo && !pExportInfo->areaBox.IsReset()) ? &pExportInfo->areaBox : NULL; EEndian eEndian = (pVisAreaManagerChunkHeader->nFlags & SERIALIZATION_FLAG_BIG_ENDIAN) ? eBigEndian : eLittleEndian; PodArray<IRenderNode*> arrUnregisteredObjects; UnregisterEngineObjectsInArea(pExportInfo, arrUnregisteredObjects, true); PodArray<IRenderNode*> arrUnregisteredEntities; UnregisterEngineObjectsInArea(NULL, arrUnregisteredEntities, false); DeleteAllVisAreas(); SAFE_DELETE(m_pAABBTree); m_pCurArea = m_pCurPortal = 0; { // construct areas m_lstVisAreas.PreAllocate(pVisAreaManagerChunkHeader->nVisAreasNum, pVisAreaManagerChunkHeader->nVisAreasNum); m_lstPortals.PreAllocate(pVisAreaManagerChunkHeader->nPortalsNum, pVisAreaManagerChunkHeader->nPortalsNum); m_lstOcclAreas.PreAllocate(pVisAreaManagerChunkHeader->nOcclAreasNum, pVisAreaManagerChunkHeader->nOcclAreasNum); nDataSize -= sizeof(SVisAreaManChunkHeader); // if(bHotUpdate) // PrintMessage("Importing indoor data (%s, %.2f MB) ...", // (bHMap && bObjs) ? "Objects and heightmap" : (bHMap ? "Heightmap" : (bObjs ? "Objects" : "Nothing")), ((float)nDataSize)/1024.f/1024.f); m_visAreas.PreAllocate(pVisAreaManagerChunkHeader->nVisAreasNum); m_visAreaColdData.PreAllocate(pVisAreaManagerChunkHeader->nVisAreasNum); m_portals.PreAllocate(pVisAreaManagerChunkHeader->nPortalsNum); m_portalColdData.PreAllocate(pVisAreaManagerChunkHeader->nPortalsNum); m_occlAreas.PreAllocate(pVisAreaManagerChunkHeader->nOcclAreasNum); m_occlAreaColdData.PreAllocate(pVisAreaManagerChunkHeader->nOcclAreasNum); for (int i = 0; i < m_lstVisAreas.Count(); i++) { m_lstVisAreas[i] = CreateTypeVisArea(); } for (int i = 0; i < m_lstPortals.Count(); i++) { m_lstPortals[i] = CreateTypePortal(); } for (int i = 0; i < m_lstOcclAreas.Count(); i++) { m_lstOcclAreas[i] = CreateTypeOcclArea(); } } { // load areas content for (int i = 0; i < m_lstVisAreas.Count(); i++) { m_lstVisAreas[i]->Load(f, nDataSize, pStatObjTable, pMatTable, eEndian, pExportInfo); } for (int i = 0; i < m_lstPortals.Count(); i++) { m_lstPortals[i]->Load(f, nDataSize, pStatObjTable, pMatTable, eEndian, pExportInfo); } for (int i = 0; i < m_lstOcclAreas.Count(); i++) { m_lstOcclAreas[i]->Load(f, nDataSize, pStatObjTable, pMatTable, eEndian, pExportInfo); } } for (int i = 0; i < arrUnregisteredObjects.Count(); i++) { arrUnregisteredObjects[i]->ReleaseNode(); } arrUnregisteredObjects.Reset(); for (int i = 0; i < arrUnregisteredEntities.Count(); i++) { Get3DEngine()->RegisterEntity(arrUnregisteredEntities[i]); } arrUnregisteredEntities.Reset(); SAFE_DELETE(m_pAABBTree); m_pCurArea = m_pCurPortal = 0; UpdateConnections(); return nDataSize == 0; } ////////////////////////////////////////////////////////////////////// // Segmented World inline bool IsContainBox2D(const AABB& base, const AABB& test) { if (base.min.x < test.max.x && base.max.x > test.min.x && base.min.y < test.max.y && base.max.y > test.min.y) { return true; } return false; } void CVisAreaManager::PrepareSegmentData(const AABB& box) { m_segVisAreas.Clear(); for (int v = 0; v < m_lstVisAreas.Count(); v++) { if (IsContainBox2D(m_lstVisAreas[v]->m_boxArea, box)) { m_segVisAreas.Add(m_lstVisAreas[v]); } } m_segPortals.Clear(); for (int p = 0; p < m_lstPortals.Count(); p++) { if (IsContainBox2D(m_lstPortals[p]->m_boxArea, box)) { m_segPortals.Add(m_lstPortals[p]); } } m_segOcclAreas.Clear(); for (int o = 0; o < m_lstOcclAreas.Count(); o++) { if (IsContainBox2D(m_lstOcclAreas[o]->m_boxArea, box)) { m_segOcclAreas.Add(m_lstOcclAreas[o]); } } } bool CVisAreaManager::StreamCompiledData(uint8* pData, int nDataSize, int nSID, std::vector<struct IStatObj*>* pStatObjTable, std::vector<_smart_ptr<IMaterial>>* pMatTable, std::vector<struct IStatInstGroup*>* pStatInstGroupTable, const Vec2& vIndexOffset) { SVisAreaManChunkHeader* pVisAreaManagerChunkHeader = (SVisAreaManChunkHeader*)pData; pData += sizeof(SVisAreaManChunkHeader); nDataSize -= sizeof(SVisAreaManChunkHeader); assert(pVisAreaManagerChunkHeader->nVersion == VISAREAMANAGER_CHUNK_VERSION); EEndian eEndian = (pVisAreaManagerChunkHeader->nFlags & SERIALIZATION_FLAG_BIG_ENDIAN) ? eBigEndian : eLittleEndian; SAFE_DELETE(m_pAABBTree); m_pCurArea = m_pCurPortal = 0; for (int i = 0; i < pVisAreaManagerChunkHeader->nVisAreasNum; i++) { VisAreaGUID guid = CVisArea::GetGUIDFromFile(pData, eEndian); CSWVisArea* pVisArea = (CSWVisArea*)FindVisAreaByGuid(guid, m_lstVisAreas); if (!pVisArea) { pVisArea = CreateVisAreaFromPool(m_lstVisAreas, m_visAreas, m_visAreaColdData, false); m_lstVisAreas.Add(pVisArea); } pVisArea->AddRef(); m_visAreaSegmentData[nSID].m_visAreaIndices.push_back(pVisArea->m_nSlotID); pVisArea->Load(pData, nDataSize, nSID, pStatObjTable, pMatTable, eEndian, 0, vIndexOffset); } for (int i = 0; i < pVisAreaManagerChunkHeader->nPortalsNum; i++) { VisAreaGUID guid = CVisArea::GetGUIDFromFile(pData, eEndian); CSWVisArea* pVisArea = (CSWVisArea*)FindVisAreaByGuid(guid, m_lstPortals); if (!pVisArea) { pVisArea = CreateVisAreaFromPool(m_lstPortals, m_portals, m_portalColdData, true); m_lstPortals.Add(pVisArea); } pVisArea->AddRef(); m_portalSegmentData[nSID].m_visAreaIndices.push_back(pVisArea->m_nSlotID); pVisArea->Load(pData, nDataSize, nSID, pStatObjTable, pMatTable, eEndian, 0, vIndexOffset); } for (int i = 0; i < pVisAreaManagerChunkHeader->nOcclAreasNum; i++) { VisAreaGUID guid = CVisArea::GetGUIDFromFile(pData, eEndian); CSWVisArea* pVisArea = (CSWVisArea*)FindVisAreaByGuid(guid, m_lstOcclAreas); if (!pVisArea) { pVisArea = CreateVisAreaFromPool(m_lstOcclAreas, m_occlAreas, m_occlAreaColdData, false); m_lstOcclAreas.Add(pVisArea); } pVisArea->AddRef(); m_occlAreaSegmentData[nSID].m_visAreaIndices.push_back(pVisArea->m_nSlotID); pVisArea->Load(pData, nDataSize, nSID, pStatObjTable, pMatTable, eEndian, 0, vIndexOffset); } SAFE_DELETE(m_pAABBTree); m_pCurArea = m_pCurPortal = 0; SAFE_DELETE(pStatObjTable); SAFE_DELETE(pMatTable); SAFE_DELETE(pStatInstGroupTable); return !(nDataSize == 0); } CSWVisArea* CVisAreaManager::FindFreeVisAreaFromPool(PodArray<CVisArea*, ReservedVisAreaBytes>& visAreas) { for (int i = 0; i < visAreas.Count(); i++) { CSWVisArea* pVisArea = (CSWVisArea*)visAreas[i]; if (!pVisArea->NumRefs()) { pVisArea->m_nSlotID = i; return pVisArea; } } return NULL; } template<class T> CSWVisArea* CVisAreaManager::CreateVisAreaFromPool(PodArray<CVisArea*>& lstVisAreas, PodArray<CVisArea*, ReservedVisAreaBytes>& visAreas, PodArray<T>& visAreaColdData, bool bIsPortal) { CSWVisArea* pVisArea = FindFreeVisAreaFromPool(visAreas); if (!pVisArea) { int nVisArea = visAreas.Count(); visAreas.PreAllocate(nVisArea * 2); visAreaColdData.PreAllocate(nVisArea * 2); ResetVisAreaList(lstVisAreas, visAreas, visAreaColdData); pVisArea = CreateTypeArea(visAreas, visAreaColdData, bIsPortal); // assign the slot id once the pool is enlarged pVisArea->m_nSlotID = nVisArea; } return pVisArea; } template<class T> void CVisAreaManager::ResetVisAreaList(PodArray<CVisArea*>& lstVisAreas, PodArray<CVisArea*, ReservedVisAreaBytes>& visAreas, PodArray<T>& visAreaColdData) { for (int i = 0; i < visAreas.Count(); i++) { CVisArea* pVisArea = visAreas[i]; if (pVisArea->m_pObjectsTree) { pVisArea->m_pObjectsTree->SetVisArea(pVisArea); } pVisArea->SetColdDataPtr(&visAreaColdData[i]); lstVisAreas[i] = pVisArea; } } template<class T> CSWVisArea* CVisAreaManager::CreateTypeArea(PodArray<CVisArea*, ReservedVisAreaBytes>& visAreas, PodArray<T>& visAreaColdData, bool bIsPortal) { CSWVisArea* pNewVisArea = new CSWVisArea(); SGenericColdData* pColdData = &visAreaColdData.AddNew(); visAreas.Add(pNewVisArea); pColdData->m_dataType = bIsPortal ? eCDT_Portal : eCDT_Generic; pNewVisArea->SetColdDataPtr(pColdData); return pNewVisArea; }