This commit is contained in:
romkazvo
2023-08-07 19:29:24 +08:00
commit 34d6c5d489
4832 changed files with 1389451 additions and 0 deletions

View File

@@ -0,0 +1,620 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: statobjconstr.cpp
// Version: v1.00
// Created: 28/5/2001 by Vladimir Kajalin
// Compilers: Visual Studio.NET
// Description: creation
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "StatObj.h"
#include "MeshIdx.h"
#include "../RenderDll/Common/shadow_renderer.h"
#include <irenderer.h>
#include <CrySizer.h>
#include "objman.h"
float CStatObj::m_fStreamingTimePerFrame=0;
void CStatObj::FreeTriData()
{
delete m_pTriData;
m_pTriData=0;
}
const char * CStatObj::GetScriptMaterialName(int Id)
{
CLeafBuffer *lb = m_pLeafBuffer;
if (Id < 0)
{
for (int i=0; i<lb->m_pMats->Count(); i++)
{
if ((*lb->m_pMats)[i].sScriptMaterial[0])
return (*lb->m_pMats)[i].sScriptMaterial;
}
return NULL;
}
else
if (Id < lb->m_pMats->Count() && (*lb->m_pMats)[Id].sScriptMaterial[0])
return (*lb->m_pMats)[Id].sScriptMaterial;
return NULL;
}
void CStatObj::CalcRadiuses()
{
m_vBoxCenter = (m_vBoxMax+m_vBoxMin)*0.5f;
m_fObjectRadius = GetDistance(m_vBoxMin, m_vBoxMax)*0.5f;
float dxh = (float)max( fabs(GetBoxMax().x), fabs(GetBoxMin().x));
float dyh = (float)max( fabs(GetBoxMax().y), fabs(GetBoxMin().y));
m_fRadiusHors = (float)cry_sqrtf(dxh*dxh+dyh*dyh);
m_fRadiusVert = (GetBoxMax().z - GetBoxMin().z)*0.5f;// never change this
}
CStatObj::CStatObj( )
{
m_nUsers = 0; // referense counter
m_bOpenEdgesTested = false;
m_eVertsSharing=evs_NoSharing;
m_bLoadAdditinalInfo=false;
m_bKeepInLocalSpace=false;
m_bUseStreaming=false;
m_bMakePhysics=false;
m_nSpriteTexRes=0;
ZeroStruct( m_szFolderName );
ZeroStruct( m_szFileName );
ZeroStruct( m_szGeomName );
m_pStencilShadowConnectivity=0;
m_nLastRendFrameId = 0;
m_nMarkedForStreamingFrameId = 0;
m_fBackSideLevel = 1.f;
m_bCalcLighting = false;
memset(m_arrpLowLODs,0,sizeof(m_arrpLowLODs));
m_nLoadedLodsNum=1;
m_bPhysicsExistInCompiledFile=false;
Init();
}
void CStatObj::Init()
{
m_pTriData = 0;
m_nLoadedTrisCount = 0;
m_fObjectRadius = 0;
m_fRadiusHors = 0;
m_fRadiusVert = 0;
m_pSvObj=NULL;
m_dwFlags=m_dwFlags2=0;
ZeroStruct( m_arrSpriteTexID );
m_vBoxMin.Set(0,0,0);
m_vBoxMax.Set(0,0,0);
m_vBoxCenter.Set(0,0,0);
memset(m_arrPhysGeomInfo, 0, sizeof(m_arrPhysGeomInfo));
m_pSMLSource = 0;
m_pLeafBuffer = 0;
m_bDefaultObject=false;
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
if(m_arrpLowLODs[i])
m_arrpLowLODs[i]->Init();
m_eCCGFStreamingStatus = ecss_NotLoaded;
m_pReadStream=0;
m_bCompilingNotAllowed=0;
}
CStatObj::~CStatObj()
{
ShutDown();
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
if(m_arrpLowLODs[i])
delete m_arrpLowLODs[i];
}
void CStatObj::ShutDown()
{
// assert (IsHeapValid());
m_pReadStream=0;
if(m_pTriData)
m_pTriData->FreeLMInfo();
// assert (IsHeapValid());
delete m_pTriData;
m_pTriData = 0;
// assert (IsHeapValid());
for(int n=0; n<2; n++)
if(m_arrPhysGeomInfo[n])
GetPhysicalWorld()->GetGeomManager()->UnregisterGeometry(m_arrPhysGeomInfo[n]);
// assert (IsHeapValid());
if(m_pSMLSource && m_pSMLSource->m_LightFrustums.Count() && m_pSMLSource->m_LightFrustums[0].pModelsList)
delete m_pSMLSource->m_LightFrustums[0].pModelsList;
delete m_pSMLSource;
// assert (IsHeapValid());
if(m_pLeafBuffer && !m_pLeafBuffer->m_bMaterialsWasCreatedInRenderer)
{
for (int i=0; i<(*m_pLeafBuffer->m_pMats).Count(); i++)
{
CMatInfo *mi = m_pLeafBuffer->m_pMats->Get(i);
if(mi->pRE)
mi->pRE->Release();
if (mi->shaderItem.m_pShader)
mi->shaderItem.m_pShader->Release();
if (mi->shaderItem.m_pShaderResources)
mi->shaderItem.m_pShaderResources->Release();
}
delete m_pLeafBuffer->m_pMats;
m_pLeafBuffer->m_pMats=0;
}
// assert (IsHeapValid());
GetRenderer()->DeleteLeafBuffer(m_pLeafBuffer);
m_pLeafBuffer=0;
// assert (IsHeapValid());
for(int i=0; i<FAR_TEX_COUNT; i++)
if(m_arrSpriteTexID[i])
GetRenderer()->RemoveTexture(m_arrSpriteTexID[i]);
if (m_pSvObj)
{
// assert (IsHeapValid());
m_pSvObj->Release();
m_pSvObj=NULL;
}
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
{
if(m_arrpLowLODs[i])
m_arrpLowLODs[i]->ShutDown();
}
m_ShaderParams.Free();
// free light source smart pointers
for(int i=0; i<m_lstLSources.Count(); i++)
{
m_lstLSources[i].m_pLightImage = NULL;
m_lstLSources[i].m_pShader = NULL;
}
}
/*
void CStatObj::BuildOcTree()
{
if(!m_pTriData->m_nFaceCount || m_pTriData->m_nFaceCount<=2)
return;
CBox parent_box( m_pTriData->m_vBoxMin, m_pTriData->m_vBoxMax );
parent_box.max += 0.01f;
parent_box.min +=-0.01f;
CObjFace ** allFaces = new CObjFace *[m_pTriData->m_nFaceCount];
for(int f=0; f<m_pTriData->m_nFaceCount; f++)
{
m_pTriData->m_pFaces[f].m_vCenter =
(Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[0]].x) +
Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[1]].x) +
Vec3d(&m_pTriData->m_pVerts[m_pTriData->m_pFaces[f].v[2]].x))/3.f;
allFaces[f] = &m_pTriData->m_pFaces[f];
}
const int max_tris_in_leaf = 2000;
const float leaf_min_size = stricmp(m_szGeomName,"sector_0") ? 16.f : 32.f;
text_to_log(" Generating octree ... ");
m_pOcTree = new octree_node( &parent_box, allFaces, triData->m_nFaceCount, triData, leaf_min_size, max_tris_in_leaf, 2);
text_to_log_plus("%d leafs created", octree_node::static_current_leaf_id);
m_pOcTree->update_bbox(triData);
delete [] allFaces;
}*/
//float M akeBuffersTime = 0;
void CStatObj::MakeLeafBuffer(bool bSortAndShareVerts)
{
if(GetSystem()->IsDedicated())
return;
assert(!m_pLeafBuffer);
m_pLeafBuffer = GetRenderer()->CreateLeafBuffer(eBT_Static,"StatObj");
m_pLeafBuffer->m_pMats = new list2<CMatInfo>;
m_pLeafBuffer->m_pMats->AddList(m_pTriData->m_lstMatTable);
if(bSortAndShareVerts)
bSortAndShareVerts=bSortAndShareVerts;
if(m_pTriData->m_nFaceCount)
m_pLeafBuffer->CreateBuffer(m_pTriData, bSortAndShareVerts, true, //false,);
m_pTriData->m_lstGeomNames.Count()>0 && strstr(m_pTriData->m_lstGeomNames[0],"cloth")!=0);
// remove materials without geometry
if(m_bIgnoreFakeMaterialsInCGF)
if(m_pLeafBuffer && !m_pLeafBuffer->m_bMaterialsWasCreatedInRenderer)
{
for (int i=0; i<(*m_pLeafBuffer->m_pMats).Count(); i++)
{
CMatInfo *mi = m_pLeafBuffer->m_pMats->Get(i);
if(!mi->pRE || !mi->nNumIndices || !mi->nNumVerts)
{
if (mi->shaderItem.m_pShader)
mi->shaderItem.m_pShader->Release();
if (mi->shaderItem.m_pShaderResources)
mi->shaderItem.m_pShaderResources->Release();
m_pLeafBuffer->m_pMats->Delete(i);
if(i<m_lstShaderTemplates.Num())
m_lstShaderTemplates.DelElem(i);
i--;
}
else
mi->pRE->m_pChunk = mi;
}
}
int nDeleted = m_pTriData->m_lstMatTable.Count() - m_pLeafBuffer->m_pMats->Count();
if(nDeleted)
CryLogComment(" %d not used material slots removed", nDeleted);
}
//////////////////////////////////////////////////////////////////////////
int CStatObj::GetAllocatedBytes()
{
int size = sizeof(*this) + m_pTriData ? m_pTriData->GetAllocatedBytes() : 0;
// for(int i=0; i<MAX_TREE_LEAFS_NUM; i++)
{
size += m_pLeafBuffer->GetAllocatedBytes(false);
}
return size;
}
///////////////////////////////////////////////////////////////////////////////////////
Vec3d CStatObj::GetHelperPos(const char * szHelperName)
{
for(int i=0; i<m_lstHelpers.Count(); i++)
if(!strcmp(m_lstHelpers[i].sName,szHelperName))
return m_lstHelpers[i].tMat.GetTranslationOLD();
return Vec3d(0,0,0);
}
///////////////////////////////////////////////////////////////////////////////////////
const Matrix44 * CStatObj::GetHelperMatrixByName(const char * szHelperName)
{
for(int i=0; i<m_lstHelpers.Count(); i++)
if(!strcmp(m_lstHelpers[i].sName,szHelperName))
return &(m_lstHelpers[i].tMat);
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////
const char *CStatObj::GetHelperById(int nId, Vec3d & vPos, Matrix44* pMat, int * pnType)
{
if ( nId >= m_lstHelpers.Count() || nId<0 )
return (NULL);
vPos = m_lstHelpers[nId].tMat.GetTranslationOLD();
if(pnType)
*pnType = m_lstHelpers[nId].nType;
if(pMat)
*pMat = m_lstHelpers[nId].tMat;
return (m_lstHelpers[nId].sName);
}
/*
bool CStatObj::GetHelper(int id, char * szHelperName, int nMaxHelperNameSize, Vec3d * pPos, Vec3d * pRot)
{
if(id<0 || id>=triData->m_Helpers.Count())
return false;
strncpy(szHelperName, triData->m_Helpers[id].name, nMaxHelperNameSize);
*pPos = triData->m_Helpers[id].pos;
*pRot = triData->m_Helpers[id].rot;
return true;
} */
void CStatObj::UpdateCustomLightingSpritesAndShadowMaps(Vec3d vStatObjAmbientColor, int nTexRes, float fBackSideLevel, bool bCalcLighting)
{
AUTO_PROFILE_SECTION(GetTimer(), CObjManager::m_dUpdateCustomLightingSpritesAndShadowMaps);
m_nSpriteTexRes = nTexRes;
m_fBackSideLevel = fBackSideLevel;
m_bCalcLighting = bCalcLighting;
Vec3d vLight = GetSystem()->GetI3DEngine()->GetSunPosition();
vLight.Normalize();
// Vec3d vColor = GetSystem()->GetI3DEngine()->GetWorldColor();
float fSize = m_vBoxMax.z - m_vBoxMin.z;
// update lighting for full lod and lower lods
if(m_pLeafBuffer)
m_pLeafBuffer->UpdateCustomLighting( m_fBackSideLevel, vStatObjAmbientColor, vLight, bCalcLighting );
int nLowestLod=0;
for(int nLodLevel=1; nLodLevel<MAX_STATOBJ_LODS_NUM; nLodLevel++)
if(m_arrpLowLODs[nLodLevel])
{
if(m_arrpLowLODs[nLodLevel]->GetLeafBuffer())
{
m_arrpLowLODs[nLodLevel]->GetLeafBuffer()->UpdateCustomLighting( m_fBackSideLevel, vStatObjAmbientColor, vLight, bCalcLighting );
nLowestLod = nLodLevel;
}
}
// make sprites
if(nLowestLod)
{
// clear sprites in full lod
for(int i=0; i<FAR_TEX_COUNT; i++)
if(m_arrSpriteTexID[i])
{
GetRenderer()->RemoveTexture(m_arrSpriteTexID[i]);
m_arrSpriteTexID[i]=0;
}
// make new sprites in low lod
m_arrpLowLODs[nLowestLod]->CreateModelFarImages(nTexRes); // use lowest lod if present
// move sprite id from low inro into full lod
memcpy(m_arrSpriteTexID, m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID, sizeof(m_arrSpriteTexID));
memset(m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID, 0, sizeof(m_arrpLowLODs[nLowestLod]->m_arrSpriteTexID));
m_nSpriteTexRes = m_arrpLowLODs[nLowestLod]->m_nSpriteTexRes;
}
else
CreateModelFarImages(nTexRes);
MakeShadowMaps(vLight);
// if(m_pTriData && !m_pTriData->m_lstLSources.Count())
// FreeTriData();
}
/*
const char * CStatObj::GetPhysMaterialName(int nMatID)
{
if(m_pLeafBuffer && m_pLeafBuffer->m_pMats && nMatID < m_pLeafBuffer->m_pMats->Count())
return m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat;
return 0;
}
bool CStatObj::SetPhysMaterialName(int nMatID, const char * szPhysMatName)
{
if(m_pLeafBuffer && m_pLeafBuffer->m_pMats && nMatID < m_pLeafBuffer->m_pMats->Count())
{
strncpy(m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat, szPhysMatName, sizeof(m_pLeafBuffer->m_pMats->Get(nMatID)->szPhysMat));
return true;
}
return false;
}
*/
void CStatObj::RegisterUser()
{
m_nUsers++;
}
void CStatObj::UnregisterUser()
{
m_nUsers--;
}
float CStatObj::GetDistFromPoint(const Vec3d & vPoint)
{
float fMinDist = 4096;
for(int v=0; v<m_pTriData->m_nVertCount; v++)
{
float fDist = GetDistance(m_pTriData->m_pVerts[v],vPoint);
if(fDist < fMinDist)
fMinDist = fDist;
}
return fMinDist;
}
bool CStatObj::IsSameObject(const char * szFileName, const char * szGeomName)
{
// cmp object names
if (szGeomName)
{
// [Anton] - always use new cgf for objects used for cloth simulation
if (*szGeomName && stricmp(szGeomName,"cloth") == 0)
return false;
if(stricmp(szGeomName,m_szGeomName)!=0)
return false;
}
// Normilize file name
char szFileNameNorm[MAX_PATH_LENGTH]="";
char *pszDest = szFileNameNorm;
const char *pszSource = szFileName;
while (*pszSource)
{
if (*pszSource=='/')
*pszDest++='\\';
else
*pszDest++=*pszSource;
pszSource++;
}
*pszDest=0;
// cmp file names
if(stricmp(szFileNameNorm,m_szFileName)!=0)
return false;
return true;
}
void CStatObj::GetMemoryUsage(ICrySizer* pSizer)
{
pSizer->AddObject(this,GetMemoryUsage());
}
#ifdef WIN64
#pragma warning( push ) //AMD Port
#pragma warning( disable : 4267 )
#endif
int CStatObj::GetMemoryUsage()
{
int nSize=0;
for(int i=0; i<MAX_STATOBJ_LODS_NUM; i++)
if(m_arrpLowLODs[i])
nSize += m_arrpLowLODs[i]->GetMemoryUsage();
nSize += m_lstHelpers.GetMemoryUsage();
nSize += m_lstLSources.GetMemoryUsage();
nSize += m_lstOcclVolInds.GetMemoryUsage();
nSize += m_lstOcclVolVerts.GetMemoryUsage();
nSize += m_lstShaderTemplates.GetMemoryUsage();
nSize += m_pSMLSource ? sizeof(*m_pSMLSource) : 0;
nSize += m_pSvObj ? m_pSvObj->GetMemoryUsage() : 0;
nSize += m_pTriData ? m_pTriData->GetMemoryUsage() : 0;
nSize += m_ShaderParams.GetMemoryUsage() + m_ShaderParams.Num()*sizeof(SShaderParam);
return nSize;
}
#ifdef WIN64
#pragma warning( pop ) //AMD Port
#endif
bool CStatObj::CheckValidVegetation()
{
if(m_pLeafBuffer && m_pLeafBuffer->m_pMats)
for(int i=0; i<m_pLeafBuffer->m_pMats->Count(); i++)
{
CMatInfo * pMatInfo = m_pLeafBuffer->m_pMats->Get(i);
IShader * pShader = pMatInfo->shaderItem.m_pShader;
if(!pShader || !pMatInfo->nNumIndices)
continue;
pShader = pShader->GetTemplate(0);
const char * pTemplateName = pShader->GetName();
char buff[64];
strncpy(buff, pTemplateName, sizeof(buff)); buff[sizeof(buff)-1]=0;
strlwr(buff);
if( !strstr(buff,"templplants") &&
!strstr(buff,"nodraw") &&
!strstr(buff,"templdecal_vcolors") &&
!strstr(buff,"templdecalalphatest_vcolors"))
{
#if !defined(LINUX)//don't worry, we won't render anything under linux
Warning( 0,m_szFileName,"CStatObj::CheckValidVegetation: Shader template is undefined or can not be used for vegetations: %s [%s]",
pTemplateName, m_szFileName);
// return false;
#endif
}
}
return true;
}
bool CStatObj::EnableLightamapSupport()
{
assert(m_eVertsSharing == evs_NoSharing);
if(m_eVertsSharing == evs_NoSharing)
return true;
/*
GetLog()->Log("Activating lightamap support for %s", m_szFileName);
m_eVertsSharing = evs_NoSharing;
Refresh(FRO_GEOMETRY);
*/
return false;//!m_bDefaultObject;
}
IStatObj * CStatObj::GetLodObject(int nLodLevel)
{
if(nLodLevel<1)
return this;
if(nLodLevel<3)
return (IStatObj *)m_arrpLowLODs[nLodLevel];
return 0;
}
bool CStatObj::IsPhysicsExist()
{
return m_bPhysicsExistInCompiledFile || GetPhysGeom(0) || GetPhysGeom(1) || GetPhysGeom(2);
}
int CStatObj::GetRenderTrisCount()
{
int nCount=0;
if(GetLeafBuffer())
GetLeafBuffer()->GetIndices(&nCount);
return nCount/3;
}
bool CStatObj::IsSphereOverlap(const Sphere& sSphere)
{
if(m_pLeafBuffer && Overlap::Sphere_AABB(sSphere,AABB(m_vBoxMin,m_vBoxMax)))
{ // if inside bbox
int nInds = 0, nPosStride=0;
ushort *pInds = m_pLeafBuffer->GetIndices(&nInds);
const byte * pPos = m_pLeafBuffer->GetPosPtr(nPosStride,0,true);
if(pInds && pPos)
for(int i=0; (i+2)<nInds; i+=3)
{ // test all triangles of water surface strip
Vec3d v0 = *(Vec3d*)&pPos[nPosStride*pInds[i+0]];
Vec3d v1 = *(Vec3d*)&pPos[nPosStride*pInds[i+1]];
Vec3d v2 = *(Vec3d*)&pPos[nPosStride*pInds[i+2]];
Vec3d vBoxMin = v0; vBoxMin.CheckMin(v1); vBoxMin.CheckMin(v2);
Vec3d vBoxMax = v0; vBoxMax.CheckMax(v1); vBoxMax.CheckMax(v2);
if( Overlap::Sphere_AABB(sSphere,AABB(vBoxMin,vBoxMax)))
return true;
}
}
return false;
}