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

214 lines
7.2 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: statobjmandraw.cpp
// Version: v1.00
// Created: 28/5/2001 by Vladimir Kajalin
// Compilers: Visual Studio.NET
// Description: Draw static objects (vegetations)
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "StatObj.h"
#include "objman.h"
#include "visareas.h"
#include "terrain_sector.h"
#include "3dengine.h"
#include "cbuffer.h"
bool CObjManager::IsBoxOccluded( const Vec3d & vBoxMin, const Vec3d & vBoxMax, float fDistance, OcclusionTestClient * pOcclTestVars )
{
FUNCTION_PROFILER_FAST( GetSystem(),PROFILE_3DENGINE,m_bProfilerEnabled );
assert(pOcclTestVars);
assert(fDistance>=0);
if(m_nRenderStackLevel)
return pOcclTestVars->bLastResult; // return result of base level test
if(pOcclTestVars->nLastVisibleFrameID < GetFrameID()-1)
{ // if was invisible last frames (because of frustum culling)
pOcclTestVars->ucOcclusionByObjectsFrames = 0; // force to test this frame
if(GetCVars()->e_terrain_occlusion_culling!=2)
pOcclTestVars->ucOcclusionByTerrainFrames = 0; // force to test this frame
}
{ // test occlusion by objects
if(!pOcclTestVars->ucOcclusionByObjectsFrames && fDistance>COVERAGEBUFFER_OCCLUSION_TESTERS_MIN_DISTANCE && GetCVars()->e_cbuffer)
{ // less distance do not work because objects are sorted wrong
if(!m_pCoverageBuffer->IsBBoxVisible(vBoxMin,vBoxMax))
{
pOcclTestVars->ucOcclusionByObjectsFrames = 0; // force to test next frame
pOcclTestVars->bLastResult = true;
return true;
}
}
pOcclTestVars->ucOcclusionByObjectsFrames += 4; // skip testing next frame
}
/*
{ // test occl by antiportals
if(GetVisAreaManager()->IsOccludedByOcclVolumes(vBoxMin,vBoxMax))
return true;
}
*/
{ // test occlusion by terrain
Vec3d vTopMax = vBoxMax;
Vec3d vTopMin = vBoxMin; vTopMin.z = vTopMax.z;
const Vec3d & vCamPos = GetViewCamera().GetPos();
vTopMax.CheckMin(Vec3d((float)CTerrain::GetTerrainSize(),(float)CTerrain::GetTerrainSize(),1024.f));
vTopMin.CheckMax(Vec3d(0,0,-1024.f));
vTopMin.CheckMin(Vec3d((float)CTerrain::GetTerrainSize(),(float)CTerrain::GetTerrainSize(),1024.f));
vTopMax.CheckMax(Vec3d(0,0,-1024.f));
if( !pOcclTestVars->ucOcclusionByTerrainFrames && GetCVars()->e_terrain_occlusion_culling )
{
int nMaxTestsToScip = (GetVisAreaManager()->m_pCurPortal) ? 3 : 10000;
// precision in meters for this object
float fMaxStep = fDistance*GetCVars()->e_terrain_occlusion_culling_precision;
if( (fMaxStep < (vTopMax.x - vTopMin.x)*2.f || fMaxStep < (vTopMax.y - vTopMin.y)*2.f) &&
// fDistance<700 &&
vBoxMin.x != vBoxMax.x && vBoxMin.y != vBoxMax.y )
{
bool bOccluded = true;
// todo: debug this
float dx = (vTopMax.x - vTopMin.x)*0.99999f;
while(dx>fMaxStep)
dx*=0.5f;
float dy = (vTopMax.y - vTopMin.y)*0.99999f;
while(dy>fMaxStep)
dy*=0.5f;
// todo: test only borders
for(float x=vTopMin.x; x<=vTopMax.x; x+=dx)
for(float y=vTopMin.y; y<=vTopMax.y; y+=dy)
{
if(!m_pTerrain->IsPointOccludedByTerrain(Vec3d(x, y, vTopMax.z), fDistance, vCamPos, nMaxTestsToScip))
{
bOccluded = false;
x=y=1000000;//break
}
}
if(bOccluded)
{
if(GetCVars()->e_terrain_occlusion_culling!=2)
pOcclTestVars->ucOcclusionByTerrainFrames = 0; // force to test next frame
pOcclTestVars->bLastResult = true;
return true;
}
}
else
{
Vec3d vTopMid = (vTopMin+vTopMax)*0.5f;
if( m_pTerrain->IsPointOccludedByTerrain(vTopMid, fDistance,vCamPos, nMaxTestsToScip))
{
if(GetCVars()->e_terrain_occlusion_culling!=2)
pOcclTestVars->ucOcclusionByTerrainFrames = 0; // force to test next frame
pOcclTestVars->bLastResult = true;
return true;
}
}
}
if(pOcclTestVars->ucOcclusionByTerrainFrames == 0) // && GetCVars()->e_terrain_occlusion_culling==3)
{ // randomize test time, do this only here otherwice ucOcclusionByTerrainFrames may never become 0 and next test will not happend
static int arrRnd[16] =
{
rand()%4+1, rand()%4+1, rand()%4+1, rand()%4+1,
rand()%4+1, rand()%4+1, rand()%4+1, rand()%4+1,
rand()%4+1, rand()%4+1, rand()%4+1, rand()%4+1,
rand()%4+1, rand()%4+1, rand()%4+1, rand()%4+1
};
static int nRndCounter = 0;
nRndCounter++;
if(nRndCounter>=16)
nRndCounter=0;
pOcclTestVars->ucOcclusionByTerrainFrames = arrRnd[nRndCounter]*4;
}
else
pOcclTestVars->ucOcclusionByTerrainFrames += 4; // skip testing next 64 frames
}
/* const Vec3d & vCamPos = GetViewCamera().GetPos();
bool bCameraInBBox =
vCamPos.x >= (vBoxMin.x-0.05f) && vCamPos.y >= (vBoxMin.y-0.05f) && vCamPos.z >= (vBoxMin.z-0.05f) &&
vCamPos.x <= (vBoxMax.x+0.05f) && vCamPos.y <= (vBoxMax.y+0.05f) && vCamPos.z <= (vBoxMax.z+0.05f);
// Make test only if camera outside of the box and if feature supported
if(fDistance>1 && !bCameraInBBox && GetCVars()->e_hw_occlusion_culling_objects && (GetRenderer()->GetFeatures() & RFT_OCCLUSIONTEST) )
{
// construct RE if needed
for(int i=0; i<2; i++)
{
if(!pOcclTestVars->arrREOcclusionQuery[i])
pOcclTestVars->arrREOcclusionQuery[i] =
(CREOcclusionQuery *)GetRenderer()->EF_CreateRE(eDATA_OcclusionQuery);
pOcclTestVars->arrREOcclusionQuery[i]->m_vBoxMin = vBoxMin;
pOcclTestVars->arrREOcclusionQuery[i]->m_vBoxMax = vBoxMax;
}
int nSlotId = GetFrameID()&1;
GetRenderer()->EF_AddEf(0, pOcclTestVars->arrREOcclusionQuery[nSlotId], m_pShaderOcclusionQuery, 0);
if(GetCVars()->e_hw_occlusion_culling_objects>1)
{
float fVis = (pOcclTestVars->arrREOcclusionQuery[!nSlotId]->m_nVisSamples >= 2);
float fCol[] = {fVis,!fVis,1,1};
GetRenderer()->DrawLabelEx((vBoxMin + vBoxMax)*0.5f,6, fCol, false, true, "%s",
fVis ? "V" : "N");
}
if(
pOcclTestVars->arrREOcclusionQuery[0]->m_nVisSamples < 2 &&
pOcclTestVars->arrREOcclusionQuery[1]->m_nVisSamples < 2 &&
1 >= abs( pOcclTestVars->arrREOcclusionQuery[0]->m_nCheckFrame -
pOcclTestVars->arrREOcclusionQuery[1]->m_nCheckFrame ) &&
GetFrameID()-2 <= pOcclTestVars->arrREOcclusionQuery[0]->m_nDrawFrame &&
GetFrameID()-2 <= pOcclTestVars->arrREOcclusionQuery[1]->m_nDrawFrame )
{ // return true only if last test is not older than 1 frame
pOcclTestVars->bLastResult = true;
return true;
}
}*/
pOcclTestVars->bLastResult = false;
pOcclTestVars->nLastVisibleFrameID = GetFrameID();
return false;
}
void CObjManager::PrefechObjects()
{
for (ObjectsMap::iterator it = m_lstLoadedObjects.begin(); it != m_lstLoadedObjects.end(); ++it)
{
CStatObj * pStatObj = (*it);
SRendParams params;
params.nDLightMask = 1;
GetRenderer()->EF_StartEf();
for(int i=0; i<3; i++)
pStatObj->Render(params,Vec3(zero),i);
GetRenderer()->EF_EndEf3D(0);
}
}