You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1248 lines
38 KiB
C++
1248 lines
38 KiB
C++
/*
|
|
* 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 : Level loading
|
|
|
|
|
|
#include "Cry3DEngine_precompiled.h"
|
|
|
|
#include "3dEngine.h"
|
|
#include "ObjMan.h"
|
|
#include "VisAreas.h"
|
|
#include "Ocean.h"
|
|
#include "DecalManager.h"
|
|
#include "MatMan.h"
|
|
#include "IndexedMesh.h"
|
|
#include "SkyLightManager.h"
|
|
#include "ObjectsTree.h"
|
|
#include "LightEntity.h"
|
|
#include "TimeOfDay.h"
|
|
#include "LightEntity.h"
|
|
#include "RenderMeshMerger.h"
|
|
#include "FogVolumeRenderNode.h"
|
|
#include "IDeferredCollisionEvent.h"
|
|
#include <IMaterialEffects.h>
|
|
#include "ClipVolumeManager.h"
|
|
#include "Environment/OceanEnvironmentBus.h"
|
|
|
|
#include <I3DEngine.h>
|
|
#include <LoadScreenBus.h>
|
|
#include <StatObjBus.h>
|
|
#include "AzCore/Component/TickBus.h"
|
|
|
|
//------------------------------------------------------------------------------
|
|
#define LEVEL_DATA_FILE "LevelData.xml"
|
|
#define CUSTOM_MATERIALS_FILE "Materials.xml"
|
|
#define PARTICLES_FILE "LevelParticles.xml"
|
|
#define SHADER_LIST_FILE "ShadersList.txt"
|
|
#define LEVEL_CONFIG_FILE "Level.cfg"
|
|
#define LEVEL_EDITOR_CONFIG_FILE "Editor.cfg"
|
|
//------------------------------------------------------------------------------
|
|
const uint32 MAX_ACTIVE_BREEZE_POINTS = 99;
|
|
//------------------------------------------------------------------------------
|
|
|
|
inline Vec3 StringToVector(const char* str)
|
|
{
|
|
Vec3 vTemp(0, 0, 0);
|
|
float x, y, z;
|
|
if (azsscanf(str, "%f,%f,%f", &x, &y, &z) == 3)
|
|
{
|
|
vTemp(x, y, z);
|
|
}
|
|
else
|
|
{
|
|
vTemp(0, 0, 0);
|
|
}
|
|
return vTemp;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void C3DEngine::LoadEmptyLevel()
|
|
{
|
|
CreateOctree(0.0f);
|
|
LoadDefaultAssets();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void C3DEngine::SetLevelPath(const char* szFolderName)
|
|
{
|
|
// make folder path
|
|
assert(strlen(szFolderName) < 1024);
|
|
azstrcpy(m_szLevelFolder, AZ_ARRAY_SIZE(m_szLevelFolder), szFolderName);
|
|
if (strlen(m_szLevelFolder) > 0)
|
|
{
|
|
if (m_szLevelFolder[strlen(m_szLevelFolder) - 1] != '/')
|
|
{
|
|
azstrcat(m_szLevelFolder, AZ_ARRAY_SIZE (m_szLevelFolder), "/");
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void C3DEngine::LoadDefaultAssets()
|
|
{
|
|
GetRenderer()->InitSystemResources(FRR_SYSTEM_RESOURCES);
|
|
|
|
//Add a call to refresh the loading screen and call the loading tick functions to ensure that no big gaps in coverage occur.
|
|
SYNCHRONOUS_LOADING_TICK();
|
|
|
|
#if !defined(SYS_ENV_AS_STRUCT)
|
|
PREFAST_ASSUME(gEnv);
|
|
#endif
|
|
|
|
GetMatMan()->InitDefaults();
|
|
|
|
m_nBlackTexID = GetRenderer()->EF_LoadTexture("EngineAssets/Textures/black.dds", FT_DONT_STREAM)->GetTextureID();
|
|
m_nBlackCMTexID = GetRenderer()->EF_LoadTexture("EngineAssets/Textures/BlackCM.dds", FT_DONT_RELEASE | FT_DONT_STREAM)->GetTextureID();
|
|
|
|
m_pMatFogVolEllipsoid = GetMatMan()->LoadMaterial("EngineAssets/Materials/Fog/FogVolumeEllipsoid", false);
|
|
m_pMatFogVolBox = GetMatMan()->LoadMaterial("EngineAssets/Materials/Fog/FogVolumeBox", false);
|
|
|
|
if (!m_pRESky)
|
|
{
|
|
m_pRESky = (CRESky*)GetRenderer()->EF_CreateRE(eDATA_Sky); //m_pRESky->m_fAlpha = 1.f;
|
|
}
|
|
if (!m_pREHDRSky)
|
|
{
|
|
m_pREHDRSky = (CREHDRSky*)GetRenderer()->EF_CreateRE(eDATA_HDRSky);
|
|
}
|
|
|
|
if (!m_ptexIconLowMemoryUsage)
|
|
{
|
|
m_ptexIconLowMemoryUsage = gEnv->pRenderer->EF_LoadDefaultTexture("LowMemoryUsage");
|
|
}
|
|
|
|
if (!m_ptexIconAverageMemoryUsage)
|
|
{
|
|
m_ptexIconAverageMemoryUsage = gEnv->pRenderer->EF_LoadDefaultTexture("AverageMemoryUsage");
|
|
}
|
|
|
|
if (!m_ptexIconHighMemoryUsage)
|
|
{
|
|
m_ptexIconHighMemoryUsage = gEnv->pRenderer->EF_LoadDefaultTexture("HighMemoryUsage");
|
|
}
|
|
|
|
if (!m_ptexIconEditorConnectedToConsole)
|
|
{
|
|
m_ptexIconEditorConnectedToConsole = gEnv->pRenderer->EF_LoadDefaultTexture("LivePreview");
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool C3DEngine::InitLevelForEditor([[maybe_unused]] const char* szFolderName, [[maybe_unused]] const char* szMissionName)
|
|
{
|
|
#if defined(CONSOLE)
|
|
CRY_ASSERT_MESSAGE(0, "InitLevelForEditor not supported on consoles yet");
|
|
return false;
|
|
#else
|
|
LOADING_TIME_PROFILE_SECTION;
|
|
|
|
m_bEditor = true;
|
|
m_bAreaActivationInUse = false;
|
|
m_bLayersActivated = true;
|
|
|
|
ClearDebugFPSInfo();
|
|
|
|
|
|
if (!szFolderName || !szFolderName[0])
|
|
{
|
|
Warning("C3DEngine::LoadLevel: Level name is not specified");
|
|
return 0;
|
|
}
|
|
|
|
if (!szMissionName || !szMissionName[0])
|
|
{
|
|
Warning("C3DEngine::LoadLevel: Mission name is not specified");
|
|
}
|
|
|
|
char szMissionNameBody[256] = "NoMission";
|
|
if (!szMissionName)
|
|
{
|
|
szMissionName = szMissionNameBody;
|
|
}
|
|
|
|
SetLevelPath(szFolderName);
|
|
|
|
// Load console vars specific to this level.
|
|
if (GetPak()->IsFileExist(GetLevelFilePath(LEVEL_CONFIG_FILE)))
|
|
{
|
|
GetISystem()->LoadConfiguration(GetLevelFilePath(LEVEL_CONFIG_FILE));
|
|
}
|
|
|
|
if (GetPak()->IsFileExist(GetLevelFilePath(LEVEL_EDITOR_CONFIG_FILE)))
|
|
{
|
|
GetISystem()->LoadConfiguration(GetLevelFilePath(LEVEL_EDITOR_CONFIG_FILE));
|
|
}
|
|
|
|
if (!m_pObjManager)
|
|
{
|
|
m_pObjManager = CryAlignedNew<CObjManager>();
|
|
}
|
|
|
|
if (!m_pVisAreaManager)
|
|
{
|
|
m_pVisAreaManager = new CVisAreaManager();
|
|
}
|
|
|
|
CRY_ASSERT(m_pClipVolumeManager->GetClipVolumeCount() == 0);
|
|
|
|
if (m_pSkyLightManager)
|
|
{
|
|
m_pSkyLightManager->InitSkyDomeMesh();
|
|
}
|
|
|
|
// recreate decals
|
|
SAFE_DELETE(m_pDecalManager);
|
|
m_pDecalManager = new CDecalManager();
|
|
|
|
// restore game state
|
|
EnableOceanRendering(true);
|
|
m_pObjManager->SetLockCGFResources(0);
|
|
|
|
LoadDefaultAssets();
|
|
|
|
{
|
|
const char* SettingsFileName = GetLevelFilePath("ScreenshotMap.Settings");
|
|
|
|
AZ::IO::HandleType metaFileHandle = gEnv->pCryPak->FOpen(SettingsFileName, "r");
|
|
if (metaFileHandle != AZ::IO::InvalidHandle)
|
|
{
|
|
char Data[1024 * 8];
|
|
gEnv->pCryPak->FRead(Data, sizeof(Data), metaFileHandle);
|
|
azsscanf(Data, "<Map CenterX=\"%f\" CenterY=\"%f\" SizeX=\"%f\" SizeY=\"%f\" Height=\"%f\" Quality=\"%d\" Orientation=\"%d\" />",
|
|
&GetCVars()->e_ScreenShotMapCenterX,
|
|
&GetCVars()->e_ScreenShotMapCenterY,
|
|
&GetCVars()->e_ScreenShotMapSizeX,
|
|
&GetCVars()->e_ScreenShotMapSizeY,
|
|
&GetCVars()->e_ScreenShotMapCamHeight,
|
|
&GetCVars()->e_ScreenShotQuality,
|
|
&GetCVars()->e_ScreenShotMapOrientation);
|
|
gEnv->pCryPak->FClose(metaFileHandle);
|
|
}
|
|
}
|
|
|
|
|
|
GetObjManager()->LoadOcclusionMesh(szFolderName);
|
|
|
|
// delete m_pObjectsTree[nSID];
|
|
// m_pObjectsTree[nSID] = NULL;
|
|
return (true);
|
|
#endif
|
|
}
|
|
|
|
bool C3DEngine::LevelLoadingInProgress()
|
|
{
|
|
return Cry3DEngineBase::m_bLevelLoadingInProgress;
|
|
}
|
|
|
|
bool C3DEngine::LoadCompiledOctreeForEditor()
|
|
{
|
|
// Load LevelData.xml File.
|
|
XmlNodeRef xmlLevelData = GetSystem()->LoadXmlFromFile(GetLevelFilePath(LEVEL_DATA_FILE));
|
|
|
|
if (xmlLevelData == 0)
|
|
{
|
|
Error("C3DEngine::LoadLevel: xml file not found (files missing?)"); // files missing ?
|
|
return false;
|
|
}
|
|
|
|
std::vector<struct IStatObj*>* pStatObjTable = NULL;
|
|
std::vector<_smart_ptr<IMaterial> >* pMatTable = NULL;
|
|
|
|
int nSID = 0;
|
|
|
|
XmlNodeRef nodeRef = xmlLevelData->findChild("SurfaceTypes");
|
|
|
|
LoadCollisionClasses(xmlLevelData->findChild("CollisionClasses"));
|
|
|
|
SAFE_DELETE(pStatObjTable);
|
|
SAFE_DELETE(pMatTable);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool C3DEngine::LoadVisAreas(std::vector<struct IStatObj*>** ppStatObjTable, std::vector<_smart_ptr<IMaterial> >** ppMatTable)
|
|
{
|
|
LOADING_TIME_PROFILE_SECTION;
|
|
|
|
PrintMessage("===== Loading %s =====", COMPILED_VISAREA_MAP_FILE_NAME);
|
|
|
|
// open file
|
|
AZ::IO::HandleType fileHandle = GetPak()->FOpen(GetLevelFilePath(COMPILED_VISAREA_MAP_FILE_NAME), "rbx");
|
|
if (fileHandle == AZ::IO::InvalidHandle)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// read header
|
|
SVisAreaManChunkHeader header;
|
|
if (!GetPak()->FRead(&header, 1, fileHandle, false))
|
|
{
|
|
GetPak()->FClose(fileHandle);
|
|
return 0;
|
|
}
|
|
|
|
SwapEndian(header, (header.nFlags & SERIALIZATION_FLAG_BIG_ENDIAN) ? eBigEndian : eLittleEndian);
|
|
|
|
if (header.nChunkSize)
|
|
{
|
|
assert(!m_pVisAreaManager);
|
|
m_pVisAreaManager = new CVisAreaManager();
|
|
if (!m_pVisAreaManager->Load(fileHandle, header.nChunkSize, &header, *ppStatObjTable, *ppMatTable))
|
|
{
|
|
delete m_pVisAreaManager;
|
|
m_pVisAreaManager = NULL;
|
|
}
|
|
}
|
|
|
|
assert(GetPak()->FEof(fileHandle));
|
|
|
|
GetPak()->FClose(fileHandle);
|
|
|
|
return m_pVisAreaManager != NULL;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void C3DEngine::UnloadLevel()
|
|
{
|
|
if (!m_levelLoaded)
|
|
{
|
|
return;
|
|
}
|
|
GetRenderer()->EnableLevelUnloading(true);
|
|
|
|
GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_UNLOAD, 0, 0);
|
|
// Run any events that were queued against the system tick bus before we start tearing down systems and deleting things
|
|
// This should prevent any stale events from running when the next level is loaded
|
|
AZ::SystemTickBus::ExecuteQueuedEvents();
|
|
|
|
GetRenderer()->EnableLevelUnloading(false);
|
|
|
|
m_bInUnload = true;
|
|
m_szLevelFolder[0] = 0;
|
|
|
|
GetRenderer()->FlushRTCommands(true, true, true);
|
|
|
|
SVOGILegacyRequestBus::Broadcast(&SVOGILegacyRequests::ReleaseData);
|
|
InstanceStatObjEventBus::Broadcast(&InstanceStatObjEventBus::Events::ReleaseData);
|
|
|
|
FreeRNTmpDataPool();
|
|
|
|
if (m_pSkyLightManager)
|
|
{
|
|
m_pSkyLightManager->ReleaseSkyDomeMesh();
|
|
}
|
|
|
|
ResetPostEffects();
|
|
|
|
// delete decal manager
|
|
if (m_pDecalManager)
|
|
{
|
|
CryComment("Deleting Decals");
|
|
SAFE_DELETE(m_pDecalManager);
|
|
CryComment("done");
|
|
}
|
|
|
|
if (m_pOcean)
|
|
{
|
|
CryComment("Deleting Ocean");
|
|
SAFE_DELETE(m_pOcean);
|
|
CryComment("done");
|
|
}
|
|
|
|
// delete outdoor objects
|
|
CryComment("Deleting Octree");
|
|
DestroyOctree();
|
|
SAFE_DELETE(m_pObjectsTree);
|
|
m_pObjectsTree = nullptr;
|
|
|
|
// delete indoors
|
|
if (m_pVisAreaManager)
|
|
{
|
|
CryComment("Deleting VisAreas");
|
|
SAFE_DELETE(m_pVisAreaManager);
|
|
CryComment("done");
|
|
}
|
|
|
|
CRY_ASSERT(m_pClipVolumeManager->GetClipVolumeCount() == 0);
|
|
|
|
m_LightVolumesMgr.Reset();
|
|
|
|
m_pTerrainWaterMat = 0;
|
|
m_nWaterBottomTexId = 0;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CryComment("Removing Lights ...");
|
|
DeleteAllStaticLightSources();
|
|
SAFE_DELETE(m_pSun);
|
|
CryComment("done");
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
CleanLevelShaders();
|
|
|
|
if (m_pRESky)
|
|
{
|
|
m_pRESky->Release(true);
|
|
}
|
|
if (m_pREHDRSky)
|
|
{
|
|
m_pREHDRSky->Release(true);
|
|
}
|
|
m_pRESky = 0;
|
|
m_pREHDRSky = 0;
|
|
stl::free_container(m_skyMatName);
|
|
stl::free_container(m_skyLowSpecMatName);
|
|
m_previousSkyType = -1;
|
|
|
|
if (m_nCloudShadowTexId)
|
|
{
|
|
ITexture* tex = GetRenderer()->EF_GetTextureByID(m_nCloudShadowTexId);
|
|
if (tex)
|
|
{
|
|
tex->Release();
|
|
}
|
|
|
|
m_nCloudShadowTexId = 0;
|
|
GetRenderer()->SetCloudShadowsParams(0, Vec3(0, 0, 0), 1, false, 1);
|
|
SetGlobalParameter(E3DPARAM_VOLFOG_SHADOW_ENABLE, Vec3(0, 0, 0));
|
|
}
|
|
|
|
if (m_nNightMoonTexId)
|
|
{
|
|
ITexture* tex = GetRenderer()->EF_GetTextureByID(m_nNightMoonTexId);
|
|
if (tex)
|
|
{
|
|
tex->Release();
|
|
}
|
|
|
|
m_nNightMoonTexId = 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (m_pObjManager)
|
|
{
|
|
bool bDeleteAll = !m_bEditor || m_bInShutDown;
|
|
CryComment("Deleting Static Objects");
|
|
m_pObjManager->UnloadObjects(bDeleteAll);
|
|
m_pObjManager->GetCullThread().UnloadLevel();
|
|
CryComment("done");
|
|
}
|
|
|
|
AZ_Assert(m_pObjectsTree == nullptr, "m_pObjectsTree == nullptr");
|
|
COctreeNode::StaticReset();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Force delete all materials.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (GetMatMan() && !m_bEditor)
|
|
{
|
|
// Should be after deleting all meshes.
|
|
// We force delete all materials.
|
|
CryComment("Deleting Materials");
|
|
GetMatMan()->ShutDown();
|
|
CryComment("done");
|
|
}
|
|
|
|
//Set default icons to nullptr here, texture manager will take care of the memory release
|
|
m_ptexIconAverageMemoryUsage = nullptr;
|
|
m_ptexIconLowMemoryUsage = nullptr;
|
|
m_ptexIconHighMemoryUsage = nullptr;
|
|
m_ptexIconEditorConnectedToConsole = nullptr;
|
|
|
|
if (m_pOpticsManager && !gEnv->IsEditor())
|
|
{
|
|
m_pOpticsManager->Reset();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
stl::free_container(m_lstAlwaysVisible);
|
|
if (m_decalRenderNodes.empty())
|
|
{
|
|
stl::free_container(m_decalRenderNodes);
|
|
}
|
|
stl::free_container(m_lstPerObjectShadows);
|
|
m_nCustomShadowFrustumCount = 0;
|
|
|
|
Cry3DEngineBase::m_pRenderMeshMerger->Reset();
|
|
|
|
SAFE_DELETE(m_pTimeOfDay);
|
|
CLightEntity::StaticReset();
|
|
CVisArea::StaticReset();
|
|
CFogVolumeRenderNode::StaticReset();
|
|
|
|
GetRenderer()->FlushRTCommands(true, true, true);
|
|
|
|
IDeferredPhysicsEventManager* pPhysEventManager = GetDeferredPhysicsEventManager();
|
|
if (pPhysEventManager)
|
|
{
|
|
pPhysEventManager->ClearDeferredEvents();
|
|
}
|
|
|
|
m_PhysicsAreaUpdates.Reset();
|
|
for (size_t i = 0; i < NUM_BENDING_POOLS; stl::free_container(m_bendingPool[i++]))
|
|
{
|
|
;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// clear data used for SRenderingPass
|
|
stl::free_container(m_RenderingPassCameras[0]);
|
|
stl::free_container(m_RenderingPassCameras[1]);
|
|
stl::free_container(m_deferredRenderComponentStreamingPriorityUpdates);
|
|
|
|
stl::free_container(m_lstCustomShadowFrustums);
|
|
|
|
m_nWindSamplePositions = 0;
|
|
if (m_pWindSamplePositions)
|
|
{
|
|
CryModuleMemalignFree(m_pWindSamplePositions);
|
|
m_pWindSamplePositions = NULL;
|
|
}
|
|
|
|
stl::free_container(m_collisionClasses);
|
|
m_levelLoaded = false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void C3DEngine::LoadFlaresData()
|
|
{
|
|
string flareExportListPath = gEnv->p3DEngine->GetLevelFilePath(FLARE_EXPORT_FILE);
|
|
XmlNodeRef pFlareRootNode = gEnv->pSystem->LoadXmlFromFile(flareExportListPath);
|
|
|
|
if (pFlareRootNode == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int nFlareExportFileVer = 0;
|
|
pFlareRootNode->getAttr("Version", nFlareExportFileVer);
|
|
|
|
for (int i = 0, iCount(pFlareRootNode->getChildCount()); i < iCount; ++i)
|
|
{
|
|
XmlNodeRef pFlareNode = pFlareRootNode->getChild(i);
|
|
if (pFlareNode == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
const char* flareName = NULL;
|
|
if (!pFlareNode->getAttr("name", &flareName))
|
|
{
|
|
continue;
|
|
}
|
|
int nOutIndex(-1);
|
|
|
|
if (nFlareExportFileVer == 0)
|
|
{
|
|
gEnv->pOpticsManager->Load(flareName, nOutIndex);
|
|
}
|
|
else if (nFlareExportFileVer == 1)
|
|
{
|
|
if (pFlareNode->getChildCount() == 0)
|
|
{
|
|
gEnv->pOpticsManager->Load(flareName, nOutIndex);
|
|
}
|
|
else if (pFlareNode->getChildCount() > 0)
|
|
{
|
|
gEnv->pOpticsManager->Load(pFlareNode, nOutIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool C3DEngine::LoadLevel(const char* szFolderName, const char* szMissionName)
|
|
{
|
|
LOADING_TIME_PROFILE_SECTION;
|
|
|
|
CRY_ASSERT(m_levelLoaded == false);
|
|
|
|
PREFAST_ASSUME(gEnv);
|
|
|
|
stl::scoped_set<bool> setInLoad(m_bInLoad, true);
|
|
|
|
m_bInUnload = false;
|
|
m_bAreaActivationInUse = false;
|
|
m_bLayersActivated = false;
|
|
m_eShadowMode = ESM_NORMAL;
|
|
|
|
m_vPrevMainFrameCamPos.Set(-1000000.f, -1000000.f, -1000000.f);
|
|
m_vAverageCameraMoveDir = Vec3(0);
|
|
m_fAverageCameraSpeed = 0;
|
|
|
|
ClearDebugFPSInfo();
|
|
|
|
#if !defined(CONSOLE)
|
|
m_bEditor = false;
|
|
#endif
|
|
|
|
assert(!m_bEditor);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
if (!szFolderName || !szFolderName[0])
|
|
{
|
|
Warning("C3DEngine::LoadLevel: Level name is not specified");
|
|
return 0;
|
|
}
|
|
|
|
if (!szMissionName || !szMissionName[0])
|
|
{
|
|
Warning("C3DEngine::LoadLevel: Mission name is not specified");
|
|
}
|
|
|
|
char szMissionNameBody[256] = "NoMission";
|
|
if (!szMissionName)
|
|
{
|
|
szMissionName = szMissionNameBody;
|
|
}
|
|
|
|
SetLevelPath(szFolderName);
|
|
|
|
if (GetPak()->IsFileExist(GetLevelFilePath(LEVEL_CONFIG_FILE)))
|
|
{
|
|
GetISystem()->LoadConfiguration(GetLevelFilePath(LEVEL_CONFIG_FILE));
|
|
}
|
|
|
|
{ // check is LevelData.xml file exist
|
|
char sMapFileName[_MAX_PATH];
|
|
cry_strcpy(sMapFileName, m_szLevelFolder);
|
|
cry_strcat(sMapFileName, LEVEL_DATA_FILE);
|
|
if (!IsValidFile(sMapFileName))
|
|
{
|
|
PrintMessage("Error: Level not found: %s", sMapFileName);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (!m_pObjManager)
|
|
{
|
|
m_pObjManager = CryAlignedNew<CObjManager>();
|
|
}
|
|
|
|
CRY_ASSERT(m_pClipVolumeManager->GetClipVolumeCount() == 0);
|
|
|
|
// Load and activate all shaders used by the level before activating any shaders
|
|
if (!m_bEditor)
|
|
{
|
|
LoadUsedShadersList();
|
|
}
|
|
|
|
#if AZ_LOADSCREENCOMPONENT_ENABLED
|
|
// Make sure system resources are inited before displaying a load screen
|
|
GetRenderer()->InitSystemResources(FRR_SYSTEM_RESOURCES);
|
|
// IMPORTANT: This MUST be done AFTER the LoadConfiguration() above.
|
|
EBUS_EVENT(LoadScreenBus, LevelStart);
|
|
#endif // if AZ_LOADSCREENCOMPONENT_ENABLED
|
|
|
|
LoadDefaultAssets();
|
|
|
|
if (m_pSkyLightManager)
|
|
{
|
|
m_pSkyLightManager->InitSkyDomeMesh();
|
|
// set default render parameters.
|
|
// for some reason this is not done later???
|
|
m_pSkyLightManager->UpdateRenderParams();
|
|
}
|
|
|
|
// Load LevelData.xml File.
|
|
XmlNodeRef xmlLevelData = GetSystem()->LoadXmlFromFile(GetLevelFilePath(LEVEL_DATA_FILE));
|
|
|
|
if (xmlLevelData == 0)
|
|
{
|
|
Error("C3DEngine::LoadLevel: xml file not found (files missing?)"); // files missing ?
|
|
return false;
|
|
}
|
|
|
|
// re-create decal manager
|
|
SAFE_DELETE(m_pDecalManager);
|
|
m_pDecalManager = new CDecalManager();
|
|
|
|
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_MATERIALS);
|
|
if (GetCVars()->e_PreloadMaterials)
|
|
{
|
|
// Preload materials.
|
|
GetMatMan()->PreloadLevelMaterials();
|
|
}
|
|
if (GetCVars()->e_PreloadDecals)
|
|
{
|
|
// Preload materials.
|
|
GetMatMan()->PreloadDecalMaterials();
|
|
}
|
|
|
|
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_OBJECTS);
|
|
// preload level cgfs
|
|
if (GetCVars()->e_StatObjPreload && !gEnv->IsEditor())
|
|
{
|
|
m_pObjManager->PreloadLevelObjects();
|
|
}
|
|
|
|
std::vector<struct IStatObj*>* pStatObjTable = NULL;
|
|
std::vector<_smart_ptr<IMaterial> >* pMatTable = NULL;
|
|
|
|
int nSID = 0;
|
|
|
|
// load terrain
|
|
XmlNodeRef nodeRef = xmlLevelData->findChild("SurfaceTypes");
|
|
|
|
LoadCollisionClasses(xmlLevelData->findChild("CollisionClasses"));
|
|
|
|
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_STATIC_WORLD);
|
|
|
|
#if defined(FEATURE_SVO_GI)
|
|
if (gEnv->pConsole->GetCVar("e_GI")->GetIVal())
|
|
{
|
|
// Load SVOGI settings
|
|
char szFileName[256];
|
|
azsprintf(szFileName, "mission_%s.xml", szMissionName);
|
|
XmlNodeRef xmlMission = GetSystem()->LoadXmlFromFile(Get3DEngine()->GetLevelFilePath(szFileName));
|
|
if (xmlMission)
|
|
{
|
|
LoadTISettings(xmlMission->findChild("Environment"));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// load indoors
|
|
if (!LoadVisAreas(&pStatObjTable, &pMatTable))
|
|
{
|
|
Error("VisAreas file (%s) not found or file version error, please try to re-export the level", COMPILED_VISAREA_MAP_FILE_NAME);
|
|
return false;
|
|
}
|
|
|
|
SAFE_DELETE(pStatObjTable);
|
|
SAFE_DELETE(pMatTable);
|
|
|
|
//Update loading screen and important tick functions
|
|
SYNCHRONOUS_LOADING_TICK();
|
|
|
|
PrintMessage("===== Loading mission settings from XML =====");
|
|
|
|
//Update loading screen and important tick functions
|
|
SYNCHRONOUS_LOADING_TICK();
|
|
|
|
// load leveldata.xml
|
|
m_pTerrainWaterMat = 0;
|
|
m_nWaterBottomTexId = 0;
|
|
LoadMissionDataFromXMLNode(szMissionName);
|
|
|
|
//Update loading screen and important tick functions
|
|
SYNCHRONOUS_LOADING_TICK();
|
|
|
|
|
|
// init water if not initialized already (if no mission was found)
|
|
if (!GetOcean())
|
|
{
|
|
PrintMessage("===== Creating Ocean =====");
|
|
CreateOcean(m_pTerrainWaterMat, COcean::GetWaterLevelInfo());
|
|
}
|
|
|
|
PrintMessage("===== Load level physics data =====");
|
|
LoadFlaresData();
|
|
|
|
// restore game state
|
|
EnableOceanRendering(true);
|
|
m_pObjManager->SetLockCGFResources(false);
|
|
|
|
PrintMessage("===== loading occlusion mesh =====");
|
|
|
|
GetObjManager()->LoadOcclusionMesh(szFolderName);
|
|
|
|
PrintMessage("===== Finished loading static world =====");
|
|
|
|
m_skipedLayers.clear();
|
|
|
|
if (gEnv->pMaterialEffects)
|
|
{
|
|
gEnv->pMaterialEffects->CompleteInit();
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void C3DEngine::LoadCollisionClasses(XmlNodeRef node)
|
|
{
|
|
m_collisionClasses.clear();
|
|
if (node)
|
|
{
|
|
int count = node->getChildCount();
|
|
m_collisionClasses.reserve(count);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
SCollisionClass cc(0, 0);
|
|
XmlNodeRef xmlCC = node->getChild(i);
|
|
xmlCC->getAttr("type", cc.type);
|
|
xmlCC->getAttr("ignore", cc.ignore);
|
|
m_collisionClasses.push_back(cc);
|
|
}
|
|
}
|
|
}
|
|
|
|
void C3DEngine::LoadMissionDataFromXMLNode(const char* szMissionName)
|
|
{
|
|
LOADING_TIME_PROFILE_SECTION;
|
|
|
|
GetRenderer()->MakeMainContextActive();
|
|
|
|
// set default values
|
|
m_vFogColor(1, 1, 1);
|
|
m_fMaxViewDistHighSpec = 8000;
|
|
m_fMaxViewDistLowSpec = 1000;
|
|
m_vDefFogColor = m_vFogColor;
|
|
|
|
// mission environment
|
|
if (szMissionName && szMissionName[0])
|
|
{
|
|
char szFileName[256];
|
|
sprintf_s(szFileName, "mission_%s.xml", szMissionName);
|
|
XmlNodeRef xmlMission = GetSystem()->LoadXmlFromFile(Get3DEngine()->GetLevelFilePath(szFileName));
|
|
if (xmlMission)
|
|
{
|
|
LoadEnvironmentSettingsFromXML(xmlMission->findChild("Environment"), GetDefSID());
|
|
LoadTimeOfDaySettingsFromXML(xmlMission->findChild("TimeOfDay"));
|
|
}
|
|
else
|
|
{
|
|
Error("C3DEngine::LoadMissionDataFromXMLNode: Mission file not found: %s", szFileName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Error("C3DEngine::LoadMissionDataFromXMLNode: Mission name is not defined");
|
|
}
|
|
}
|
|
|
|
char* C3DEngine::GetXMLAttribText(XmlNodeRef pInputNode, const char* szLevel1, const char* szLevel2, const char* szDefaultValue)
|
|
{
|
|
static char szResText[128];
|
|
|
|
cry_strcpy(szResText, szDefaultValue);
|
|
|
|
XmlNodeRef nodeLevel = pInputNode->findChild(szLevel1);
|
|
if (nodeLevel && nodeLevel->haveAttr(szLevel2))
|
|
{
|
|
cry_strcpy(szResText, nodeLevel->getAttr(szLevel2));
|
|
}
|
|
|
|
return szResText;
|
|
}
|
|
|
|
char* C3DEngine::GetXMLAttribText(XmlNodeRef pInputNode, const char* szLevel1, const char* szLevel2, const char* szLevel3, const char* szDefaultValue)
|
|
{
|
|
static char szResText[128];
|
|
|
|
cry_strcpy(szResText, szDefaultValue);
|
|
|
|
XmlNodeRef nodeLevel = pInputNode->findChild(szLevel1);
|
|
if (nodeLevel)
|
|
{
|
|
nodeLevel = nodeLevel->findChild(szLevel2);
|
|
if (nodeLevel)
|
|
{
|
|
cry_strcpy(szResText, nodeLevel->getAttr(szLevel3));
|
|
}
|
|
}
|
|
|
|
return szResText;
|
|
}
|
|
|
|
void C3DEngine::UpdateMoonDirection()
|
|
{
|
|
float moonLati(-gf_PI + gf_PI* m_moonRotationLatitude / 180.0f);
|
|
float moonLong(0.5f * gf_PI - gf_PI* m_moonRotationLongitude / 180.0f);
|
|
|
|
float sinLon(sinf(moonLong));
|
|
float cosLon(cosf(moonLong));
|
|
float sinLat(sinf(moonLati));
|
|
float cosLat(cosf(moonLati));
|
|
|
|
m_moonDirection = Vec3(sinLon * cosLat, sinLon * sinLat, cosLon);
|
|
}
|
|
|
|
void C3DEngine::LoadEnvironmentSettingsFromXML(XmlNodeRef pInputNode, [[maybe_unused]] int nSID)
|
|
{
|
|
PrintComment("Loading environment settings from XML ...");
|
|
|
|
// set start and end time for dawn/dusk (to fade moon/sun light in and out)
|
|
float dawnTime = (float)atof(GetXMLAttribText(pInputNode, "Lighting", "DawnTime", "355"));
|
|
float dawnDuration = (float)atof(GetXMLAttribText(pInputNode, "Lighting", "DawnDuration", "10"));
|
|
float duskTime = (float)atof(GetXMLAttribText(pInputNode, "Lighting", "DuskTime", "365"));
|
|
float duskDuration = (float)atof(GetXMLAttribText(pInputNode, "Lighting", "DuskDuration", "10"));
|
|
|
|
m_dawnStart = (dawnTime - dawnDuration * 0.5f) / 60.0f;
|
|
m_dawnEnd = (dawnTime + dawnDuration * 0.5f) / 60.0f;
|
|
m_duskStart = 12.0f + (duskTime - duskDuration * 0.5f) / 60.0f;
|
|
m_duskEnd = 12.0f + (duskTime + duskDuration * 0.5f) / 60.0f;
|
|
|
|
if (m_dawnEnd > m_duskStart)
|
|
{
|
|
m_duskEnd += m_dawnEnd - m_duskStart;
|
|
m_duskStart = m_dawnEnd;
|
|
}
|
|
|
|
|
|
// get moon info
|
|
m_moonRotationLatitude = (float)atof(GetXMLAttribText(pInputNode, "Moon", "Latitude", "240"));
|
|
m_moonRotationLongitude = (float)atof(GetXMLAttribText(pInputNode, "Moon", "Longitude", "45"));
|
|
UpdateMoonDirection();
|
|
|
|
m_nightMoonSize = (float)atof(GetXMLAttribText(pInputNode, "Moon", "Size", "0.5"));
|
|
|
|
{
|
|
char moonTexture[256];
|
|
cry_strcpy(moonTexture, GetXMLAttribText(pInputNode, "Moon", "Texture", ""));
|
|
|
|
ITexture* pTex(0);
|
|
if (moonTexture[0] != '\0')
|
|
{
|
|
pTex = GetRenderer()->EF_LoadTexture(moonTexture, FT_DONT_STREAM);
|
|
}
|
|
|
|
m_nNightMoonTexId = pTex ? pTex->GetTextureID() : 0;
|
|
}
|
|
|
|
// max view distance
|
|
m_fMaxViewDistHighSpec = (float)atol(GetXMLAttribText(pInputNode, "Fog", "ViewDistance", "8000"));
|
|
m_fMaxViewDistLowSpec = (float)atol(GetXMLAttribText(pInputNode, "Fog", "ViewDistanceLowSpec", "1000"));
|
|
m_fMaxViewDistScale = 1.f;
|
|
|
|
m_volFogGlobalDensityMultiplierLDR = (float)max(atof(GetXMLAttribText(pInputNode, "Fog", "LDRGlobalDensMult", "1.0")), 0.0);
|
|
|
|
// SkyBox
|
|
const string skyMaterialName = GetXMLAttribText(pInputNode, "SkyBox", "Material", "Materials/Sky/Sky");
|
|
const string skyLowSpecMaterialName = GetXMLAttribText(pInputNode, "SkyBox", "MaterialLowSpec", "Materials/Sky/Sky");
|
|
SetSkyMaterialPath(skyMaterialName);
|
|
SetSkyLowSpecMaterialPath(skyLowSpecMaterialName);
|
|
LoadSkyMaterial();
|
|
|
|
m_fSkyBoxAngle = (float)atof(GetXMLAttribText(pInputNode, "SkyBox", "Angle", "0.0"));
|
|
m_fSkyBoxStretching = (float)atof(GetXMLAttribText(pInputNode, "SkyBox", "Stretching", "1.0"));
|
|
|
|
// set terrain water (aka the infinite ocean), sun road and bottom shaders
|
|
if (OceanToggle::IsActive())
|
|
{
|
|
AZStd::string szOceanMatName = OceanRequest::GetOceanMaterialName();
|
|
m_pTerrainWaterMat = GetMatMan()->LoadMaterial(szOceanMatName.c_str(), false);
|
|
}
|
|
else
|
|
{
|
|
char szTerrainWaterMatName[256];
|
|
cry_strcpy(szTerrainWaterMatName, GetXMLAttribText(pInputNode, "Ocean", "Material", "EngineAssets/Materials/Water/Ocean_default"));
|
|
m_pTerrainWaterMat = szTerrainWaterMatName[0] ? GetMatMan()->LoadMaterial(szTerrainWaterMatName, false) : nullptr;
|
|
}
|
|
CreateOcean(m_pTerrainWaterMat, COcean::GetWaterLevelInfo());
|
|
|
|
m_oceanWindDirection = (float) atof(GetXMLAttribText(pInputNode, "OceanAnimation", "WindDirection", "1.0"));
|
|
m_oceanWindSpeed = (float) atof(GetXMLAttribText(pInputNode, "OceanAnimation", "WindSpeed", "4.0"));
|
|
m_oceanWavesSpeed = (float) atof(GetXMLAttribText(pInputNode, "OceanAnimation", "WavesSpeed", "1.0"));
|
|
m_oceanWavesAmount = (float) atof(GetXMLAttribText(pInputNode, "OceanAnimation", "WavesAmount", "1.5"));
|
|
m_oceanWavesSize = (float) atof(GetXMLAttribText(pInputNode, "OceanAnimation", "WavesSize", "0.75"));
|
|
|
|
// re-scale speed based on size - the smaller the faster waves move
|
|
m_oceanWavesSpeed /= m_oceanWavesSize;
|
|
|
|
m_oceanCausticsDistanceAtten = (float)atof(GetXMLAttribText(pInputNode, "Ocean", "CausticsDistanceAtten", "100.0"));
|
|
m_oceanCausticsTiling = (float)atof(GetXMLAttribText(pInputNode, "Ocean", "CausticsTilling", "1.0"));
|
|
m_oceanCausticDepth = (float)atof(GetXMLAttribText(pInputNode, "Ocean", "CausticDepth", "8.0"));
|
|
m_oceanCausticIntensity = (float)atof(GetXMLAttribText(pInputNode, "Ocean", "CausticIntensity", "1.0"));
|
|
|
|
// update relevant time of day settings
|
|
ITimeOfDay* pTimeOfDay(GetTimeOfDay());
|
|
if (pTimeOfDay)
|
|
{
|
|
CTimeOfDay::SEnvironmentInfo envTODInfo;
|
|
{
|
|
const char* pText = GetXMLAttribText(pInputNode, "EnvState", "SunLinkedToTOD", "true");
|
|
envTODInfo.bSunLinkedToTOD = !strcmp(pText, "true") || !strcmp(pText, "1");
|
|
}
|
|
// get rotation of sun around z axis (needed to define an arbitrary path over zenit for day/night cycle position calculations)
|
|
envTODInfo.sunRotationLatitude = (float) atof(GetXMLAttribText(pInputNode, "Lighting", "SunRotation", "240"));
|
|
envTODInfo.sunRotationLongitude = (float) atof(GetXMLAttribText(pInputNode, "Lighting", "Longitude", "90"));
|
|
|
|
pTimeOfDay->SetEnvironmentSettings(envTODInfo);
|
|
pTimeOfDay->Update(true, true);
|
|
}
|
|
|
|
{
|
|
const char* pText = GetXMLAttribText(pInputNode, "EnvState", "SunShadowsMinSpec", "1");
|
|
int nMinSpec = atoi(pText);
|
|
if (nMinSpec > 0 && CheckMinSpec(nMinSpec))
|
|
{
|
|
m_bSunShadows = true;
|
|
}
|
|
else
|
|
{
|
|
m_bSunShadows = false;
|
|
}
|
|
}
|
|
|
|
{
|
|
const char* pText = GetXMLAttribText(pInputNode, "EnvState", "SunShadowsAdditionalCascadeMinSpec", "0");
|
|
int nMinSpec = atoi(pText);
|
|
if (nMinSpec > 0 && CheckMinSpec(nMinSpec))
|
|
{
|
|
m_nSunAdditionalCascades = 1;
|
|
}
|
|
else
|
|
{
|
|
m_nSunAdditionalCascades = 0;
|
|
}
|
|
}
|
|
|
|
{
|
|
m_nGsmCache = m_pConsole->GetCVar("r_ShadowsCache")->GetIVal();
|
|
}
|
|
|
|
{
|
|
const char* pText = GetXMLAttribText(pInputNode, "Terrain", "HeightMapAO", "false");
|
|
m_bHeightMapAoEnabled = !strcmp(pText, "true") || !strcmp(pText, "1");
|
|
}
|
|
|
|
{
|
|
int nMinSpec = 3;//atoi(pText);
|
|
m_fSunClipPlaneRange = 256.0;
|
|
m_fSunClipPlaneRangeShift = 0.0f;
|
|
|
|
if (nMinSpec > 0 && CheckMinSpec(nMinSpec))
|
|
{
|
|
m_fSunClipPlaneRange = (float)atof(GetXMLAttribText(pInputNode, "EnvState", "SunShadowsClipPlaneRange", "256.0"));
|
|
|
|
float fSunClipPlaneRangeShift = (float)atof(GetXMLAttribText(pInputNode, "EnvState", "SunShadowsClipPlaneRangeShift", "0.0"));
|
|
m_fSunClipPlaneRangeShift = clamp_tpl(fSunClipPlaneRangeShift / 100.0f, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
|
|
{
|
|
const char* pText = GetXMLAttribText(pInputNode, "EnvState", "UseLayersActivation", "false");
|
|
Get3DEngine()->m_bAreaActivationInUse = !strcmp(pText, "true") || !strcmp(pText, "1");
|
|
}
|
|
|
|
// load cloud shadow parameters
|
|
{
|
|
char cloudShadowTexture[256];
|
|
cry_strcpy(cloudShadowTexture, GetXMLAttribText(pInputNode, "CloudShadows", "CloudShadowTexture", ""));
|
|
|
|
ITexture* pTex = 0;
|
|
if (cloudShadowTexture[0] != '\0')
|
|
{
|
|
pTex = GetRenderer()->EF_LoadTexture(cloudShadowTexture, FT_DONT_STREAM);
|
|
}
|
|
|
|
m_nCloudShadowTexId = pTex ? pTex->GetTextureID() : 0;
|
|
|
|
// Get animation parameters
|
|
const Vec3 cloudShadowSpeed = StringToVector(GetXMLAttribText(pInputNode, "CloudShadows", "CloudShadowSpeed", "0,0,0"));
|
|
|
|
const float cloudShadowTiling = (float)atof(GetXMLAttribText(pInputNode, "CloudShadows", "CloudShadowTiling", "1.0"));
|
|
const float cloudShadowBrightness = (float)atof(GetXMLAttribText(pInputNode, "CloudShadows", "CloudShadowBrightness", "1.0"));
|
|
|
|
const char* pText = GetXMLAttribText(pInputNode, "CloudShadows", "CloudShadowInvert", "false");
|
|
const bool cloudShadowInvert = !strcmp(pText, "true") || !strcmp(pText, "1");
|
|
|
|
GetRenderer()->SetCloudShadowsParams(m_nCloudShadowTexId, cloudShadowSpeed, cloudShadowTiling, cloudShadowInvert, cloudShadowBrightness);
|
|
}
|
|
|
|
// Particle lighting params. <DEPRECATED> Remove for projects post C3, should be no particle lighting multipliers - have assets tweaked from start
|
|
{
|
|
m_fParticlesAmbientMultiplier = (float)atof(GetXMLAttribText(pInputNode, "ParticleLighting", "AmbientMul", "1.0"));
|
|
m_fParticlesLightMultiplier = (float)atof(GetXMLAttribText(pInputNode, "ParticleLighting", "LightsMul", "1.0"));
|
|
}
|
|
|
|
{
|
|
const char* pText = GetXMLAttribText(pInputNode, "VolFogShadows", "Enable", "false");
|
|
const bool enable = !strcmp(pText, "true") || !strcmp(pText, "1");
|
|
|
|
pText = GetXMLAttribText(pInputNode, "VolFogShadows", "EnableForClouds", "false");
|
|
const bool enableForClouds = !strcmp(pText, "true") || !strcmp(pText, "1");
|
|
|
|
SetGlobalParameter(E3DPARAM_VOLFOG_SHADOW_ENABLE, Vec3(enable ? 1.0f : 0.0f, enableForClouds ? 1.0f : 0.0f, 0.0f));
|
|
}
|
|
|
|
#if defined(FEATURE_SVO_GI)
|
|
if (gEnv->pConsole->GetCVar("e_GI")->GetIVal())
|
|
{
|
|
LoadTISettings(pInputNode);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void C3DEngine::LoadTimeOfDaySettingsFromXML(XmlNodeRef node)
|
|
{
|
|
if (node)
|
|
{
|
|
GetTimeOfDay()->Serialize(node, true);
|
|
ITimeOfDay::SAdvancedInfo info;
|
|
GetTimeOfDay()->GetAdvancedInfo(info);
|
|
GetTimeOfDay()->SetTime(info.fStartTime, true);
|
|
}
|
|
}
|
|
|
|
//! create static object containing empty IndexedMesh
|
|
IStatObj* C3DEngine::CreateStatObj()
|
|
{
|
|
CStatObj* pStatObj = new CStatObj();
|
|
pStatObj->m_pIndexedMesh = new CIndexedMesh();
|
|
return pStatObj;
|
|
}
|
|
|
|
IStatObj* C3DEngine::CreateStatObjOptionalIndexedMesh(bool createIndexedMesh)
|
|
{
|
|
CStatObj* pStatObj = new CStatObj();
|
|
if (createIndexedMesh)
|
|
{
|
|
pStatObj->m_pIndexedMesh = new CIndexedMesh();
|
|
}
|
|
return pStatObj;
|
|
}
|
|
|
|
bool C3DEngine::RestoreTerrainFromDisk([[maybe_unused]] int nSID)
|
|
{
|
|
ResetParticlesAndDecals();
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool C3DEngine::LoadUsedShadersList()
|
|
{
|
|
LOADING_TIME_PROFILE_SECTION;
|
|
gEnv->pRenderer->EF_Query(EFQ_SetShaderCombinations);
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool C3DEngine::PrecreateDecals()
|
|
{
|
|
LOADING_TIME_PROFILE_SECTION;
|
|
|
|
CObjManager::DecalsToPrecreate& decals(GetObjManager()->GetDecalsToPrecreate());
|
|
// pre-create ...
|
|
if (GetCVars()->e_DecalsPreCreate)
|
|
{
|
|
CryLog("Pre-creating %d decals...", (int)decals.size());
|
|
|
|
CObjManager::DecalsToPrecreate::iterator it(decals.begin());
|
|
CObjManager::DecalsToPrecreate::iterator itEnd(decals.end());
|
|
for (; it != itEnd; ++it)
|
|
{
|
|
IDecalRenderNode* pDecalRenderNode(*it);
|
|
pDecalRenderNode->Precache();
|
|
}
|
|
|
|
CryLog(" done.\n");
|
|
}
|
|
else
|
|
{
|
|
CryLog("Skipped pre-creation of decals.\n");
|
|
}
|
|
|
|
// ... and discard list (even if pre-creation was skipped!)
|
|
decals.resize(0);
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Called by game when everything needed for level is loaded.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void C3DEngine::PostLoadLevel()
|
|
{
|
|
LOADING_TIME_PROFILE_SECTION;
|
|
|
|
CRY_ASSERT(m_levelLoaded == false);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Submit water material to physics if the ocean exists
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
if (GetCVars()->e_PrecacheLevel)
|
|
{
|
|
// pre-create decals
|
|
PrecreateDecals();
|
|
}
|
|
|
|
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_TEXTURES);
|
|
|
|
GetRenderer()->PostLevelLoading();
|
|
|
|
// refresh material constants pulled in from resources (such as textures)
|
|
GetMatMan()->RefreshShaderResourceConstants();
|
|
|
|
if (m_nGsmCache > 0)
|
|
{
|
|
m_CachedShadowsBounds.Reset();
|
|
SetRecomputeCachedShadows(m_nCachedShadowsUpdateStrategy = ShadowMapFrustum::ShadowCacheData::eFullUpdate);
|
|
}
|
|
m_levelLoaded = true;
|
|
}
|
|
|
|
|
|
int C3DEngine::SaveStatObj(IStatObj* pStatObj, TSerialize ser)
|
|
{
|
|
if (!(pStatObj->GetFlags() & STATIC_OBJECT_GENERATED))
|
|
{
|
|
bool bVal = false;
|
|
ser.Value("altered", bVal);
|
|
ser.Value("file", pStatObj->GetFilePath());
|
|
ser.Value("geom", pStatObj->GetGeoName());
|
|
}
|
|
else
|
|
{
|
|
bool bVal = true;
|
|
ser.Value("altered", bVal);
|
|
ser.Value("CloneSource", pStatObj->GetCloneSourceObject() ? pStatObj->GetCloneSourceObject()->GetFilePath() : "0");
|
|
pStatObj->Serialize(ser);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
IStatObj* C3DEngine::LoadStatObj(TSerialize ser)
|
|
{
|
|
bool bVal;
|
|
IStatObj* pStatObj;
|
|
ser.Value("altered", bVal);
|
|
if (!bVal)
|
|
{
|
|
string fileName, geomName;
|
|
ser.Value("file", fileName);
|
|
ser.Value("geom", geomName);
|
|
pStatObj = LoadStatObjUnsafeManualRef(fileName, geomName);
|
|
}
|
|
else
|
|
{
|
|
string srcObjName;
|
|
ser.Value("CloneSource", srcObjName);
|
|
if (*(const unsigned short*)(const char*)srcObjName != '0')
|
|
{
|
|
pStatObj = LoadStatObjUnsafeManualRef(srcObjName)->Clone(false, false, true);
|
|
}
|
|
else
|
|
{
|
|
pStatObj = CreateStatObj();
|
|
}
|
|
pStatObj->Serialize(ser);
|
|
}
|
|
return pStatObj;
|
|
}
|
|
|
|
|
|
|
|
|