//////////////////////////////////////////////////////////////////////////// // // 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("", 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; ie_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; iLog("Deleting visareas ..."); delete m_pVisAreaManager; m_pVisAreaManager = 0; GetLog()->Log("Deleting terrain ..."); // list2 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)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 && fHeightExplodeTerrain(vPos,fRadius, m_pObjManager, bDeformTerrain); list2 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-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; nPassEF_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; xGetSecInfo(x*CTerrain::GetSectorSize(), y*CTerrain::GetSectorSize()); if(pSecInfo) { pSecInfo->ReleaseHeightMapVertBuffer(); pSecInfo->m_cGeometryMML=0; pSecInfo->m_fDistance=0; } } } list2 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 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; sm_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; iLogPlus("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=0 && max_ye_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; em_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;iGetIPak()->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 lstEntitiesInArea; lstEntitiesInArea.AddList(((CVisArea*)pVisArea)->m_lstEntities[DYNAMIC_ENTITIES]); lstEntitiesInArea.AddList(((CVisArea*)pVisArea)->m_lstEntities[STATIC_ENTITIES]); for(int i=0; iUnRegisterEntity(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; iRegisterEntity(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; fm_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; iGetVisFrameId())<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; iCheckPhysicalized(); } 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; xDeleteDecalsInRange(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; iCount(); i++) { if(pShadowMapLeafBuffersList->GetAt(i)) { pRenderer->DeleteLeafBuffer(pShadowMapLeafBuffersList->GetAt(i)); pShadowMapLeafBuffersList->GetAt(i)=0; } } delete pShadowMapLeafBuffersList; pShadowMapLeafBuffersList=0; } delete this; }