Files
FC1/Cry3DEngine/3dEngine.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

2638 lines
78 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: 3dengine.cpp
// Version: v1.00
// Created: 28/5/2001 by Vladimir Kajalin
// Compilers: Visual Studio.NET
// Description: Implementation of I3DEngine interface methods
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "3dEngine.h"
#include "visareas.h"
#include "objman.h"
#include "terrain_water.h"
#include "CryStaticModel.h"
#include "partman.h"
#include "DecalManager.h"
#include "bflyes.h"
#include "rain.h"
#include "meshidx.h"
#include "detail_grass.h"
#include "StencilShadowEdgeDetector.h" // CStencilShadowEdgeDetector
#include "StencilShadowConnectivityBuilder.h" // CStencilShadowConnectivityBuilder
#include "watervolumes.h"
#include "LMCompStructures.h"
#include "LMSerializationManager2.h"
#include "brush.h"
ISystem * Cry3DEngineBase::m_pSys=0;
IRenderer * Cry3DEngineBase::m_pRenderer=0;
ITimer * Cry3DEngineBase::m_pTimer=0;
ILog * Cry3DEngineBase::m_pLog=0;
IPhysicalWorld * Cry3DEngineBase::m_pPhysicalWorld=0;
IConsole * Cry3DEngineBase::m_pConsole=0;
I3DEngine * Cry3DEngineBase::m_p3DEngine=0;
CVars * Cry3DEngineBase::m_pCVars=0;
ICryPak * Cry3DEngineBase::m_pCryPak=0;
int Cry3DEngineBase::m_nRenderStackLevel=0;
int Cry3DEngineBase::m_dwRecursionDrawFlags[2]={0,0};
int Cry3DEngineBase::m_nRenderFrameID = 0;
bool Cry3DEngineBase::m_bProfilerEnabled = false;
int Cry3DEngineBase::m_CpuFlags=0;
double Cry3DEngineBase::m_SecondsPerCycle=0;
float Cry3DEngineBase::m_fPreloadStartTime=0;
bool Cry3DEngineBase::m_bIgnoreFakeMaterialsInCGF = false;
bool Cry3DEngineBase::m_bEditorMode = false;
ESystemConfigSpec Cry3DEngineBase::m_configSpec = CONFIG_VERYHIGH_SPEC;
ESystemConfigSpec Cry3DEngineBase::m_LightConfigSpec = CONFIG_VERYHIGH_SPEC;
#define LAST_POTENTIALLY_VISIBLE_TIME 2
//////////////////////////////////////////////////////////////////////
C3DEngine::C3DEngine(ISystem * pSystem)
{
CXFile::SetIPack(pSystem->GetIPak());
Cry3DEngineBase::m_pSys=pSystem;
Cry3DEngineBase::m_pRenderer=pSystem->GetIRenderer();
Cry3DEngineBase::m_pTimer=pSystem->GetITimer();
Cry3DEngineBase::m_pLog=pSystem->GetILog();
Cry3DEngineBase::m_pPhysicalWorld=pSystem->GetIPhysicalWorld();
Cry3DEngineBase::m_pConsole=pSystem->GetIConsole();
Cry3DEngineBase::m_p3DEngine=this;
Cry3DEngineBase::m_pCryPak=pSystem->GetIPak();
Cry3DEngineBase::m_pCVars=0;
Cry3DEngineBase::m_CpuFlags=pSystem->GetCPUFlags();
Cry3DEngineBase::m_SecondsPerCycle=pSystem->GetSecondsPerCycle();
#ifdef _DEBUG
#ifndef _XBOX
// _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // _crtBreakAlloc
// _controlfp( _EM_INEXACT,_MCW_EM );
#endif
#endif
m_pShadowEdgeDetector=new CStencilShadowEdgeDetector();
m_pConnectivityBuilder=new CStencilShadowConnectivityBuilder();
m_pStaticConnectivityBuilder = new CStencilShadowStaticConnectivityBuilder();
m_pRenderCallbackFunc = NULL;
memset(m_SunObject, 0, sizeof(m_SunObject));
m_pBlurObj=0;
m_pBlurObj=GetRenderer()->EF_GetObject(false, -1);
m_pScreenObj=0;
m_pScreenObj=GetRenderer()->EF_GetObject(false, -1);
m_szLevelFolder[0]=0;
m_nFlags=0;
m_pRE2DQuad=0;
m_pSHFullScreenQuad = NULL;
m_pSHSky = NULL;//GetRenderer()->EF_LoadShader("InfRedGal", eSH_World, EF_SYSTEM);
m_pTerrainWaterShader = m_pSunRoadShader = 0;
m_nWaterBottomTexId=0;
m_pSHLensFlares = GetRenderer()->EF_LoadShader("CryLight", eSH_World, EF_SYSTEM);
m_vSunPosition = Vec3d(0, -10000.0f, 10000.0f);
m_pSHDefault = GetRenderer()->EF_LoadShader("Default", eSH_World, EF_SYSTEM);
m_pTerrain=0;
m_bEnabled=1;
ITexPic * pPic = GetRenderer()->EF_LoadTexture("diskette.tga",0,0,eTT_Base);
m_nStreamingIconTexID = pPic->GetTextureID();
pPic = GetRenderer()->EF_LoadTexture("black.tga",0,0,eTT_Base);
m_nBlackTexID = pPic->GetTextureID();
ITexPic * pPicSpot = GetRenderer()->EF_LoadTexture("spot_shadow.tga",0,0,eTT_Base);
m_nShadowSpotTexId = pPicSpot->GetTextureID();
// create components
m_pObjManager = 0;//new CObjManager (m_pSystem);
m_pPartManager = 0;
m_pDecalManager = 0;//new CDecalManager (m_pSystem, this);
// m_pBFManager = new CBFManager ();
m_pRainManager = new CRainManager ();
m_pVisAreaManager = 0;
m_pCVars = new CVars();
Cry3DEngineBase::m_pCVars = m_pCVars;
// create REs
m_pRESky = (CRESky*) GetRenderer()->EF_CreateRE(eDATA_Sky); m_pRESky->m_fAlpha = 1.f;
//m_pREOutSpace = (CREOutSpace * ) GetRenderer()->EF_CreateRE(eDATA_OutSpace);
m_pREDummy = (CREDummy*) GetRenderer()->EF_CreateRE(eDATA_Dummy);
m_pRETerrainParticles = (CRETerrainParticles*)GetRenderer()->EF_CreateRE(eDATA_TerrainParticles);
m_pRE2DQuad = (CRE2DQuad*) GetRenderer()->EF_CreateRE(eDATA_2DQuad);
m_pREScreenProcess = (CREScreenProcess*) GetRenderer()->EF_CreateRE(eDATA_ScreenProcess);
m_pSHScreenTexMap = GetRenderer()->EF_LoadShader("ScreenTexMap", eSH_World, EF_SYSTEM);
m_pSHScreenProcess = GetRenderer()->EF_LoadShader("ScreenProcess", eSH_World, EF_SYSTEM);
m_pSHOutSpace = GetRenderer()->EF_LoadShader("OutSpace", eSH_World, EF_SYSTEM);
m_pSHFarTreeSprites = GetRenderer()->EF_LoadShader("FarTreeSprites", eSH_World, EF_SYSTEM);
m_pSHClearStencil = GetRenderer()->EF_LoadShader("ClearStencil", eSH_World, EF_SYSTEM);
m_pSHShadowMapGen = GetRenderer()->EF_LoadShader("ShadowMapGen", eSH_World, EF_SYSTEM);
m_pSHBinocularDistortMask = GetRenderer()->EF_LoadShader("BinocularDistortMask", eSH_World, EF_SYSTEM);
m_pSHScreenDistort = GetRenderer()->EF_LoadShader("ScreenDistort", eSH_World, EF_SYSTEM);
m_pSHSniperDistortMask = GetRenderer()->EF_LoadShader("SniperDistortMask", eSH_World, EF_SYSTEM);
m_pSHRainMap = GetRenderer()->EF_LoadShader("RainMap", eSH_World, EF_SYSTEM);
m_pSHStencil = GetRenderer()->EF_LoadShader("<Stencil>", eSH_World, EF_SYSTEM);
m_pSHStencilState = GetRenderer()->EF_LoadShader("StencilState", eSH_World, EF_SYSTEM);
m_pSHStencilStateInv = GetRenderer()->EF_LoadShader("StencilStateInv", eSH_World, EF_SYSTEM);
m_pSHTerrainParticles = GetRenderer()->EF_LoadShader("TerrainParticles", eSH_World, EF_SYSTEM);
m_pPhysMaterialEnumerator=0;
m_fMaxViewDist = 1024;
m_fWorldColorRatio = 1;
m_vWorldColorConst(0.5f,0.5f,0.5f);
m_fWaterBumpAmountX = 0.08f;
m_fWaterBumpAmountY = 0.11f;
m_fWaterBorderTranspRatio = m_fWaterReflectRatio = m_fWaterTranspRatio = 1.f;
m_fSkyBoxAngle=0;
m_fSkyBoxStretching=0;
m_fSunHeightScale=0;
m_pFogTopPlane=0;
m_vWindForce(0,-8,0);
m_pMatMan = new CMatMan();
m_bShore = m_bOcean = true;
m_pREShadowMapGenerator = (CREShadowMapGen*)GetRenderer()->EF_CreateRE(eDATA_ShadowMapGen);
m_bTerrainLightMapGenError = false;
m_vUnderWaterFogColor.Set(0.2f,0.35f,0.4f);
m_fUnderWaterFogDistance = 16;
m_bOceanCaustics = true;
m_fFogFarDist = DEFAULT_ZMAX;
m_nRealLightsNum=0;
m_pSysSpec = GetConsole()->GetCVar( "sys_spec" );
m_pLightQuality = GetConsole()->GetCVar("r_Quality_BumpMapping");
}
//////////////////////////////////////////////////////////////////////
C3DEngine::~C3DEngine()
{
assert(IsHeapValid());
ShutDown();
delete m_pPartManager;
delete m_pDecalManager;
// delete m_pBFManager;
delete m_pRainManager;
delete m_pVisAreaManager;
delete m_pObjManager;
delete m_pCVars;
delete m_pMatMan; m_pMatMan=0;
SAFE_RELEASE(m_pRESky);
//m_pREOutSpace->Release();
SAFE_RELEASE(m_pREDummy);
SAFE_RELEASE(m_pRETerrainParticles);
SAFE_RELEASE(m_pRE2DQuad);
SAFE_RELEASE(m_pREShadowMapGenerator);
SAFE_RELEASE(m_pREScreenProcess);
if (m_pSHLensFlares)
m_pSHLensFlares->Release(true);
if (m_pSHDefault)
m_pSHDefault->Release(true);
if (m_pSHScreenTexMap)
m_pSHScreenTexMap->Release(true);
if (m_pSHScreenProcess)
m_pSHScreenProcess->Release(true);
if (m_pSHOutSpace)
m_pSHOutSpace->Release(true);
if (m_pSHFarTreeSprites)
m_pSHFarTreeSprites->Release(true);
if (m_pSHClearStencil)
m_pSHClearStencil->Release(true);
if (m_pSHShadowMapGen)
m_pSHShadowMapGen->Release(true);
if (m_pSHBinocularDistortMask)
m_pSHBinocularDistortMask->Release(true);
if (m_pSHScreenDistort)
m_pSHScreenDistort->Release(true);
if (m_pSHSniperDistortMask)
m_pSHSniperDistortMask->Release(true);
if (m_pSHRainMap)
m_pSHRainMap->Release(true);
if (m_pSHStencil)
m_pSHStencil->Release(true);
if (m_pSHStencilState)
m_pSHStencilState->Release(true);
if (m_pSHStencilStateInv)
m_pSHStencilStateInv->Release(true);
if (m_pSHTerrainParticles)
m_pSHTerrainParticles->Release(true);
if (m_nStreamingIconTexID)
{
GetRenderer()->RemoveTexture(m_nStreamingIconTexID);
m_nStreamingIconTexID = 0;
}
if (m_nShadowSpotTexId)
{
GetRenderer()->RemoveTexture(m_nShadowSpotTexId);
m_nShadowSpotTexId = 0;
}
delete m_pShadowEdgeDetector;
delete m_pConnectivityBuilder;
delete m_pStaticConnectivityBuilder;
GetLog()->Log ("\003----------------------------------------------------------------------");
GetLog()->Log ("\003Cry3DEngine profile statistics:");
GetLog()->Log ("\003I3DEngine::MakeObject() : %4.1f sec", CObjManager::m_dMakeObjectTime);
GetLog()->Log ("\003I3DEngine::LoadLevel() : %4.1f sec", m_dLoadLevelTime);
GetLog()->Log ("\003I3DEngine::LoadMaterial() : %4.1f sec", CObjManager::m_dCIndexedMesh__LoadMaterial);
GetLog()->Log ("\003I3DEngine::UpdateCustomLightingSpritesAndShadowMaps() : %4.1f sec", CObjManager::m_dUpdateCustomLightingSpritesAndShadowMaps);
GetLog()->Log ("\003----------------------------------------------------------------------");
}
//////////////////////////////////////////////////////////////////////
bool C3DEngine::Init()
{
ShutDown();
return (true);
}
bool C3DEngine::IsCameraAnd3DEngineInvalid(const CCamera cam, const char * szCaller)
{
const Vec3d & vCamPos = cam.GetPos();
const Vec3d & vAngles = cam.GetAngles();
const float fFov = cam.GetFov();
if (!m_pObjManager || !m_pDecalManager)
{
//GetLog()->Log("Warning: %s: Engine not initialized or level not loaded");
return (true);
}
if( m_fMaxViewDist<=0 || m_fFogFarDist<=0 ||
!_finite(vCamPos.x) || !_finite(vCamPos.y) || !_finite(vCamPos.z) ||
!_finite(vAngles.x) || !_finite(vAngles.y) || !_finite(vAngles.z) ||
IsEquivalent(vCamPos,Vec3d(0,0,0),VEC_EPSILON) || vCamPos.z < -GetTerrainSize()*4 || vCamPos.z > GetTerrainSize()*4 ||
fFov < 0.025f || fFov > gf_PI)
{
Warning(0,0,"%s: Camera undefined : Pos=(%.1f, %.1f, %.1f), Rot=(%.1f, %.1f, %.1f), Fov=%.1f, MaxViewDist=%.1f, FogFarDist=%.1f",
szCaller,
vCamPos.x, vCamPos.y, vCamPos.z,
vAngles.x, vAngles.y, vAngles.z,
fFov, m_fMaxViewDist, m_fFogFarDist);
return true;
}
return false;
}
void C3DEngine::Update()
{
m_bProfilerEnabled = GetISystem()->GetIProfileSystem()->IsProfiling();
m_configSpec = GetISystem()->GetConfigSpec();
m_LightConfigSpec = (ESystemConfigSpec)GetCurrentLightSpec();
/// if(m_pVisAreaManager)
// m_pVisAreaManager->Preceche(m_pObjManager);
}
//////////////////////////////////////////////////////////////////////
void C3DEngine::UpdateScene(bool bAddStaticLights, bool bAlwaysAddSun)
{
if(IsCameraAnd3DEngineInvalid(GetViewCamera(), "C3DEngine::Update"))
return;
Vec3d vTerrainColor = GetSystem()->GetI3DEngine()->GetWorldColor();//*GetSystem()->GetI3DEngine()->GetWorldBrightnes();
GetRenderer()->EF_SetWorldColor(vTerrainColor[0],vTerrainColor[1],vTerrainColor[2],1);
if( bAlwaysAddSun || (GetCVars()->e_sun && IsOutdoorVisible() && m_pObjManager && m_pVisAreaManager) )
{
// Add sun lsource
CDLight DynLight;
// memset(&DynLight, 0, sizeof(CDLight));
DynLight.m_Origin = GetSunPosition();//Vec3d(0, -5000.0f, 5000.0f);
DynLight.m_fRadius = 100000000;
DynLight.m_Color = GetSunColor();
DynLight.m_Color.r *= GetWorldColor().x;
DynLight.m_Color.g *= GetWorldColor().y;
DynLight.m_Color.b *= GetWorldColor().z;
DynLight.m_SpecColor= GetSunColor();
DynLight.m_SpecColor.r *= GetWorldColor().x;
DynLight.m_SpecColor.g *= GetWorldColor().y;
DynLight.m_SpecColor.b *= GetWorldColor().z;
DynLight.m_Flags |= DLF_DIRECTIONAL | DLF_SUN | DLF_THIS_AREA_ONLY | DLF_LM | DLF_CASTSHADOW_MAPS;
if(GetCVars()->e_sun_stencil)
DynLight.m_Flags |= DLF_CASTSHADOW_VOLUME;
for(int i=0; i<GetCVars()->e_sun; i++)
AddDynamicLightSource(DynLight,(IEntityRender*)-1);
}
if(bAddStaticLights)
UpdateStaticLightSources();
LightSourcesDebug();
if(m_pObjManager && m_pTerrain)
m_pTerrain->SetCBuffer(m_pObjManager->m_pCoverageBuffer);
m_bTerrainLightMapGenError = false;
}
//////////////////////////////////////////////////////////////////////
void C3DEngine::ShutDown(bool bEditorMode)
{
if(GetRenderer() != GetSystem()->GetIRenderer())
GetSystem()->Error("Renderer was deallocated before I3DEngine::ShutDown() call");
// reinit console variables
// delete m_pCVars;
// m_pCVars = new CVars(m_pSystem);
GetLog()->Log("Removing lights ...");
for(int i=0; i<m_lstDynLights.Count(); i++)
{
CDLight * pLight = &m_lstDynLights[i];
FreeLightSourceComponents(pLight);
}
DeleteAllStaticLightSources();
GetLog()->Log("Deleting visareas ...");
delete m_pVisAreaManager;
m_pVisAreaManager = 0;
GetLog()->Log("Deleting terrain ...");
// list2<struct IEntityRender*> lstTerrainObjects;
// if(m_pTerrain)
// m_pTerrain->GetObjects(lstTerrainObjects);
delete m_pTerrain;
m_pTerrain=0;
GetLog()->Log("ObjManager shutdown ...");
delete m_pObjManager;
m_pObjManager=0;
GetRenderer()->DeleteLeafBuffer(m_pFogTopPlane);
m_pFogTopPlane=0;
SAFE_RELEASE(m_pSHSky);
}
//////////////////////////////////////////////////////////////////////
void C3DEngine::ActivateLight(const char *szName,bool bActivate)
{
assert(0);
// GetBuildingManager()->ActivateLight(szName,bActivate);
}
#ifdef WIN64
#pragma warning( push ) //AMD Port
#pragma warning( disable : 4311 )
#endif
//////////////////////////////////////////////////////////////////////
void C3DEngine::SetCamera(const CCamera &cam, bool bToTheScreen)
{
// if(GetCVars()->e_hires_screenshoot)
// return;
if(IsCameraAnd3DEngineInvalid(cam, "C3DEngine::SetCamera"))
return;
GetViewCamera() = cam;
// realtime skybox processing
if(GetCVars()->e_out_space)
{
const float fNearFarDistance = 64;
if(bToTheScreen)
{
GetViewCamera().SetZMin(DEFAULT_ZMIN);
GetViewCamera().SetZMax(fNearFarDistance*1.5f);
}
else
{
GetViewCamera().SetZMin(fNearFarDistance*0.75f);
GetViewCamera().SetZMax(DEFAULT_ZMAX);
m_fMaxViewDist = DEFAULT_ZMAX;
}
}
else if(GetViewCamera().GetZMax()>m_fMaxViewDist)
GetViewCamera().SetZMax(m_fMaxViewDist);
/*
Vec3d vPosTest(106,120,0);
vPosTest.z = GetWaterLevel(&vPosTest);
GetRenderer()->Draw3dBBox(vPosTest-Vec3d(0.05f,0.05f,0.05f),vPosTest+Vec3d(0.05f,0.05f,0.05f));
*/
// under water camera effects
// float fUnderWater = GetWaterLevel(&GetViewCamera().GetPos())-GetViewCamera().GetPos().z;
// int nRecursionLevel = (int)GetRenderer()->EF_Query(EFQ_RecurseLevel);
// float fZMin = GetViewCamera().GetZMin();
//if(fUnderWater>(-fZMin) && nRecursionLevel==0)
{
// modify camera pos
/* if(fUnderWater>-0.04f) // if very close to the water - jump 5sm down
GetViewCamera().SetPos(GetViewCamera().GetPos()-Vec3d(0,0,0.08f));
// set z near
if(fabs(fUnderWater)<fZMin)
GetViewCamera().SetZMin(fZMin*0.2f);
*/
// set animated fov
/*if(fUnderWater>0)
{
if(fUnderWater>1)
fUnderWater=1;
float k = 1.f+0.1f*(float)cry_sinf(2.f*GetTimer()->GetCurrTime())*fUnderWater;
// CCamera cam = GetViewCamera();
GetViewCamera().SetFov(gf_PI_DIV_2/(k*0.6f+0.4f));
GetViewCamera().SetProjRatio((600.f/800.f)*k);
}*/
}
//GetViewCamera().Init(GetRenderer()->GetWidth(), GetRenderer()->GetHeight(),
//GetViewCamera().GetFov(), m_fMaxViewDist, GetViewCamera().GetProjRatio(), GetViewCamera().GetZMin());
GetViewCamera().Init(GetRenderer()->GetWidth(), GetRenderer()->GetHeight(),
GetViewCamera().GetFov(), m_fMaxViewDist, 0, GetViewCamera().GetZMin());
GetViewCamera().Update();
GetRenderer()->SetCamera(GetViewCamera());
if (m_pTerrain && bToTheScreen)
{
m_pObjManager->m_fZoomFactor = 0.05f + 0.95f*(RAD2DEG(GetViewCamera().GetFov())/90.f);
m_pTerrain->m_fLodLFactor = m_pObjManager->m_fZoomFactor*m_pObjManager->m_fZoomFactor;
}
}
#ifdef WIN64
#pragma warning( pop ) //AMD Port
#endif
IStatObj * C3DEngine::MakeObject(const char * szFileName, const char * szGeomName,
EVertsSharing eVertsSharing,
bool bLoadAdditinalInfo, bool bKeepInLocalSpace)
{
if(!szFileName || !szFileName[0])
{
Warning( 0,0,"I3DEngine::MakeObject: filename is not specified");
return 0;
}
if(!m_pObjManager)
m_pObjManager = new CObjManager (this);
return m_pObjManager->MakeObject(szFileName, szGeomName, eVertsSharing, bLoadAdditinalInfo, bKeepInLocalSpace);
}
bool C3DEngine::ReleaseObject(IStatObj * pObject)
{
if(!m_pObjManager || !pObject)
return 0;
if(!m_pObjManager->ReleaseObject((CStatObj*)pObject))
{
GetLog()->Log("Warning: I3DEngine::ReleaseObject: Attempt to release invalid IStatObj pointer");
return false;
}
return true;
}
IStatObj* C3DEngine::MakeObject()
{
return new CStatObj();
}
void C3DEngine::RegisterEntity( IEntityRender* pEntityRS )
{
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
// if(strstr(pEntityRS->GetEntityClassName(),"Light"))
// int y=0;
#ifdef _DEBUG // crash test basically
const char * szClass = pEntityRS->GetEntityClassName();
const char * szName = pEntityRS->GetName();
if(!szName[0] && !szClass[0])
Warning(0,0,"C3DEngine::RegisterEntity: Entity undefined"); // do not register undefined objects
if(!_finite(pEntityRS->GetPos().x) || !_finite(pEntityRS->GetPos().y) || !_finite(pEntityRS->GetPos().z))
{
Warning(0,0,"Warning: C3DEngine::RegisterEntity: Entity position undefined: %s", szName);
return;
}
#endif
if(!GetCVars()->e_register_in_sectors)
return; // speed test
/*
ICryCharInstance * cmodel = pEntityRS->GetEntityCharacter(0);
if(cmodel && (cmodel->GetFlags() & CS_FLAG_DRAW_NEAR))
{
if(cmodel->GetFlags() & CS_FLAG_DRAW_MODEL)
int t=0;
}
*/
if(!pEntityRS->GetEntityRS())
return;
pEntityRS->GetRenderBBox(pEntityRS->m_vWSBoxMin, pEntityRS->m_vWSBoxMax);
assert(_finite(pEntityRS->m_vWSBoxMin.x) && _finite(pEntityRS->m_vWSBoxMin.y) && _finite(pEntityRS->m_vWSBoxMin.z));
assert(_finite(pEntityRS->m_vWSBoxMax.x) && _finite(pEntityRS->m_vWSBoxMax.y) && _finite(pEntityRS->m_vWSBoxMax.z));
pEntityRS->m_fWSRadius = GetDistance(pEntityRS->m_vWSBoxMin, pEntityRS->m_vWSBoxMax)*0.5f;
// if(!pEntityRS->GetEntityRS()->pOcclState)
// pEntityRS->GetEntityRS()->pOcclState = new OcclusionTestClient;
// if(pEntityRS->GetRndFlags()&ERF_SELECTED)
// int iww=0;
if(!(pEntityRS->GetRndFlags()&ERF_OUTDOORONLY) && // do not find vis area if this flag is not set
m_pVisAreaManager && m_pVisAreaManager->SetEntityArea(pEntityRS))
return;
assert(m_pTerrain == m_pObjManager->m_pTerrain);
if(m_pObjManager)
m_pObjManager->RegisterEntity(pEntityRS);
}
bool C3DEngine::UnRegisterEntity( IEntityRender* pEntityRS )
{
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
if(!GetCVars()->e_register_in_sectors)
return true; // speed test
#ifdef _DEBUG // crash test basically
const char * szClass = pEntityRS->GetEntityClassName();
const char * szName = pEntityRS->GetName();
if(!szName[0] && !szClass[0])
Warning(0,0,"C3DEngine::RegisterEntity: Entity undefined"); // do not register undefined objects
#endif
bool bFound = false;
if(m_pObjManager && m_pVisAreaManager)
bFound |= m_pVisAreaManager->UnRegisterEntity(pEntityRS);
if(m_pTerrain)
{
assert(m_pTerrain == m_pObjManager->m_pTerrain);
if(m_pObjManager && m_pTerrain == m_pObjManager->m_pTerrain)
bFound |= m_pObjManager->UnRegisterEntity(pEntityRS);
}
/*
#ifdef _DEBUG
if(pEntityRS->m_pSector || pEntityRS->m_pVisArea)
{
const char * szName = pEntityRS->GetName();
GetLog()->Log("Error: C3DEngine::UnRegisterEntity: Entity %s(ptr=%d) was not fully unregistered", szName, (int)pEntityRS);
assert(0);
}
if((m_pTerrain && m_pTerrain->UnRegisterInAllSectors(pEntityRS)) ||
(m_pVisAreaManager && m_pVisAreaManager->UnRegisterInAllSectors(pEntityRS)))
{
const char * szName = pEntityRS->GetName();
GetLog()->Log("Error: C3DEngine::UnRegisterEntity: Entity %s(ptr=%d) was found after unregistration", szName, (int)pEntityRS);
assert(0);
}
#endif
*/
return bFound;
}
bool C3DEngine::UnRegisterInAllSectors(IEntityRender * pEntityRS)
{
if(m_pObjManager && m_pVisAreaManager)
m_pVisAreaManager->UnRegisterEntity(pEntityRS);
if(m_pTerrain)
return m_pTerrain->UnRegisterInAllSectors(pEntityRS);
return 0;
}
void C3DEngine::SpawnParticles( const ParticleParams & SpawnParticleParams )
{
if(m_pPartManager)
m_pPartManager->Spawn( SpawnParticleParams,m_fMaxViewDist, m_pObjManager);
}
void C3DEngine::CreateDecal( const CryEngineDecalInfo& DecalInfo )
{
if(!GetCVars()->e_decals)
return;
// if(DecalInfo.nTid != 4276)
// return;
if(GetCVars()->e_decals == 2)
GetLog()->Log("Debug: C3DEngine::CreateDecal: Pos=(%.1f,%.1f,%.1f) Size=%.2f ObjName=%s nPartID=%d", DecalInfo.vPos.x, DecalInfo.vPos.y, DecalInfo.vPos.z, DecalInfo.fSize, DecalInfo.pDecalOwner ? DecalInfo.pDecalOwner->GetName() : "NULL", DecalInfo.nPartID);
if(DecalInfo.pDecalOwner)
if(DecalInfo.pDecalOwner->GetEntityCharacter(0) || DecalInfo.pDecalOwner->GetEntityCharacter(1))
{
ICryCharInstance* pChar = DecalInfo.pDecalOwner->GetEntityCharacter(0);
if(pChar)
{
CryEngineDecalInfo DecalLCS = DecalInfo;
Matrix44 matCharacter;
matCharacter.SetIdentity();
Vec3d vAngles = DecalInfo.pDecalOwner->GetAngles();
matCharacter=matCharacter*Matrix33::CreateRotationX( DEG2RAD(-vAngles.x) );
matCharacter=matCharacter*Matrix33::CreateRotationY( DEG2RAD(+vAngles.y) ); //IMPORTANT: radian-angle must be negated
matCharacter=matCharacter*Matrix33::CreateRotationZ( DEG2RAD(-vAngles.z) );
matCharacter.SetTranslationOLD (DecalInfo.pDecalOwner->GetPos());
Matrix44 matInvCharacter = GetInverted44(matCharacter);
DecalLCS.vPos = matInvCharacter.TransformPointOLD(DecalInfo.vPos);
DecalLCS.vHitDirection = matInvCharacter.TransformVectorOLD(DecalLCS.vHitDirection);
pChar->CreateDecal(DecalLCS);
}
}
// make decal on static entity component
if(m_pDecalManager)
{
CryEngineDecalInfo DecalInfoFixed = DecalInfo;
if(DecalInfo.pDecalOwner)
{ // try to find at least one marked to be visible static component
Matrix44 objMat, objMatInv;
int nPartID = DecalInfo.nPartID;
IStatObj * pEntObject = DecalInfo.pDecalOwner->GetEntityStatObj(nPartID, &objMat, true);
while(!pEntObject && nPartID<16)
{ // find first visible entity component
pEntObject = DecalInfo.pDecalOwner->GetEntityStatObj(++nPartID, &objMat, true);
}
if(!pEntObject)
return;
DecalInfoFixed.nPartID = nPartID;
}
m_pDecalManager->Spawn( DecalInfoFixed, m_fMaxViewDist, GetTerrain() );
}
}
ICryCharInstance * C3DEngine::MakeCharacter(const char * cid_file_name, unsigned int dwFlags)
{
ICryCharManager* pCharManager = GetSystem()->GetIAnimationSystem();
assert(pCharManager);
// NOTE: The returned class is not necessarily CryCharInstance. It can be AnimObject as well
return pCharManager->MakeCharacter(cid_file_name, dwFlags);
}
void C3DEngine::RemoveCharacter(ICryCharInstance * pCryCharInstance)
{
ICryCharManager* pCharManager = GetSystem()->GetIAnimationSystem();
if(pCryCharInstance && pCharManager)
pCharManager->RemoveCharacter(pCryCharInstance);
}
/*
float C3DEngine::GetDayTime(float fPrevDayTime)
{
if(fPrevDayTime)
{
float fDayTimeDiff = (GetCVars()->e_day_time - fPrevDayTime);
while(fDayTimeDiff>12)
fDayTimeDiff-=12;
while(fDayTimeDiff<-12)
fDayTimeDiff+=12;
fDayTimeDiff = (float)fabs(fDayTimeDiff);
return fDayTimeDiff;
}
return GetCVars()->e_day_time;
} */
void C3DEngine::SetWorldColorRatio(float fWorldColorRatio)
{
m_fWorldColorRatio = fWorldColorRatio;
}
float C3DEngine::GetWorldColorRatio()
{
return m_fWorldColorRatio;
}
Vec3d C3DEngine::GetWorldColor(bool bScaled)
{
if(bScaled)
{
//*
Vec3d color;
color = m_vWorldColorConst*m_fWorldColorRatio;
if(color.x > 1.0f)
color.x = 1.0f;
if(color.y > 1.0f)
color.y = 1.0f;
if(color.z > 1.0f)
color.z = 1.0f;
return color;
//*/
// return m_vWorldColorConst*m_fWorldColorRatio;
}
else
return m_vWorldColorConst;
}
void C3DEngine::SetWorldColor(Vec3d vColor)
{
m_vWorldColorConst = vColor;
}
void C3DEngine::SetOutdoorAmbientColor(Vec3d vColor)
{
if (m_pObjManager)
m_pObjManager->m_vOutdoorAmbientColor = vColor;
}
float C3DEngine::GetTerrainElevation(float x, float y)
{
return m_pTerrain ? m_pTerrain->GetZApr(x, y) : 0;
}
float C3DEngine::GetTerrainZ(int x, int y)
{
if(x<0 || y<0 || x>=CTerrain::GetTerrainSize() || y>=CTerrain::GetTerrainSize())
{
// GetLog()->Log("C3DEngine::GetTerrainZ: values out of range %d, %d, %d", (int)m_pTerrain, x, y);
return BOTTOM_LEVEL;
}
return m_pTerrain ? m_pTerrain->GetZ(x, y) : 0;
}
int C3DEngine::GetHeightMapUnitSize()
{
return CTerrain::GetHeightMapUnitSize();
}
int C3DEngine::GetTerrainSize()
{
return CTerrain::GetTerrainSize();
}
float C3DEngine::GetMaxViewDist()
{
return m_fMaxViewDist;
}
/*
bool C3DEngine::AddStaticObject(const char * szFileName, const Vec3d & vPos, const float fScale)
{
if(!m_pTerrain)
return 0;
return m_pTerrain->AddStaticObject(szFileName, vPos, fScale, m_pObjManager);
} */
bool C3DEngine::AddStaticObject(int nObjectID, const Vec3d & vPos, const float fScale, uchar ucBright)
{
if(!m_pTerrain)
return 0;
return m_pTerrain->AddStaticObject(nObjectID, vPos, fScale, m_pObjManager, ucBright);
}
bool C3DEngine::RemoveStaticObject(int nObjectID, const Vec3d & vPos)
{
if(!m_pTerrain)
return 0;
return m_pTerrain->RemoveStaticObject(nObjectID, vPos, m_pObjManager);
}
#ifdef WIN64
#pragma warning( push ) //AMD Port
#pragma warning( disable : 4311 )
#endif
bool C3DEngine::PhysicalizeStaticObject(void *pForeignData,int iForeignData,int iForeignFlags)
{
if (!m_pTerrain || !m_pObjManager)
return false;
int ix=(int)pForeignData&0xFF, iy=(int)pForeignData>>8&0xFF, iobj=(int)pForeignData>>16&0xFFFF;
return 0;//m_pObjManager->PhysicalizeStatObjInst( &m_pTerrain->m_arrSecInfoTable[ix][iy]->m_lstStatObjects[iobj], true );
}
#ifdef WIN64
#pragma warning( pop ) //AMD Port
#endif
void C3DEngine::RemoveAllStaticObjects()
{
if(!m_pTerrain)
return;
// m_pObjManager->DeletePhysicalEntitys();
m_pTerrain->RemoveAllStaticObjects();
}
int C3DEngine::GetTerrainSurfaceType(int x, int y)
{
if(m_pTerrain)
return m_pTerrain->GetSurfaceType(x,y);
return -1;
}
void C3DEngine::SetTerrainSurfaceType(int x, int y, int nType)
{
if(m_pTerrain)
m_pTerrain->SetSurfaceType(x,y,nType);
}
void C3DEngine::SetTerainHightMapBlock(int x1, int y1, int nSizeX, int nSizeY, ushort * TerrainBlock, ushort nUpdateMask)
{
if(m_pTerrain)
m_pTerrain->SetTerainHightMapBlock(x1, y1, nSizeX, nSizeY, TerrainBlock, nUpdateMask);
}
int C3DEngine::LockTerrainSectorTexture(int nSectorOriginX, int nSectorOriginY, int & nTexDim)
{
return m_pTerrain ? m_pTerrain->LockSectorTexture(nSectorOriginX, nSectorOriginY, nTexDim) : 0;
}
void C3DEngine::OnExplosion(Vec3d vPos, Vec3 vHitDir, float fRadius, int nTexID, bool bDeformTerrain)
{
if(vPos.x<0 || vPos.x>=CTerrain::GetTerrainSize())
return;
if(vPos.y<0 || vPos.y>=CTerrain::GetTerrainSize())
return;
// m_pBFManager->KillBF(vPos, fRadius);
// float fRadiusMinus = (vPos.z - GetTerrainZ((int)vPos.x,(int)vPos.y));
//if(fRadiusMinus < -1)
//return; // underground
// fRadius -= fRadiusMinus;
if(fRadius<=0)
return;
fRadius *= GetCVars()->e_explosion_scale;
// if(vPos.z <= GetWaterLevel())
// GetRenderer()->EF_AddSplash(vPos, EST_Water, fRadius);
//vPos+=Vec3d(1,1,0);
for(int x=int(vPos.x-fRadius); x<=int(vPos.x+fRadius)+1; x+=CTerrain::GetHeightMapUnitSize())
for(int y=int(vPos.y-fRadius); y<=int(vPos.y+fRadius)+1; y+=CTerrain::GetHeightMapUnitSize())
if(m_pTerrain->GetHoleSafe(x,y))
return;
bool bGroundBurnedOut = m_pTerrain->IsBurnedOut((int)vPos.x,(int)vPos.y);
float fHeight = (vPos.z - GetTerrainZ((int)vPos.x,(int)vPos.y));
if(m_pObjManager && !bGroundBurnedOut && fHeight>0 && fHeight<fRadius)
m_pTerrain->ExplodeTerrain(vPos,fRadius, m_pObjManager, bDeformTerrain);
list2<IEntityRender*> lstStaticsAround;
if(m_pTerrain)
m_pTerrain->GetObjectsAround(vPos, fRadius, &lstStaticsAround);
if(m_pVisAreaManager)
m_pVisAreaManager->GetObjectsAround(vPos, fRadius, &lstStaticsAround);
// make decals on the objects
for(int i=0; i<lstStaticsAround.Count(); i++)
{
CryEngineDecalInfo DecalInfo;
DecalInfo.vPos = vPos;
DecalInfo.vNormal = Vec3d(0,0,1);
DecalInfo.fSize = fRadius;//*0.6666f;
DecalInfo.fLifeTime = 120;
DecalInfo.nTid = nTexID;
DecalInfo.fAngle = float(rand()%36000)*0.01f;
DecalInfo.pDecalOwner = lstStaticsAround[i];
DecalInfo.nPartID = 0;
// DecalInfo.vHitDirection = ((vPos-GetViewCamera().GetPos()).GetNormalized()/*+vHitDir.GetNormalized()*/).GetNormalized();
DecalInfo.bAdjustPos = false;
CreateDecal( DecalInfo );
}
// make decal on the ground
if(!bGroundBurnedOut && fHeight<fRadius && fHeight>-0.5)
{
CryEngineDecalInfo DecalInfo;
DecalInfo.vPos = vPos - Vec3d(0,0,fHeight);
DecalInfo.vNormal = Vec3d(0,0,1);
DecalInfo.fSize = fRadius-fHeight;
DecalInfo.fLifeTime = 120;
DecalInfo.nTid = nTexID;
DecalInfo.fAngle = float(rand()%36000)*0.01f;
DecalInfo.bAdjustPos = false;
CreateDecal( DecalInfo );
}
}
void C3DEngine::SetSkyBox(const char * szSkyBoxShaderName)
{
SAFE_RELEASE(m_pSHSky);
m_pSHSky = szSkyBoxShaderName[0] ? GetRenderer()->EF_LoadShader(szSkyBoxShaderName, eSH_World) : NULL;
}
/*
int C3DEngine::GetMapPreviewTexID()
{
return (m_pTerrain && m_pTerrain->m_pMapPreviewTex) ? m_pTerrain->m_pMapPreviewTex->GetTextureID() : 0;
} */
void C3DEngine::SetScreenShader(const char * szShaderName)
{
if(szShaderName)
m_pSHFullScreenQuad = GetRenderer()->EF_LoadShader(szShaderName, eSH_World, EF_SYSTEM);
else
m_pSHFullScreenQuad = NULL;
}
void C3DEngine::SetMaxViewDistance(float fMaxViewDistance)
{
m_fMaxViewDist = fMaxViewDistance;
}
float C3DEngine::GetMaxViewDistance( )
{
return m_fMaxViewDist;
}
/*
void C3DEngine::SetFogParams(float fFogStart, float fFogEnd, Vec3d vFogColor)
{
m_fFogNearDist = fFogStart;
m_fFogFarDist = fFogEnd;
m_vFogColor = vFogColor;
} */
void C3DEngine::SetFogColor(const Vec3d& vFogColor)
{
m_vFogColor = vFogColor;
}
void C3DEngine::SetFogStart(const float fFogStart)
{
m_fFogNearDist = fFogStart;
}
void C3DEngine::SetFogEnd(const float fFogEnd)
{
m_fFogFarDist = fFogEnd;
}
Vec3d C3DEngine::GetFogColor( )
{
return m_vFogColor;
}
float C3DEngine::GetFogStart( )
{
return m_fFogNearDist;
}
float C3DEngine::GetFogEnd( )
{
return m_fFogFarDist;
}
/*
void C3DEngine::GetFogAndViewDistance(float & fFogStart, float & fFogEnd, Vec3d & vFogColor, float & fMaxViewDistance, bool bGetDefaultValues)
{
if(bGetDefaultValues)
{
fFogStart = m_fDefFogNearDist;
fFogEnd = m_fDefFogFarDist ;
vFogColor = m_vDefFogColor ;
fMaxViewDistance = m_fDefMaxViewDist;
}
else
{
fFogStart = m_fFogNearDist;
fFogEnd = m_fFogFarDist ;
vFogColor = m_vFogColor ;
fMaxViewDistance = m_fMaxViewDist;
}
} */
void C3DEngine::SetPhysMaterialEnumerator(IPhysMaterialEnumerator * pPhysMaterialEnumerator)
{
m_pPhysMaterialEnumerator = pPhysMaterialEnumerator;
}
IPhysMaterialEnumerator * C3DEngine::GetPhysMaterialEnumerator()
{
return m_pPhysMaterialEnumerator;
}
/*
IIndoorBase * C3DEngine::GetBuildingManager()
{
return 0;
} */
/*bool C3DEngine::IsPointInShadow(Vec3d vPos)
{
return m_pTerrain ? m_pTerrain->IsOnTheLight((int)vPos.x,(int)vPos.y)==0 : true;
} */
bool C3DEngine::IsPointInWater(Vec3d vPos)
{
// TODO: test indoors aslo
return vPos.z < GetWaterLevel(&vPos);
}
void C3DEngine::ApplyForceToEnvironment(Vec3d vPos, float fRadius, float fAmountOfForce)
{
if(m_pTerrain)
m_pTerrain->ApplyForceToEnvironment(vPos, fRadius, fAmountOfForce);
}
void BlurImage24(byte * pImage, int nSize, int nPassesNum)
{
#define DATA_TMP(_x,_y,_c) (pTemp [((_x)+nSize*(_y))*3+_c])
#define DATA_IMG(_x,_y,_c) (pImage[((_x)+nSize*(_y))*3+_c])
byte * pTemp = new byte [nSize*nSize*3];
for(int nPass=0; nPass<nPassesNum; nPass++)
{
memcpy(pTemp,pImage,nSize*nSize*3);
for(int x=1; x<nSize-1; x++)
for(int y=1; y<nSize-1; y++)
for(int c=0; c<3; c++)
{
float fVal = 0;
fVal += DATA_TMP(x,y,c);
fVal += DATA_TMP(x+1,y+1,c);
fVal += DATA_TMP(x-1,y+1,c);
fVal += DATA_TMP(x+1,y-1,c);
fVal += DATA_TMP(x-1,y-1,c);
DATA_IMG(x,y,c) = uchar(fVal*0.2f);
}
}
delete [] pTemp;
#undef DATA_IMG
#undef DATA_TMP
}
bool C3DEngine::MakeSectorLightMap(int nSectorOriginX, int nSectorOriginY, uchar * pImage, int nImageSize)
{
// reset to white
if(pImage)
for(int i=0; i<nImageSize*nImageSize*3; i++)
pImage[i] = 255;
if(!m_pTerrain)
return false;
// remove all lsources
while(m_lstDynLights.Count())
{
CDLight *pLight = &m_lstDynLights[0];
FreeLightSourceComponents(pLight);
m_lstDynLights.Delete(0);
}
// add sun lsource into light manager
UpdateScene(false,true);
// register sun in renderer
GetRenderer()->EF_ClearLightsList();
UpdateLightSources();
PrepareLightSourcesForRendering();
// only sun should be
int nRealLightsNum = ((C3DEngine*)Get3DEngine())->GetRealLightsNum();
assert(nRealLightsNum==1);
// increase frame id to help shadow map manager in renderer
unsigned short * pPtr2FrameID = (unsigned short *)GetRenderer()->EF_Query(EFQ_Pointer2FrameID);
if(pPtr2FrameID)
(*pPtr2FrameID)++;
if(nImageSize>GetRenderer()->GetWidth() || nImageSize>(float)GetRenderer()->GetHeight())
{
if(!m_bTerrainLightMapGenError)
Warning( 0,0,
"C3DEngine::MakeSectorLightMap: Requested image size is bigger than size of current renderer window."
"Please select lower resolution for terrain texture.");
m_bTerrainLightMapGenError = true;
return false;
}
if(!GetCVars()->e_shadow_maps)
{
m_bTerrainLightMapGenError = true;
return false;
}
GetLog()->Log("Building shadow map for sector %d-%d ... ", nSectorOriginX, nSectorOriginY);
GetRenderer()->BeginFrame();
{
GetRenderer()->ResetToDefault();
GetRenderer()->ClearDepthBuffer();
GetRenderer()->ClearColorBuffer(Vec3d(1,1,1));
GetRenderer()->SetClearColor(Vec3d(1,1,1));
GetRenderer()->SetViewport(0,0,nImageSize,nImageSize);
GetRenderer()->PushMatrix();
GetRenderer()->Set2DMode(true,int(CTerrain::GetSectorSize()),int(CTerrain::GetSectorSize()));
float fHalfPixelSize = (float(CTerrain::GetSectorSize())/nImageSize)*0.5f;
GetRenderer()->TranslateMatrix(-(float)nSectorOriginX-fHalfPixelSize, -(float)nSectorOriginY-fHalfPixelSize, 0);
{
for(int x=0; x<CTerrain::GetSectorsTableSize(); x++)
for(int y=0; y<CTerrain::GetSectorsTableSize(); y++)
{
CSectorInfo * pSecInfo = m_pTerrain->GetSecInfo(x*CTerrain::GetSectorSize(), y*CTerrain::GetSectorSize());
if(pSecInfo)
{
pSecInfo->ReleaseHeightMapVertBuffer();
pSecInfo->m_cGeometryMML=0;
pSecInfo->m_fDistance=0;
}
}
}
list2<struct IEntityRender*> lstAllEntities;
CSectorInfo * pSecInfo = m_pTerrain->GetSecInfo(nSectorOriginX, nSectorOriginY);
if(pSecInfo)
{
// setup vertex container
pSecInfo->m_cGeometryMML=0;
pSecInfo->m_fDistance=0;
// prepare terrain geometry
GetRenderer()->EF_StartEf();
pSecInfo->RenderSector(GetIdentityCCObject());
GetRenderer()->EF_EndEf3D(0);
GetRenderer()->ResetToDefault();
GetRenderer()->ClearDepthBuffer();
GetRenderer()->ClearColorBuffer(Vec3d(1,0,1));
GetRenderer()->SetClearColor(Vec3d(1,1,1));
// fill list with entities in this sector and neighbor sectors
if(pSecInfo)
{
lstAllEntities.AddList(pSecInfo->m_lstEntities[STATIC_ENTITIES]);
// get 2d bbox of sector
Vec3d vSecBoxMin( (float)pSecInfo->m_nOriginX,
(float)pSecInfo->m_nOriginY,0);
Vec3d vSecBoxMax( (float)pSecInfo->m_nOriginX+CTerrain::GetSectorSize(),
(float)pSecInfo->m_nOriginY+CTerrain::GetSectorSize(),512);
// get 2d bounds in sectors array
int min_x = (int)(((vSecBoxMin.x - 16.f)/CTerrain::GetSectorSize()));
int min_y = (int)(((vSecBoxMin.y - 16.f)/CTerrain::GetSectorSize()));
int max_x = (int)(((vSecBoxMax.x + 16.f)/CTerrain::GetSectorSize()));
int max_y = (int)(((vSecBoxMax.y + 16.f)/CTerrain::GetSectorSize()));
// limit bounds
if(min_x<0) min_x=0; else if(min_x>=CTerrain::GetSectorsTableSize()) min_x=CTerrain::GetSectorsTableSize()-1;
if(min_y<0) min_y=0; else if(min_y>=CTerrain::GetSectorsTableSize()) min_y=CTerrain::GetSectorsTableSize()-1;
if(max_x<0) max_x=0; else if(max_x>=CTerrain::GetSectorsTableSize()) max_x=CTerrain::GetSectorsTableSize()-1;
if(max_y<0) max_y=0; else if(max_y>=CTerrain::GetSectorsTableSize()) max_y=CTerrain::GetSectorsTableSize()-1;
list2<CSectorInfo*> lstTmpSectors;
lstTmpSectors.Add(m_pTerrain->m_arrSecInfoTable[0][0]);
for(int x=min_x; x<=max_x && x>=0 && x<=CTerrain::GetTerrainSize(); x++)
for(int y=min_y; y<=max_y && y>=0 && y<=CTerrain::GetTerrainSize(); y++)
{
CSectorInfo * pSectorInfo = m_pTerrain->m_arrSecInfoTable[x][y];
if(pSectorInfo != m_pTerrain->m_arrSecInfoTable[0][0])
lstTmpSectors.Add(pSectorInfo);
}
for(int s=0; s<lstTmpSectors.Count(); s++)
{
CSectorInfo * pSectorInfo = lstTmpSectors[s];
for(int e=0; e<pSectorInfo->m_lstEntities[STATIC_ENTITIES].Count(); e++)
{
IEntityRender * pEnt = pSectorInfo->m_lstEntities[STATIC_ENTITIES][e];
if(!(pEnt->GetRndFlags() & ERF_HIDDEN))
if(pEnt->GetRndFlags() & ERF_CASTSHADOWINTOLIGHTMAP)
if(!pEnt->GetEntityVisArea())
{
Vec3d vEntBoxMin,vEntBoxMax;
pEnt->GetRenderBBox(vEntBoxMin,vEntBoxMax);
Vec3d vRadius(pEnt->GetRenderRadius(),pEnt->GetRenderRadius(),pEnt->GetRenderRadius());
if(Overlap::AABB_AABB(AABB(vEntBoxMin,vEntBoxMax), AABB(vSecBoxMin-vRadius,vSecBoxMax+vRadius))
&& lstAllEntities.Find(pEnt)<0)
lstAllEntities.Add(pEnt);
}
}
}
}
GetLog()->LogPlus("%d casters found ... ", lstAllEntities.Count());
GetRenderer()->ResetToDefault();
GetRenderer()->ClearDepthBuffer();
GetRenderer()->ClearColorBuffer(Vec3d(1,0,1));
GetRenderer()->SetClearColor(Vec3d(1,1,1));
m_pObjManager->DrawAllShadowsOnTheGroundInSector(&lstAllEntities);
}
pSecInfo->m_cGeometryMML = 0;
pSecInfo->m_pCurShader = m_pTerrain->m_pTerrainEf;
GetRenderer()->Set2DMode(false,CTerrain::GetSectorSize(),CTerrain::GetSectorSize());
GetRenderer()->PopMatrix();
if(lstAllEntities.Count())
{
GetLog()->LogPlus("reading frame buffer ... ");
if(pImage)
GetRenderer()->ReadFrameBuffer(pImage, nImageSize, nImageSize, true, false);
bool bImageFound=false;
if(pImage)
for(int i=1; i<nImageSize*nImageSize*3; i++)
if(pImage[i]!=pImage[i-1])
bImageFound = true;
if(bImageFound && pImage)
{
GetLog()->LogPlus("blur image ... ");
BlurImage24(pImage, nImageSize, 1);
}
/* {
char sFileName[128];
snprintf(sFileName,128,"lmap-%d-%d.tga",nSectorOriginX, nSectorOriginY);
if(bImageFound)
GetRenderer()->SaveTga(pImage,24,nImageSize,nImageSize,sFileName,0);
else
remove(sFileName);
}*/
}
}
GetRenderer()->Update();
GetLog()->LogPlus("done");
return true;
}
float C3DEngine::GetDistanceToSectorWithWater()
{
CSectorInfo * pSectorInfo = NULL;
if(m_pTerrain)
pSectorInfo = m_pTerrain->GetSecInfo(GetViewCamera().GetPos());
return (pSectorInfo && (m_pTerrain->m_fDistanceToSectorWithWater > 0.1f))
? m_pTerrain->m_fDistanceToSectorWithWater : max(GetViewCamera().GetPos().z - GetWaterLevel(),0.1f);
}
void C3DEngine::SetSkyBoxAlpha(float fAlpha)
{
if(m_pRESky)
m_pRESky->m_fAlpha = fAlpha;
}
void C3DEngine::SetBFCount(int nCount)
{
Warning(0,0,"C3DEngine::SetBFCount: butterflies are not supported by 3dengine anymore, plz use boids entity instead");
// if(m_pBFManager)
// m_pBFManager->SetCount(nCount);
}
int C3DEngine::GetBFCount()
{
return 0;//m_pBFManager ? m_pBFManager->GetCount() : 0;
}
void C3DEngine::SetGrasshopperCGF( int nSlot, IStatObj * pStatObj )
{
GetLog()->Log("Warning: I3DEngine::SetGrasshopperCGF: Feature not supported anymore");
// if(m_pTerrain && m_pTerrain->m_pBugsManager)
// m_pTerrain->m_pBugsManager->SetCGF( nSlot, pStatObj );
}
void C3DEngine::SetGrasshopperCount(int nCount)
{
GetLog()->Log("Warning: I3DEngine::SetGrasshopperCount: Feature not supported anymore");
// if(m_pTerrain && m_pTerrain->m_pBugsManager)
// m_pTerrain->m_pBugsManager->SetCount(nCount);
}
int C3DEngine::GetGrasshopperCount()
{
GetLog()->Log("Warning: I3DEngine::GetGrasshopperCount: Feature not supported anymore");
return 0;//(m_pTerrain && m_pTerrain->m_pBugsManager) ? m_pTerrain->m_pBugsManager->GetCount() : 0;
}
Vec3d C3DEngine::GetOutdoorAmbientColor()
{
return m_pObjManager ? m_pObjManager->m_vOutdoorAmbientColor : Vec3d(0,0,0);
}
Vec3d C3DEngine::GetSunColor()
{
return m_pObjManager ? m_pObjManager->m_vSunColor : Vec3d(0,0,0);
}
Vec3d C3DEngine::GetSunPosition(bool bMoveUp)
{
if(bMoveUp)
{
Vec3d vSunPosition = m_vSunPosition;
vSunPosition.Normalize();
vSunPosition.z+=0.5f;
vSunPosition*=10000.0f;
return vSunPosition;
}
return m_vSunPosition;
}
Vec3d C3DEngine::GetAmbientColorFromPosition(const Vec3d & vPos, float fRadius)
{
if(m_pObjManager)
{
if(CVisArea * pVisArea = (CVisArea *)m_pVisAreaManager->GetVisAreaFromPos(vPos))
return pVisArea->m_vAmbColor+pVisArea->m_vDynAmbColor; // indooor
return m_pObjManager->m_vOutdoorAmbientColor;
}
return Vec3d(0,0,0); // undefined outdoor
}
uint C3DEngine::GetLightMaskFromPosition(const Vec3d & vPos, float fRadius)
{
// if(CVisArea * pVisArea = (CVisArea *)m_pVisAreaManager->GetVisAreaFromPos(vPos))
// return pVisArea->m_vAmbColor; // indooor
if(!m_pTerrain)
return 0;
if(fRadius > (float)CTerrain::GetSectorSize())
fRadius = (float)CTerrain::GetSectorSize();
CSectorInfo *pSectorInfo0 = m_pTerrain->GetSecInfo(vPos);
CSectorInfo *pSectorInfo1=0,*pSectorInfo2=0,*pSectorInfo3=0,*pSectorInfo4=0;
if (fRadius != 0)
{
pSectorInfo1 = m_pTerrain->GetSecInfo(vPos+Vec3d( fRadius, 0,0));
pSectorInfo2 = m_pTerrain->GetSecInfo(vPos+Vec3d( 0, fRadius,0));
pSectorInfo3 = m_pTerrain->GetSecInfo(vPos+Vec3d(-fRadius, 0,0));
pSectorInfo4 = m_pTerrain->GetSecInfo(vPos+Vec3d( 0,-fRadius,0));
}
uint nMask = 0;
if(GetRenderer()->EF_GetHeatVision())
{
nMask |= pSectorInfo0 ? pSectorInfo0->m_nDynLightMaskNoSun : 0;
nMask |= pSectorInfo1 ? pSectorInfo1->m_nDynLightMaskNoSun : 0;
nMask |= pSectorInfo2 ? pSectorInfo2->m_nDynLightMaskNoSun : 0;
nMask |= pSectorInfo3 ? pSectorInfo3->m_nDynLightMaskNoSun : 0;
nMask |= pSectorInfo4 ? pSectorInfo4->m_nDynLightMaskNoSun : 0;
}
else
{
nMask |= pSectorInfo0 ? pSectorInfo0->m_nDynLightMask : 0;
nMask |= pSectorInfo1 ? pSectorInfo1->m_nDynLightMask : 0;
nMask |= pSectorInfo2 ? pSectorInfo2->m_nDynLightMask : 0;
nMask |= pSectorInfo3 ? pSectorInfo3->m_nDynLightMask : 0;
nMask |= pSectorInfo4 ? pSectorInfo4->m_nDynLightMask : 0;
}
assert(nMask>=0);
if(!nMask)
{
nMask = GetFullLightMask();
// int nTmp = GetCVars()->e_max_entity_lights;
// GetCVars()->e_max_entity_lights = 8;
CheckDistancesToLightSources(nMask, vPos, fRadius);
//GetCVars()->e_max_entity_lights = nTmp;
}
return nMask;
}
bool C3DEngine::IsBoxVisibleOnTheScreen(const Vec3d & vBoxMin, const Vec3d & vBoxMax, OcclusionTestClient * pOcclusionTestClient )
{
// frustum test
if(!GetViewCamera().IsAABBVisibleFast( AABB(vBoxMin,vBoxMax) ))
return false;
// check visibility of outdoor sectors where this box is
// get 2d bounds in sectors array
int min_x = (int)(((vBoxMin.x - 1.f)/CTerrain::GetSectorSize()));
int min_y = (int)(((vBoxMin.y - 1.f)/CTerrain::GetSectorSize()));
int max_x = (int)(((vBoxMax.x + 1.f)/CTerrain::GetSectorSize()));
int max_y = (int)(((vBoxMax.y + 1.f)/CTerrain::GetSectorSize()));
if(min_x<0) min_x=0;
if(min_y<0) min_y=0;
if(max_x>=CTerrain::GetSectorsTableSize()) max_x = CTerrain::GetSectorsTableSize()-1;
if(max_y>=CTerrain::GetSectorsTableSize()) max_y = CTerrain::GetSectorsTableSize()-1;
// this test is valid only if entire bbox is in the map
if( min_x>=0 && max_x<CTerrain::GetSectorsTableSize() ||
min_y>=0 && max_y<CTerrain::GetSectorsTableSize() )
{ // if some sector was visible in last 5 sec - box is visible
for(int x=min_x; x<=max_x; x++)
for(int y=min_y; y<=max_y; y++)
{ // if some sector was visible in last 5 sec - box is visible
if(!GetCVars()->e_terrain ||
(GetTimer()->GetCurrTime() - m_pTerrain->m_arrSecInfoTable[x][y]->GetLastTimeUsed()) < 3.f)
{
if( pOcclusionTestClient )
{ // test terrain and objects (cbuffer) occlusion
float fDist = GetDistance( (vBoxMin + vBoxMax)*0.5f, GetViewCamera().GetPos());
if( m_pObjManager->IsBoxOccluded(vBoxMin,vBoxMax,fDist,pOcclusionTestClient) )
return false;
}
return true; // sector is visible
}
}
return false; // no sectors was rendered in last seconds
}
return true;
}
bool C3DEngine::IsSphereVisibleOnTheScreen(const Vec3d & vPos, const float fRadius, OcclusionTestClient * pOcclusionTestClient )
{
return IsBoxVisibleOnTheScreen(
vPos - Vec3d(fRadius,fRadius,fRadius),
vPos + Vec3d(fRadius,fRadius,fRadius),
pOcclusionTestClient );
}
IEntityRenderState * C3DEngine::MakeEntityRenderState()
{
return new IEntityRenderState;
}
void C3DEngine::FreeEntityRenderState(IEntityRender * pEntityRnd)
{
// GetLog()->Log("vlad: C3DEngine::FreeEntityRenderState: %d, %s", (int)(IEntityRender*)pEntityRnd, pEntityRnd->GetName());
/*
LightMapInfo * pLightMapInfo = (LightMapInfo *)pEntityRnd->GetLightMapInfo();
if(pLightMapInfo && pLightMapInfo->pLMTCBuffer)
GetRenderer()->ReleaseBuffer(pLightMapInfo->pLMTCBuffer);
*/
// TODO: Delete data here, or at a more appropiate place
// (currently done in CBrush::~CBrush(), hope that is 'a more appropiate place')
RemoveEntityLightSources(pEntityRnd);
if(m_pDecalManager)
m_pDecalManager->OnEntityDeleted(pEntityRnd);
if(m_pPartManager)
m_pPartManager->OnEntityDeleted(pEntityRnd);
GetRenderer()->OnEntityDeleted(pEntityRnd);
/*
#ifdef _DEBUG
UnRegisterInAllSectors(pEntityRnd);
#else*/
UnRegisterEntity(pEntityRnd);
//#endif
IEntityRenderState * pEntRendState = pEntityRnd->GetEntityRS();
if(!pEntRendState)
return;
if(pEntRendState->pShadowMapInfo)
{
pEntRendState->pShadowMapInfo->Release(pEntityRnd->GetEntityRenderType(), GetRenderer());
pEntRendState->pShadowMapInfo = NULL;
}
// check that was really unregistered
/* if(pEntityRnd->m_pSector)
for(int t=0; t<2; t++)
{
for(int e=0; e<pEntityRnd->m_pSector->m_lstEntities[t].Count(); e++)
{
if(pEntityRnd->m_pSector->m_lstEntities[t][e]->GetEntityRS() == pEntRendState)
{
assert(0); // UnRegisterInAllSectors do this already
pEntityRnd->m_pSector->m_lstEntities[t].Delete(e);
}
}
pEntityRnd->m_pSector->m_lstEntities[t].Delete(pEntityRnd);
}
pEntityRnd->m_pSector = 0;
*/
// delete occlusion client
/* for(int i=0; i<2; i++)
if(pEntRendState->pOcclState && pEntRendState->pOcclState->arrREOcclusionQuery[i])
{
pEntRendState->pOcclState->arrREOcclusionQuery[i]->Release();
pEntRendState->pOcclState->arrREOcclusionQuery[i] = 0;
}*/
// delete pEntRendState->pOcclState;
//pEntRendState->pOcclState = 0;
//todo: is it needed?
// pEntityRnd->m_pVisArea = 0;
delete pEntRendState;
pEntityRnd->GetEntityRS()=0;
}
#ifdef WIN64
#pragma warning( push ) //AMD Port
#pragma warning( disable : 4267 )
#endif
//////////////////////////////////////////////////////////
// checks whether the given file is a character file
// returns true if it is
//////////////////////////////////////////////////////////
bool C3DEngine::IsCharacterFile(const char * szCGFileName)
{
FILE * f = GetSystem()->GetIPak()->FOpen(szCGFileName,"rb");
if(!f)
return false;
//read the file header
FILE_HEADER fh;
int res = GetSystem()->GetIPak()->FRead(&fh,sizeof(fh),1,f);
if(res!=1)
{
GetSystem()->GetIPak()->FClose(f);
return false;
}
if(fh.Version != GeomFileVersion || fh.FileType != FileType_Geom)
{
GetSystem()->GetIPak()->FClose(f);
return false;
}
//read the chunk table
GetSystem()->GetIPak()->FSeek(f,fh.ChunkTableOffset,SEEK_SET);
int n_chunks;
res = GetSystem()->GetIPak()->FRead(&n_chunks,sizeof(n_chunks),1,f);
if(res!=1)
{
GetSystem()->GetIPak()->FClose(f);
return false;
}
CHUNK_HEADER * arrChunks = new CHUNK_HEADER [n_chunks];
res = GetSystem()->GetIPak()->FRead(arrChunks,sizeof(CHUNK_HEADER),n_chunks,f);
if(res!=n_chunks)
{
delete [] arrChunks;
GetSystem()->GetIPak()->FClose(f);
return false;
}
for(int i=0;i<n_chunks;i++)
{
switch (arrChunks[i].ChunkType)
{
case ChunkType_BoneNameList:
delete [] arrChunks;
GetSystem()->GetIPak()->FClose (f);
return true;
}
}
delete [] arrChunks;
GetSystem()->GetIPak()->FClose(f);
return false;
}
#ifdef WIN64
#pragma warning( pop ) //AMD Port
#endif
//////////////////////////////////////////////////////////////////////////
IParticleEmitter* C3DEngine::CreateParticleEmitter()
{
if (m_pPartManager)
return m_pPartManager->CreateEmitter();
return 0;
}
//////////////////////////////////////////////////////////////////////////
void C3DEngine::DeleteParticleEmitter(IParticleEmitter * pPartEmitter)
{
assert(pPartEmitter);
if (m_pPartManager)
m_pPartManager->DeleteEmitter(pPartEmitter);
}
const char * C3DEngine::GetLevelFilePath(const char * szFileName)
{
strcpy(m_sGetLevelFilePathTmpBuff, m_szLevelFolder);
strcat(m_sGetLevelFilePathTmpBuff, szFileName);
return m_sGetLevelFilePathTmpBuff;
}
ushort * C3DEngine::GetUnderWaterSmoothHMap(int & nDimensions)
{
return m_pTerrain ? m_pTerrain->GetUnderWaterSmoothHMap(nDimensions) : 0;
}
void C3DEngine::MakeUnderWaterSmoothHMap(int nWaterUnitSize)
{
if(m_pTerrain)
m_pTerrain->MakeUnderWaterSmoothHMap(nWaterUnitSize);
}
void C3DEngine::SetTerrainBurnedOut(int x, int y, bool bBurnedOut)
{
if(m_pTerrain)
{
m_pTerrain->SetBurnedOut(x, y, bBurnedOut);
// update vert buffers
CSectorInfo * pInfo = m_pTerrain->GetSecInfo(x,y);
if(pInfo)
pInfo->ReleaseHeightMapVertBuffer();
}
}
bool C3DEngine::IsTerrainBurnedOut(int x, int y)
{
return m_pTerrain ? m_pTerrain->IsBurnedOut(x, y) : 0;
}
void C3DEngine::UpdateDetailObjects()
{
if(m_pTerrain && m_pTerrain->m_pDetailObjects)
m_pTerrain->m_pDetailObjects->UpdateGrass();
}
int C3DEngine::GetTerrainSectorSize()
{
return m_pTerrain ? m_pTerrain->GetSectorSize() : 0;
}
void C3DEngine::AddWaterSplash (Vec3d vPos, eSplashType eST, float fForce, int Id=-1)
{
GetRenderer()->EF_AddSplash(vPos, eST, fForce, Id);
}
void C3DEngine::EnableHeatVision(bool bEnable)
{
GetRenderer()->EF_EnableHeatVision(bEnable);
}
void C3DEngine::ActivatePortal(const Vec3d &vPos, bool bActivate, IEntityRender *pEntity)
{
m_pVisAreaManager->ActivatePortal(vPos, bActivate, pEntity);
}
int C3DEngine::GetTerrainTextureDim()
{
return m_pTerrain ? m_pTerrain->GetTerrainTextureDim() : 0;
}
bool C3DEngine::SetStatInstGroup(int nGroupId, const IStatInstGroup & siGroup)
{
m_pObjManager->m_lstStaticTypes.PreAllocate(1024,1024);
if(nGroupId<0 || nGroupId>=m_pObjManager->m_lstStaticTypes.Count())
return false;
m_pObjManager->m_lstStaticTypes[nGroupId].pStatObj = (CStatObj*)siGroup.pStatObj;
if(siGroup.pStatObj)
siGroup.pStatObj->CheckValidVegetation();
m_pObjManager->m_lstStaticTypes[nGroupId].bHideability = siGroup.bHideability;
m_pObjManager->m_lstStaticTypes[nGroupId].bPhysNonColl = siGroup.bPhysNonColl;
m_pObjManager->m_lstStaticTypes[nGroupId].fBending = siGroup.fBending;
m_pObjManager->m_lstStaticTypes[nGroupId].bCastShadow = siGroup.bCastShadow;
m_pObjManager->m_lstStaticTypes[nGroupId].bRecvShadow = siGroup.bRecvShadow;
m_pObjManager->m_lstStaticTypes[nGroupId].bPrecShadow = siGroup.bPrecShadow;
m_pObjManager->m_lstStaticTypes[nGroupId].bUseAlphaBlending = siGroup.bUseAlphaBlending;
// m_pObjManager->m_lstStaticTypes[nGroupId].bTakeBrightnessFromLightBit = siGroup.bTakeBrightnessFromLightBit;
m_pObjManager->m_lstStaticTypes[nGroupId].fSpriteDistRatio = siGroup.fSpriteDistRatio;
m_pObjManager->m_lstStaticTypes[nGroupId].fShadowDistRatio = siGroup.fShadowDistRatio;
m_pObjManager->m_lstStaticTypes[nGroupId].fMaxViewDistRatio = siGroup.fMaxViewDistRatio;
m_pObjManager->m_lstStaticTypes[nGroupId].fBrightness = siGroup.fBrightness;
m_pObjManager->m_lstStaticTypes[nGroupId].bUpdateShadowEveryFrame = siGroup.bUpdateShadowEveryFrame;
// m_pObjManager->m_lstStaticTypes[nGroupId].fAmbScale = siGroup.fAmbScale;
m_pObjManager->m_lstStaticTypes[nGroupId].nSpriteTexRes = siGroup.nSpriteTexRes;
m_pObjManager->m_lstStaticTypes[nGroupId].pMaterial = siGroup.pMaterial;
m_pObjManager->m_lstStaticTypes[nGroupId].fBackSideLevel = siGroup.fBackSideLevel;
m_pObjManager->m_lstStaticTypes[nGroupId].bCalcLighting = siGroup.bCalcLighting;
m_pObjManager->m_lstStaticTypes[nGroupId].bUseSprites = siGroup.bUseSprites;
m_pObjManager->m_lstStaticTypes[nGroupId].bFadeSize = siGroup.bFadeSize;
m_pObjManager->m_lstStaticTypes[nGroupId].SetRndFlags();
return true;
}
bool C3DEngine::GetStatInstGroup(int nGroupId, IStatInstGroup & siGroup)
{
if(nGroupId<0 || nGroupId>=m_pObjManager->m_lstStaticTypes.Count())
return false;
siGroup.pStatObj = m_pObjManager->m_lstStaticTypes[nGroupId].pStatObj;
siGroup.bHideability = m_pObjManager->m_lstStaticTypes[nGroupId].bHideability;
siGroup.bPhysNonColl = m_pObjManager->m_lstStaticTypes[nGroupId].bPhysNonColl;
siGroup.fBending = m_pObjManager->m_lstStaticTypes[nGroupId].fBending;
siGroup.bCastShadow = m_pObjManager->m_lstStaticTypes[nGroupId].bCastShadow;
siGroup.bRecvShadow = m_pObjManager->m_lstStaticTypes[nGroupId].bRecvShadow;
siGroup.bPrecShadow = m_pObjManager->m_lstStaticTypes[nGroupId].bPrecShadow;
siGroup.bUseAlphaBlending = m_pObjManager->m_lstStaticTypes[nGroupId].bUseAlphaBlending;
// siGroup.bTakeBrightnessFromLightBit = m_pObjManager->m_lstStaticTypes[nGroupId].bTakeBrightnessFromLightBit;
siGroup.fSpriteDistRatio = m_pObjManager->m_lstStaticTypes[nGroupId].fSpriteDistRatio;
siGroup.fShadowDistRatio = m_pObjManager->m_lstStaticTypes[nGroupId].fShadowDistRatio;
siGroup.fMaxViewDistRatio = m_pObjManager->m_lstStaticTypes[nGroupId].fMaxViewDistRatio;
siGroup.fBrightness = m_pObjManager->m_lstStaticTypes[nGroupId].fBrightness;
siGroup.bUpdateShadowEveryFrame = m_pObjManager->m_lstStaticTypes[nGroupId].bUpdateShadowEveryFrame;
// siGroup.fAmbScale = m_pObjManager->m_lstStaticTypes[nGroupId].fAmbScale;
siGroup.nSpriteTexRes = m_pObjManager->m_lstStaticTypes[nGroupId].nSpriteTexRes;
siGroup.pMaterial = m_pObjManager->m_lstStaticTypes[nGroupId].pMaterial;
siGroup.fBackSideLevel = m_pObjManager->m_lstStaticTypes[nGroupId].fBackSideLevel;
siGroup.bCalcLighting = m_pObjManager->m_lstStaticTypes[nGroupId].bCalcLighting;
siGroup.bUseSprites = m_pObjManager->m_lstStaticTypes[nGroupId].bUseSprites;
return true;
}
void C3DEngine::GetMemoryUsage(class ICrySizer * pSizer)
{
if (!pSizer->Add(*this))
return; // we've already added this object
{
SIZER_COMPONENT_NAME(pSizer, "Particles");
if(m_pPartManager)
m_pPartManager->GetMemoryUsage(pSizer);
}
pSizer->AddContainer(m_lstDynLights);
{
// SIZER_COMPONENT_NAME(pSizer, "BFlies");
// pSizer->AddObject(m_pBFManager, m_pBFManager->GetMemoryUsage());
}
if(m_pConnectivityBuilder)
{
SIZER_COMPONENT_NAME(pSizer, "EdgeConnectivityBuilder");
m_pConnectivityBuilder->GetMemoryUsage(pSizer);
}
pSizer->AddObject(m_pCVars, sizeof(CVars));
if(m_pDecalManager)
{
SIZER_COMPONENT_NAME(pSizer, "DecalManager");
m_pDecalManager->GetMemoryUsage(pSizer);
pSizer->AddObject(m_pDecalManager, sizeof(*m_pDecalManager));
}
if(m_pShadowEdgeDetector)
{
SIZER_COMPONENT_NAME(pSizer, "ShadowEdgeDetector");
m_pShadowEdgeDetector->GetMemoryUsage(pSizer);
pSizer->AddObject(m_pShadowEdgeDetector, sizeof(*m_pShadowEdgeDetector));
}
if(m_pObjManager)
{
SIZER_COMPONENT_NAME(pSizer, "ObjManager");
pSizer->AddObject(m_pObjManager, sizeof(*m_pObjManager) + m_pObjManager->GetMemoryUsage(pSizer));
}
if (m_pTerrain)
{
SIZER_COMPONENT_NAME(pSizer, "Terrain");
m_pTerrain->GetMemoryUsage(pSizer);
}
if (m_pVisAreaManager)
{
SIZER_COMPONENT_NAME(pSizer, "VisAreas");
m_pVisAreaManager->GetMemoryUsage(pSizer);
}
}
float C3DEngine::GetWaterLevel(IEntityRender * pEntityRender, Vec3d * pvFlowDir)
{
// const char * pName = pEntityRender->GetEntityClassName();
if (pEntityRender && m_pObjManager && m_pObjManager->m_pCWaterVolumes && m_pObjManager->m_pTerrain)
{
IPhysicalEntity *pent = pEntityRender->GetPhysics();
pe_params_bbox pbb;
Vec3d pos;
if (pent && pent->GetParams(&pbb))
pos = (pbb.BBox[0]+pbb.BBox[1])*0.5f;
else
pos = pEntityRender->GetPos();
float fWaterVolumeLevel = m_pObjManager->m_pCWaterVolumes->GetWaterVolumeLevelFor2DPoint(pos, pvFlowDir);
return max(fWaterVolumeLevel, pEntityRender->GetEntityVisArea() ? WATER_LEVEL_UNKNOWN : m_pObjManager->m_pTerrain->GetWaterLevel());
}
if(m_pObjManager && m_pObjManager->m_pTerrain && pEntityRender && !pEntityRender->GetEntityVisArea())
return m_pObjManager->m_pTerrain->GetWaterLevel();
return WATER_LEVEL_UNKNOWN;
}
float C3DEngine::GetWaterLevel(const Vec3d * pvPos, Vec3d * pvFlowDir)
{
IVisArea * pArea = (pvPos && m_pVisAreaManager) ? m_pVisAreaManager->GetVisAreaFromPos(*pvPos) : 0;
if(m_pObjManager && pvPos && m_pObjManager->m_pCWaterVolumes && m_pObjManager->m_pTerrain)
{
float fWaterVolumeLevel = m_pObjManager->m_pCWaterVolumes->GetWaterVolumeLevelFor2DPoint(*pvPos, pvFlowDir);
return max(fWaterVolumeLevel, pArea ? WATER_LEVEL_UNKNOWN : m_pObjManager->m_pTerrain->GetWaterLevel());
}
if(m_pObjManager && m_pObjManager->m_pTerrain && !pArea)
return m_pObjManager->m_pTerrain->GetWaterLevel();
return WATER_LEVEL_UNKNOWN;
}
IWaterVolume * C3DEngine::CreateWaterVolume()
{
if(!m_pObjManager->m_pCWaterVolumes)
m_pObjManager->m_pCWaterVolumes = new CWaterVolumeManager();
if(m_pObjManager && m_pObjManager->m_pCWaterVolumes)
return m_pObjManager->m_pCWaterVolumes->CreateWaterVolume();
return 0;
}
void C3DEngine::DeleteWaterVolume(IWaterVolume * pWaterVolume)
{
if(m_pObjManager && m_pObjManager->m_pCWaterVolumes)
m_pObjManager->m_pCWaterVolumes->DeleteWaterVolume(pWaterVolume);
}
IWaterVolume * C3DEngine::FindWaterVolumeByName(const char * szName)
{
if(m_pObjManager && m_pObjManager->m_pCWaterVolumes)
return m_pObjManager->m_pCWaterVolumes->FindWaterVolumeByName(szName);
return 0;
}
IVisArea * C3DEngine::CreateVisArea()
{
return m_pObjManager ? m_pVisAreaManager->CreateVisArea() : 0;
}
void C3DEngine::DeleteVisArea(IVisArea * pVisArea)
{
if(!m_pVisAreaManager->IsValidVisAreaPointer((CVisArea*)pVisArea))
{
Warning( 0,0,"I3DEngine::DeleteVisArea: Invalid VisArea pointer");
return;
}
if(m_pObjManager)
{
((CVisArea*)pVisArea)->UnmakeAreaBrush();
list2<IEntityRender*> lstEntitiesInArea;
lstEntitiesInArea.AddList(((CVisArea*)pVisArea)->m_lstEntities[DYNAMIC_ENTITIES]);
lstEntitiesInArea.AddList(((CVisArea*)pVisArea)->m_lstEntities[STATIC_ENTITIES]);
for(int i=0; i<lstEntitiesInArea.Count(); i++)
Get3DEngine()->UnRegisterEntity(lstEntitiesInArea[i]);
assert(((CVisArea*)pVisArea)->m_lstEntities[STATIC_ENTITIES].Count()==0);
assert(((CVisArea*)pVisArea)->m_lstEntities[DYNAMIC_ENTITIES].Count()==0);
m_pVisAreaManager->DeleteVisArea((CVisArea*)pVisArea);
for(int i=0; i<lstEntitiesInArea.Count(); i++)
Get3DEngine()->RegisterEntity(lstEntitiesInArea[i]);
if(m_pObjManager->m_pCWaterVolumes)
m_pObjManager->m_pCWaterVolumes->UpdateWaterVolumeVisAreas();
}
}
void C3DEngine::UpdateVisArea(IVisArea * pVisArea,
const Vec3d * pPoints, int nCount,
const char * szName, float fHeight,
const Vec3d & vAmbientColor,
bool bAfectedByOutLights,
bool bSkyOnly, const Vec3 & vDynAmbientColor,
float fViewDistRatio, bool bDoubleSide, bool bUseDeepness, bool bUseInIndoors )
{
if(!m_pObjManager)
return;
CVisArea * pArea = (CVisArea*)pVisArea;
GetLog()->Log("C3DEngine::UpdateVisArea: %s", szName);
Vec3d vTotalBoxMin = pArea->m_vBoxMin;
Vec3d vTotalBoxMax = pArea->m_vBoxMax;
m_pVisAreaManager->UpdateVisArea((CVisArea*)pVisArea, pPoints, nCount, szName, fHeight, vAmbientColor, bAfectedByOutLights, bSkyOnly, m_pTerrain, vDynAmbientColor, fViewDistRatio, bDoubleSide, bUseDeepness, bUseInIndoors);
if(pArea->m_lstEntities[STATIC_ENTITIES].Count() || pArea->m_lstEntities[DYNAMIC_ENTITIES].Count())
{
// merge old and new bboxes
vTotalBoxMin.CheckMin(pArea->m_vBoxMin);
vTotalBoxMax.CheckMax(pArea->m_vBoxMax);
}
else
{
vTotalBoxMin = pArea->m_vBoxMin;
vTotalBoxMax = pArea->m_vBoxMax;
}
// if(strstr(szName, "VisArea8"))
// int y=0;
m_pObjManager->ReregisterEntitiesInArea(vTotalBoxMin - Vec3d(8,8,8), vTotalBoxMax + Vec3d(8,8,8));
if(m_pObjManager->m_pCWaterVolumes)
m_pObjManager->m_pCWaterVolumes->UpdateWaterVolumeVisAreas();
}
int C3DEngine::GetFogVolumeIdFromBBox(const Vec3d & vBoxMin, const Vec3d & vBoxMax)
{
for(int f=0; f<m_pTerrain->m_lstFogVolumes.Count(); f++)
{
const Vec3d & vVolMin = m_pTerrain->m_lstFogVolumes[f].vBoxMin;
const Vec3d & vVolMax = m_pTerrain->m_lstFogVolumes[f].vBoxMax;
if(vVolMax.x>vBoxMin.x && vBoxMax.x>vVolMin.x)
if(vVolMax.y>vBoxMin.y && vBoxMax.y>vVolMin.y)
if(vVolMax.z>vBoxMin.z && vBoxMax.z>vVolMin.z)
{
return m_pTerrain->m_lstFogVolumes[f].nRendererVolumeID;
}
}
return 0;
}
void C3DEngine::ResetParticlesAndDecals( )
{
if(m_pPartManager)
m_pPartManager->Reset();
if(m_pDecalManager)
m_pDecalManager->Reset();
if(GetSystem()->GetIAnimationSystem())
GetSystem()->GetIAnimationSystem()->ClearDecals();
}
IEntityRender * C3DEngine::CreateEntityRender()
{
CBrush * pBrush = new CBrush();
m_pObjManager->m_lstBrushContainer.Add(pBrush);
return pBrush;
}
IEntityRender * C3DEngine::CreateVegetation()
{
CStatObjInst * pVeget = new CStatObjInst();
m_pObjManager->m_lstVegetContainer.Add(pVeget);
return pVeget;
}
void C3DEngine::DeleteEntityRender(IEntityRender * pEntityRender)
{
UnRegisterEntity(pEntityRender);
m_pObjManager->m_lstBrushContainer.Delete((CBrush*)pEntityRender);
m_pObjManager->m_lstVegetContainer.Delete((CStatObjInst*)pEntityRender);
delete pEntityRender;
}
void C3DEngine::DrawRain()
{
Vec3d vWindDir = m_vWindForce;
vWindDir.z = -16.f - GetCVars()->e_rain_amount*16.f;
if(m_pRainManager && m_pTerrain)
m_pRainManager->Render(m_pTerrain, m_vFogColor, m_pObjManager, m_pPartManager, vWindDir);
}
void C3DEngine::SetRainAmount( float fAmount )
{
GetCVars()->e_rain_amount = max(min(1.f,fAmount),0);
}
void C3DEngine::SetWindForce( const Vec3d & vWindForce )
{
m_vWindForce = vWindForce;
}
float C3DEngine::GetAmbientLightAmountForEntity(IEntityRender * pEntity)
{
Vec3d vColor(0,0,0);
if(pEntity && pEntity->GetEntityVisArea())
vColor = ((CVisArea*)pEntity->GetEntityVisArea())->m_vAmbColor;
else if(m_pObjManager)
vColor = m_pObjManager->m_vOutdoorAmbientColor;
vColor.x *= m_vWorldColorConst.x;
vColor.y *= m_vWorldColorConst.y;
vColor.z *= m_vWorldColorConst.z;
return (vColor.x + vColor.y + vColor.z)*0.3333f;
}
float C3DEngine::GetLightAmountForEntity(IEntityRender * pEntity, bool bOnlyVisibleLights)
{
Vec3d vLightAmount(0,0,0);
uint dwDLightMask = (uint)-1; // check all lights
CheckDistancesToLightSources(dwDLightMask, pEntity->GetPos(), 1, pEntity, 16, 0, 0, &vLightAmount);
float fLightAmount = (vLightAmount.x+vLightAmount.y+vLightAmount.z)*0.233f;
return min(1.f,fLightAmount);
}
IVisArea * C3DEngine::GetVisAreaFromPos(const Vec3d &vPos)
{
if(m_pObjManager && m_pVisAreaManager)
return m_pVisAreaManager->GetVisAreaFromPos(vPos);
return 0;
}
bool C3DEngine::IsVisAreasConnected(IVisArea * pArea1, IVisArea * pArea2, int nMaxRecursion, bool bSkipDisabledPortals)
{
if (pArea1==pArea2)
return (true); // includes the case when both pArea1 & pArea2 are NULL (totally outside)
// not considered by the other checks
if (!pArea1 || !pArea2)
return (false); // avoid a crash - better to put this check only
// here in one place than in all the places where this function is called
nMaxRecursion *= 2; // include portals since portals are the areas
if(m_pObjManager && m_pVisAreaManager)
return ((CVisArea*)pArea1)->FindVisArea((CVisArea*)pArea2, nMaxRecursion, bSkipDisabledPortals);
return false;
}
#ifdef GAMECUBE
#define CRY_GCRENDER_API __declspec(export)
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*voidfunctionptr) (void); // ptr to function returning void
__declspec(section ".init") extern voidfunctionptr _ctors[];
__declspec(section ".init") extern voidfunctionptr _dtors[];
void _prolog(void);
void _epilog(void);
void _unresolved(void);
#ifdef __cplusplus
}
#endif
//_prolog is the entrypoint to the module
// Called by the main application after the module is linked
// This executes the static constructors for the module.
// User code starts here.
CRY_GCRENDER_API void _prolog(void) {
// call static initializers
OSReport("Call Static Initializers\n");
voidfunctionptr *constructor;
for (constructor = _ctors; *constructor; constructor++) {
(*constructor)();
}
}
// _epilog is called before the the module is unlinked
// This executes the static destructors for the module.
CRY_GCRENDER_API void _epilog(void) {
voidfunctionptr *destructor;
for (destructor = _dtors; *destructor; destructor++) {
(*destructor)();
}
}
// _unresolved is called if a module attempts
// to call a symbol that is not present in another module.
// If _unresolved is not specified, the branch to the symbol
// will instead branch back to itself.
CRY_GCRENDER_API void _unresolved(void) {
u32 i;
u32* p;
OSReport("\nError: Unlinked function called in module %s.\n", __FILE__);
OSReport("Address: Back Chain LR Save\n");
for (i = 0, p = (u32*) OSGetStackPointer(); // get current sp
p && (u32) p != 0xffffffff && i++ < 16;
p = (u32*) *p) // get caller sp
{
OSReport("0x%08x: 0x%08x 0x%08x\n", p, p[0], p[1]);
}
OSReport("\n");
}
#endif //GAMECUBE
bool C3DEngine::IsOutdoorVisible()
{
if(m_pVisAreaManager)
return m_pVisAreaManager->IsOutdoorAreasVisible();
return false;
}
void C3DEngine::EnableOceanRendering(bool bOcean, bool bShore)
{
m_bOcean = bOcean;
m_bShore = bShore;
}
IMatInfo * C3DEngine::CreateMatInfo()
{
return m_pMatMan ? m_pMatMan->CreateMatInfo() : 0;
}
void C3DEngine::DeleteMatInfo(IMatInfo * pMatInfo)
{
m_pMatMan->DeleteMatInfo(pMatInfo);
}
void C3DEngine::RenameMatInfo( IMatInfo *pMtl,const char *sNewName )
{
m_pMatMan->RenameMatInfo(pMtl,sNewName);
}
IMatInfo* C3DEngine::FindMaterial( const char *sMaterialName )
{
return m_pMatMan->FindMatInfo( sMaterialName );
}
//////////////////////////////////////////////////////////////////////////
ILMSerializationManager * C3DEngine::CreateLMSerializationManager()
{
return new CLMSerializationManager2();
}
bool C3DEngine::IsOutdoorsVisible()
{
return (m_pObjManager && m_pVisAreaManager) ?
m_pVisAreaManager->IsOutdoorAreasVisible() : false;
}
bool C3DEngine::IsTerainHightMapModifiedByGame()
{
return m_pTerrain ? m_pTerrain->m_bHightMapModified : 0;
}
bool C3DEngine::IsPotentiallyVisible(IEntityRender * pEntityRender, float fAdditionalRadius )
{
if(!pEntityRender->GetEntityRS())
return false;
IVisArea * pVisArea = (IVisArea *)pEntityRender->m_pVisArea;
if(pVisArea)
{ // object is in indoors - test vis of current visarea
if ((GetFrameID() - pVisArea->GetVisFrameId())<2)
return true; // visible
if (fAdditionalRadius > 0)
{ // test neighbours
IVisArea * Areas[64];
int nCount = pVisArea->GetVisAreaConnections(Areas,64);
for (int i=0; i<nCount; i++)
if((GetFrameID() - Areas[i]->GetVisFrameId())<2)
return true; // visible
}
return false; // no areas visible
}
else if(m_pTerrain)
{ // object is in outdoors - test vis of terrain sectors
if (!GetCVars()->e_terrain)
return false;
Vec3d vBoxMin,vBoxMax;
pEntityRender->GetRenderBBox(vBoxMin,vBoxMax);
// check visibility of outdoor sectors where this box is
// get 2d bounds in sectors array
// todo: use ready list of terrain sectors from entity itself
float fSizePlus = 8.f + fAdditionalRadius;
float fInvSectorSize = 1.0f / CTerrain::GetSectorSize();
int min_x = fastftol_positive( (vBoxMin.x - fSizePlus)*fInvSectorSize );
int min_y = fastftol_positive( (vBoxMin.y - fSizePlus)*fInvSectorSize );
int max_x = fastftol_positive( (vBoxMax.x + fSizePlus)*fInvSectorSize );
int max_y = fastftol_positive( (vBoxMax.y + fSizePlus)*fInvSectorSize );
// can not test outside of the map
// this test is valid only if entire bbox is in the map
if(min_x<0) return true;
if(min_y<0) return true;
if(max_x>=CTerrain::GetSectorsTableSize()) return true;
if(max_y>=CTerrain::GetSectorsTableSize()) return true;
// OcclusionTestClient * pOcclusionTestClient = 0;
float currTime = GetTimer()->GetCurrTime();
// if some sector was visible in last 2 sec - box is visible
for(int x=min_x; x<=max_x; x++)
for(int y=min_y; y<=max_y; y++)
{
if ((currTime - m_pTerrain->m_arrSecInfoTable[x][y]->GetLastTimeRendered()) < LAST_POTENTIALLY_VISIBLE_TIME)
{
/* if( pOcclusionTestClient )
{ // test terrain and objects occlusion
float fDist = GetDistance( (vBoxMin + vBoxMax)*0.5f, GetViewCamera().GetPos());
if( m_pObjManager->IsBoxOccluded(vBoxMin,vBoxMax,fDist,pOcclusionTestClient) )
return false;
}*/
return true; // sector is visible
}
}
return false; // no sectors was rendered in last seconds
}
else
return false; // no outdoors present
}
IEdgeConnectivityBuilder *C3DEngine::GetNewConnectivityBuilder( void )
{
assert(m_pConnectivityBuilder);
m_pConnectivityBuilder->Reinit();
return(m_pConnectivityBuilder);
}
//! creates a connectivity object that can be used to deserialize the connectivity data
IStencilShadowConnectivity *C3DEngine::NewConnectivity()
{
return new CStencilShadowConnectivity();
}
IEdgeConnectivityBuilder *C3DEngine::GetNewStaticConnectivityBuilder( void )
{
assert(m_pStaticConnectivityBuilder);
m_pStaticConnectivityBuilder->Reinit();
return(m_pStaticConnectivityBuilder);
}
IEdgeDetector *C3DEngine::GetEdgeDetector( void )
{
return(m_pShadowEdgeDetector);
}
void C3DEngine::UpdateBeaches()
{
if(m_pTerrain)
m_pTerrain->InitBeaches(true);
}
void C3DEngine::RestoreTerrainFromDisk()
{
if(m_pTerrain && m_pObjManager)
{
m_pTerrain->ResetTerrainVertBuffers();
m_pTerrain->LoadHighMap(GetLevelFilePath(HEIGHT_MAP_FILE_NAME), GetSystem()->GetIPak());
// m_pTerrain->LoadStatObjInstances();
// m_pObjManager->CreatePhysicalEntitys();
}
ResetParticlesAndDecals( );
}
void C3DEngine::CheckPhysicalized(const Vec3d & vBoxMin, const Vec3d & vBoxMax)
{
if(!GetCVars()->e_stream_areas)
return;
CVisArea * pVisArea = (CVisArea *)GetVisAreaFromPos((vBoxMin+vBoxMax)*0.5f);
if(pVisArea)
{ // indoor
pVisArea->CheckPhysicalized();
IVisArea * arrConnections[16];
int nConections = pVisArea->GetRealConnections(arrConnections,16);
for(int i=0; i<nConections; i++)
((CVisArea*)arrConnections[i])->CheckPhysicalized();
}
else
{ // outdoor
CSectorInfo * arrSecInfo[] =
{
m_pTerrain->GetSecInfo(int(vBoxMin.x), int(vBoxMin.y)),
m_pTerrain->GetSecInfo(int(vBoxMax.x), int(vBoxMin.y)),
m_pTerrain->GetSecInfo(int(vBoxMin.x), int(vBoxMax.y)),
m_pTerrain->GetSecInfo(int(vBoxMax.x), int(vBoxMax.y))
};
for(int i=0; i<4; i++)
if(arrSecInfo[i])
arrSecInfo[i]->CheckPhysicalized();
}
}
void C3DEngine::CheckMemoryHeap()
{
assert (IsHeapValid());
}
void C3DEngine::RecompileBeaches()
{
if(m_pTerrain)
m_pTerrain->InitBeaches(true);
}
float C3DEngine::GetObjectsLODRatio()
{
return GetCVars()->e_obj_lod_ratio;
}
float C3DEngine::GetObjectsViewDistRatio()
{
return GetCVars()->e_obj_view_dist_ratio;
}
float C3DEngine::GetObjectsMinViewDist()
{
return GetCVars()->e_obj_min_view_dist;
}
bool C3DEngine::SetMaterialFloat( char * szMatName, int nSubMatId, int nTexSlot, char * szParamName, float fValue )
{
IMatInfo * pMatInfo = FindMaterial( szMatName );
if(!pMatInfo)
{ Warning(0,0,"I3DEngine::SetMaterialFloat: Material not found: %s", szMatName); return false; }
if(nSubMatId>0)
{
if(nSubMatId<=pMatInfo->GetSubMtlCount())
pMatInfo = pMatInfo->GetSubMtl(nSubMatId-1);
else
{
Warning(0,0,"I3DEngine::SetMaterialFloat: SubMaterial not found: %s, SubMatId: %d", szMatName, nSubMatId);
return false;
}
}
SEfResTexture * pTex = pMatInfo->GetShaderItem().m_pShaderResources->m_Textures[nTexSlot];
if(!pTex)
{ Warning(0,0,"I3DEngine::SetMaterialFloat: Texture slot not found: %s, TexSlot: %d", szMatName, nTexSlot); return false; }
char szM_Name[128] = "";
if(strncmp(szParamName,"m_", 2))
strncpy(szM_Name,"m_",sizeof(szM_Name));
strncat(szM_Name,szParamName,sizeof(szM_Name));
return pTex->m_TexModificator.SetMember(szM_Name,fValue);
}
void C3DEngine::CloseTerrainTextureFile()
{
if(m_pTerrain)
m_pTerrain->CloseTerrainTextureFile();
}
//////////////////////////////////////////////////////////////////////////
IParticleEffect* C3DEngine::CreateParticleEffect()
{
if (m_pPartManager)
return m_pPartManager->CreateEffect();
return 0;
}
//////////////////////////////////////////////////////////////////////////
void C3DEngine::DeleteParticleEffect( IParticleEffect* pEffect )
{
if (m_pPartManager)
m_pPartManager->RemoveEffect( pEffect );
}
//////////////////////////////////////////////////////////////////////////
IParticleEffect* C3DEngine::FindParticleEffect( const char *sEffectName )
{
if (m_pPartManager)
return m_pPartManager->FindEffect( sEffectName );
return 0;
}
int C3DEngine::GetLoadedObjectCount()
{
int nObjectsLoaded = m_pObjManager ? m_pObjManager->GetLoadedObjectCount() : 0;
if(GetSystem()->GetIAnimationSystem())
{
ICryCharManager::Statistics AnimStats;
GetSystem()->GetIAnimationSystem()->GetStatistics(AnimStats);
nObjectsLoaded += AnimStats.numAnimObjectModels + AnimStats.numCharModels;
}
return nObjectsLoaded;
}
void C3DEngine::DeleteEntityDecals(IEntityRender * pEntity)
{
if(m_pDecalManager && pEntity)
m_pDecalManager->OnEntityDeleted(pEntity);
}
void C3DEngine::OnLevelLoaded()
{
if(GetCVars()->e_precache_level)
{
UpdateLoadingScreen("\003Precaching level ... ");
/*
CCamera cam = GetViewCamera();
cam.SetPos(Vec3d(0,0,16));
cam.SetAngle(Vec3d(0,0,-90));
Get3DEngine()->SetCamera(cam);
GetRenderer()->BeginFrame();*/
if(m_pObjManager && m_pVisAreaManager)
m_pVisAreaManager->Preceche(m_pObjManager);
//GetRenderer()->Update();
UpdateLoadingScreenPlus("\003done");
}
/*
for(int x=0; x<C3DEngine::GetTerrainSize(); x+=GetTerrainSectorSize())
for(int y=0; y<C3DEngine::GetTerrainSize(); y+=GetTerrainSectorSize())
{
int nPosStride=0, nVertCount=0;
const char * pVerts = (const char *)C3DEngine::GetShoreGeometry(nPosStride, nVertCount, x, y);
for(int v=0 ;v<nVertCount && pVerts; v++)
{
Vec3d vPos = *((Vec3d*)&pVerts[nPosStride*v]);
assert(pVerts);
}
}*/
}
void C3DEngine::DeleteDecalsInRange( Vec3d vBoxMin, Vec3d vBoxMax, bool bDeleteBigTerrainDecals)
{
if(m_pDecalManager)
m_pDecalManager->DeleteDecalsInRange(vBoxMin, vBoxMax, bDeleteBigTerrainDecals);
}
const void * C3DEngine::GetShoreGeometry(int & nPosStride, int & nVertCount, int nSectorX, int nSectorY)
{
if(!this || !m_pTerrain)
return 0;
return m_pTerrain->GetShoreGeometry(nPosStride, nVertCount, nSectorX, nSectorY);
}
void C3DEngine::LockCGFResources()
{
if(m_pObjManager)
m_pObjManager->m_bLockCGFResources = true;
}
void C3DEngine::UnlockCGFResources()
{
if(m_pObjManager)
{
m_pObjManager->m_bLockCGFResources = false;
m_pObjManager->FreeNotUsedCGFs();
}
}
void IEntityRenderState::ShadowMapInfo::Release(enum EERType eEntType, struct IRenderer * pRenderer)
{
if(pShadowMapCasters)
{
pShadowMapCasters->Clear();
delete pShadowMapCasters;
pShadowMapCasters = 0;
}
if( pShadowMapFrustumContainer && eEntType != eERType_Vegetation ) // vegetations share same frustum allocated in CStatObj
{
delete pShadowMapFrustumContainer->m_LightFrustums.Get(0)->pEntityList;
pShadowMapFrustumContainer->m_LightFrustums.Get(0)->pEntityList=0;
delete pShadowMapFrustumContainer->m_LightFrustums.Get(0)->pModelsList;
pShadowMapFrustumContainer->m_LightFrustums.Get(0)->pModelsList=0;
delete pShadowMapFrustumContainer;
pShadowMapFrustumContainer=0;
}
if( pShadowMapFrustumContainerPassiveCasters && eEntType != eERType_Vegetation ) // vegetations share same frustum allocated in CStatObj
{
delete pShadowMapFrustumContainerPassiveCasters->m_LightFrustums.Get(0)->pEntityList;
pShadowMapFrustumContainerPassiveCasters->m_LightFrustums.Get(0)->pEntityList=0;
delete pShadowMapFrustumContainerPassiveCasters->m_LightFrustums.Get(0)->pModelsList;
pShadowMapFrustumContainerPassiveCasters->m_LightFrustums.Get(0)->pModelsList=0;
delete pShadowMapFrustumContainerPassiveCasters;
pShadowMapFrustumContainerPassiveCasters=0;
}
if(pShadowMapLeafBuffersList)
{
for(int i=0; i<pShadowMapLeafBuffersList->Count(); i++)
{
if(pShadowMapLeafBuffersList->GetAt(i))
{
pRenderer->DeleteLeafBuffer(pShadowMapLeafBuffersList->GetAt(i));
pShadowMapLeafBuffersList->GetAt(i)=0;
}
}
delete pShadowMapLeafBuffersList;
pShadowMapLeafBuffersList=0;
}
delete this;
}