JurassicParkTrespasser/jp2_pc/Source/Lib/Renderer/RenderCacheHelp.cpp
2018-01-01 23:07:24 +01:00

948 lines
25 KiB
C++

/***********************************************************************************************
*
* Copyright © DreamWorks Interactive. 1997
*
* Contents:
* Implementation of RenderCacheHelp.hpp.
*
* To do:
*
***********************************************************************************************
*
* $Log:: /JP2_PC/Source/Lib/Renderer/RenderCacheHelp.cpp $
*
* 95 10/01/98 9:47p Pkeet
* Changed the render cache list to an STL set.
*
* 94 9/25/98 1:50a Pkeet
* Set up caching for biomeshes.
*
* 93 8/31/98 10:04p Pkeet
* Changed the hardware defaults.
*
* 92 8/29/98 7:25p Pkeet
* Increased cache quality parameters for hardware.
*
* 91 8/19/98 1:34p Rwyatt
* Opps.
*
* 90 8/19/98 1:33p Rwyatt
* VC6.0 Warning fixes
*
* 89 8/19/98 11:42a Pkeet
* Fixed bug.
*
* 88 98.08.13 4:26p Mmouni
* Changes for VC++ 5.0sp3 compatibility.
*
* 87 7/06/98 6:52p Pkeet
* Added code to maintain a 1:1 aspect ratio in hardware for render caches.
*
* 86 6/21/98 2:43p Pkeet
* Added the 'SetVisible' member function call to render caches and moved the point where the
* key frame for render caches was updated.
*
* 85 6/04/98 7:43p Pkeet
* Added a parallax shear distance threshold.
*
* 84 6/04/98 6:50p Pkeet
* Added in the cache multiplier value.
*
* 83 6/03/98 8:18p Pkeet
* Added a parallax shear test for determing if a partition should be cached.
*
* 82 5/26/98 11:28p Pkeet
* Increased the minimum distance constant.
*
* 81 5/26/98 2:39p Pkeet
* Set minimum cache distance outward.
*
* 80 5/20/98 7:39p Pkeet
* Fixed crash bug.
*
* 79 5/14/98 7:32p Pkeet
* Caches get points from a partition only if they are visible and of an appropriate priority.
*
* 78 5/12/98 6:10p Pkeet
* Added code to freeze caches.
*
* 77 5/10/98 8:16p Pkeet
* Changed the acceptance sphere to be more permissive.
*
* 76 5/10/98 1:58p Pkeet
* Added area efficiency code. Added numerous asserts to debug broken caches.
*
* 75 5/05/98 2:40p Pkeet
* Added a macro switch to force the minimum distance for caching in test scene to always be 10
* metres.
*
* 74 5/05/98 1:34p Pkeet
* Altered includes to include the render cache private header file.
*
* 73 4/24/98 3:42p Pkeet
* Changed calls to the 'fGetDistanceSqr' member function of 'CPartition' to
* 'fDistanceFromGlobalCameraSqr.'
*
* 72 4/22/98 4:53p Pkeet
* Replaced slower functions to get the world radius of a partition's bounding sphere and its
* bounding radius with more efficient functions.
*
* 71 4/21/98 8:17p Pkeet
* Removed a call to 'InitializeForCaching.'
*
* 70 4/16/98 3:32p Pkeet
* Put some of the functionality of 'bShouldCache' into 'bCanCache.'
*
**********************************************************************************************/
//
// Includes.
//
#include <math.h>
#include "Common.hpp"
#include "RenderCacheHelp.hpp"
#include "RenderCachePriv.hpp"
#include "RenderCacheInterface.hpp"
#include "Lib/Math/FloatDef.hpp"
#include "Lib/Transform/VectorRange.hpp"
#include "Lib/GeomDBase/Partition.hpp"
#include "Lib/EntityDBase/Instance.hpp"
#include "Lib/GeomDBase/Mesh.hpp"
#include "Lib/Renderer/ScreenRender.hpp"
#include "Lib/Renderer/Camera.hpp"
#include "Lib/EntityDBase/GameLoop.hpp"
#include "Lib/Math/FastInverse.hpp"
#include "Lib/Renderer/LineSide2D.hpp"
#include "Lib/Sys/Profile.hpp"
#include "Lib/Sys/Scheduler.hpp"
#include "Lib/GeomDBase/PartitionSpace.hpp"
#include "Lib/Std/LocalArray.hpp"
#include "Lib/Loader/SaveFile.hpp"
#include "Lib/GeomDBase/PartitionPriv.hpp"
#include "Lib/W95/Direct3D.hpp"
//
// Macros and constants.
//
const float fMinDistanceToCache = 15.0f;
// One.
const float fOne = 1.0f;
// Distance after which the shear test will not be conducted.
const float fNoShearTestDistance = 100.0f;
// Scene file version number.
const int iCacheSceneVersion = 2;
// Distance Anne will walk in two frames.
const float fWalkDistance2 = 2.5f;
// Storage for points.
CVector3<> av3AnimalPoints[8];
//
// Module specific variables.
//
SRenderCacheSettings rcsRenderCacheSettings;
CRenderCacheStats rcstCacheStats;
//*********************************************************************************************
void AddStats(CPartition* ppart);
//
// Global functions.
//
//*********************************************************************************************
bool bShouldCache(CPartition* ppart, const CCamera& cam, float f_distance_sqr,
CShapePresence& rsp, bool b_visible)
{
Assert(ppart);
Assert(f_distance_sqr >= 0.0f);
float f_radius_cyl_sqr;
float f_cache_multiplier;
// Always cache if the caching system is frozen and there is a cache already.
if (rcsRenderCacheSettings.bFreezeCaches)
{
if (ppart->prencGet())
{
return true;
}
}
//
// Do not cache the partition if it contains a moving physics object or if it is
// uncacheable for some other reason.
//
if (!ppart->bCanCache())
goto FAIL_CACHE;
// Fail if the partition is too close.
{
float f_cache_mul = (d3dDriver.bUseD3D()) ? (4.0f) : (2.5f);
float f_radius_sph_sqr3 = f_cache_mul * ppart->rGetSphereRadiusSqr();
if (u4FromFloat(f_radius_sph_sqr3) > u4FromFloat(f_distance_sqr))
goto FAIL_CACHE;
}
// Get the cache multiplier.
f_cache_multiplier = ppart->fGetCacheMultiplier();
// Fail if the partition is too big on the screen using the radius of the cylinder.
f_radius_cyl_sqr = ppart->rGetCylinderRadiusSqr();
{
float f_radius_cyl_rel = f_radius_cyl_sqr * rcsRenderCacheSettings.fMaxAcceptCylinder * f_cache_multiplier;
if (u4FromFloat(f_radius_cyl_rel) > u4FromFloat(f_distance_sqr))
goto FAIL_CACHE;
}
// Always accept if the partition is small enough on screen.
if (!ppart->bCacheGroup(f_distance_sqr))
goto FAIL_CACHE;
// More expensive test.
{
Assert(f_distance_sqr > 0.0f);
float f_dist = fSqrtEst(f_distance_sqr) + ppart->rGetCylinderRadius();
float f_min_dist = fMinDistanceToCache * f_cache_multiplier;
// Is the cache at or beyond the minimum distance.
if (u4FromFloat(f_dist) < u4FromFloat(f_min_dist))
{
goto FAIL_CACHE;
}
}
// Final hardcore test.
{
float f_near; // Distance to the nearest point of the partition.
float f_far; // Distance to the farthest point of the partition.
float f_shear_threshold; // Threshold above which the partition will cache.
ppart->GetMinMaxDistance(f_near, f_far, rsp);
Assert(f_near <= f_far);
Assert(f_near > 0.0f);
if (u4FromFloat(f_near) > u4FromFloat(fNoShearTestDistance))
goto ADD_CACHE;
f_near -= fWalkDistance2;
if (u4FromFloat(f_near) & 0x80000000)
goto FAIL_CACHE;
f_far -= fWalkDistance2;
f_shear_threshold = rcsRenderCacheSettings.fParallaxShear;
if (u4FromFloat(f_cache_multiplier) == u4FromFloat(fOne))
{
}
else
{
if (u4FromFloat(f_cache_multiplier) > u4FromFloat(fOne))
{
f_shear_threshold = 1.0f - (1.0f - rcsRenderCacheSettings.fParallaxShear) / f_cache_multiplier;
}
else
{
f_shear_threshold *= f_cache_multiplier;
}
}
Assert(f_shear_threshold >= 0.0f);
Assert(f_shear_threshold <= 1.0f);
f_shear_threshold *= f_far;
if (u4FromFloat(f_near) > u4FromFloat(f_shear_threshold))
goto ADD_CACHE;
}
FAIL_CACHE:
//
// Test failed. Make sure the partition doesn't have a cache.
//
ppart->DeleteRenderCache();
return false;
ADD_CACHE:
// Make sure that this partition does not contain a moving object.
//if (!ppart->bContainsMovingObject())
//
// If there is a cache associated with this partition already, then the
// partition is cacheable.
//
if (ppart->prencGet())
{
// Set the frame key.
AddStats(ppart);
return true;
}
// Make sure no children are using a cache.
ppart->DeleteAllChildCaches();
//
// If a cache can be created for this partition, then it is cacheable.
//
// Make sure a cache exist for this partition.
ppart->CreateRenderCache(cam);
// Set the frame key.
AddStats(ppart);
return true;
}
//
// Class implementation.
//
//*********************************************************************************************
//
// CClosestRenderPoint implementation.
//
//*****************************************************************************************
//
// Constructor.
//
// Default constructor.
CClosestRenderPoint::CClosestRenderPoint()
: bFoundFirst(false)
{
}
//*****************************************************************************************
//
// Member functions.
//
//*****************************************************************************************
void CClosestRenderPoint::Try(const CVector3<>& v3_mesh, TReal r_min_projected_z)
{
// Clamp the y value.
if (r_min_projected_z < 0.0f)
r_min_projected_z = 0.0f;
// If this is the first point found, just store it.
if (!bFoundFirst)
{
v3ClosestMeshPt = v3_mesh;
rMinProjectedZ = r_min_projected_z;
bFoundFirst = true;
return;
}
// Compare the Y values and store the point if it is the closest.
if (r_min_projected_z < rMinProjectedZ)
{
v3ClosestMeshPt = v3_mesh;
rMinProjectedZ = r_min_projected_z;
}
}
//
// Global function bodies.
//
//*********************************************************************************************
void AddStats(CPartition* ppart)
{
// Maintain statistics if required.
if (!rcstCacheStats.bKeepStats)
return;
// Count number of objects cached.
rcstCacheStats.iNumCachedObjects += ppart->iCountInstances();
// Add the age of the cache to the sum of the ages.
rcstCacheStats.iTotalCacheAge += ppart->prencGet()->iGetCacheAge();
}
//*********************************************************************************************
uint uBuildPartitionList(TPPartitionList& rpartlist, CPartition* ppart, const CVector3<>& v3_pos)
{
Assert(ppart);
uint u_num_points = 0;
//
// Continue only if the partition is viewable.
//
float f_distance_sqr = ppart->fDistanceFromGlobalCameraSqr();
if (!ppart->bInRange(f_distance_sqr))
return u_num_points;
//
// If the partition is an instance with a mesh, add the partition to the list.
//
{
CInstance* pins; // The pointer cast as an instance.
ppart->Cast(&pins);
if (pins)
{
// Get the shape from the instance.
rptr<CMesh> pmsh = ptCastRenderType<CMesh>(pins->prdtGetRenderInfo());
if (pmsh)
{
rpartlist.push_back(ppart);
u_num_points = pmsh->pav3GetWrap().uLen;
if (!u_num_points)
{
CAnimal* pani = 0;
ppart->Cast(&pani);
if (pani)
u_num_points = 8;
}
}
}
}
//
// Recurse through children.
//
// Get a pointer to the partition's child list.
CPartition* ppartc = ppart->ppartChildren();
// Return if there are no children.
if (ppartc)
{
// Iterate through the child list to perform this function.
for (CPartition::iterator it = ppartc->begin(); it != ppartc->end(); ++it)
u_num_points += uBuildPartitionList(rpartlist, *it, v3_pos);
}
return u_num_points;
}
//*********************************************************************************************
void GetBoundingCoords(CPartition* ppart, const CTransform3<>& t3f_cam, TReal r_distance,
CDArray< CVector2<> >& rav2_convex, CVector3<>& rv3_min,
CVector3<>& rv3_max, CClosestRenderPoint& rcrp, bool b_use_box,
bool b_add_points)
{
Assert(ppart);
// Check the visible flag.
if (!ppart->bIsVisible())
return;
// Check if the partition priority suggests continuing.
if (!ppart->bIsWithinPriority())
return;
CInstance* pins; // The pointer cast as an instance.
// Cast the pointer to an instance.
ppart->Cast(&pins);
//
// If the partition is an instance with a mesh, iterate through the mesh vertices and
// extract the minimum and maximum points in camera space.
//
if (pins)
{
// Get the shape from the instance.
rptr<CMesh> pmsh = ptCastRenderType<CMesh>(pins->prdtGetRenderInfo());
// Get the minimun and maximum points.
if (pmsh)
{
// Get the shape to world transform.
CTransform3<> t3f_shape_cam = ppart->pr3Presence() * t3f_cam;
// Get the shape's wrap in camera space coordinates.
CPArray< CVector3<> > pav3_mesh = pmsh->pav3GetWrap();
CAnimal* pani = 0; // Animal cast.
// If no array is found, assume that the mesh is for an animal.
if (!pav3_mesh.atArray)
ppart->Cast(&pani);
// If there is no point cloud, assume the instance to be an animal.
if (pani)
{
CVector3<> v3_min_animal;
CVector3<> v3_max_animal;
CTransform3<> t3f_shape;
// Use global storage temporarily.
pav3_mesh.atArray = av3AnimalPoints;
pav3_mesh.uLen = 8;
// Synthesize a point cloud.
pmsh->GetExtents(pins, t3f_shape, v3_min_animal, v3_max_animal);
pav3_mesh[0] = v3_min_animal;
pav3_mesh[1] = CVector3<>(v3_min_animal.tX, v3_min_animal.tY, v3_max_animal.tZ);
pav3_mesh[2] = CVector3<>(v3_min_animal.tX, v3_max_animal.tY, v3_min_animal.tZ);
pav3_mesh[3] = CVector3<>(v3_min_animal.tX, v3_max_animal.tY, v3_max_animal.tZ);
pav3_mesh[4] = CVector3<>(v3_max_animal.tX, v3_min_animal.tY, v3_min_animal.tZ);
pav3_mesh[5] = CVector3<>(v3_max_animal.tX, v3_min_animal.tY, v3_max_animal.tZ);
pav3_mesh[6] = CVector3<>(v3_max_animal.tX, v3_max_animal.tY, v3_min_animal.tZ);
pav3_mesh[7] = v3_max_animal;
}
uint u_num_new_points = pav3_mesh.uLen; // Number of points to add.
// Limit the number of new points that can be added.
if (b_use_box)
{
u_num_new_points = Min(8, pav3_mesh.uLen);
}
// Create intermediate storage for the new points.
CLArray(CVector3<>, pav3, u_num_new_points);
if (b_use_box && pav3.uLen >= 8)
{
ppart->bGetBoundingBoxVertices(pav3);
for (uint u = 0; u < pav3.uLen; ++u)
{
pav3[u] = pav3[u] * t3f_shape_cam;
Assert(_finite(pav3[u].tX));
Assert(_finite(pav3[u].tY));
Assert(_finite(pav3[u].tZ));
}
}
else
{
// Iterate through the shape's points to transform and copy the point.
for (uint u = 0; u < pav3.uLen; ++u)
{
pav3[u] = pav3_mesh[u] * t3f_shape_cam;
Assert(_finite(pav3[u].tX));
Assert(_finite(pav3[u].tY));
Assert(_finite(pav3[u].tZ));
}
}
// Iterate through the shape's points to produce a list of convex points.
for (uint u = 0; u < pav3.uLen; ++u)
{
// Copy the point.
CVector3<> v3 = pav3[u];
Assert(_finite(v3.tX));
Assert(_finite(v3.tY));
Assert(_finite(v3.tZ));
// Get the projection value.
float f_inverse_z = fInverse(v3.tY);
float f_project = r_distance * f_inverse_z;
// Project the point into camera space.
CVector2<> v2(v3.tX * f_project, v3.tZ * f_project);
Assert(_finite(v2.tX));
Assert(_finite(v2.tY));
// Add the point to the list.
if (b_add_points)
rav2_convex.daAdd(v2);
//
// Store the point if it is the closest one yet to the camera, or the first
// point found.
//
if (u < pav3_mesh.uLen)
rcrp.Try(pav3_mesh[u], v2.tY);
// Get the minimum and maximum x, y and z positions.
rv3_min.tX = Min(rv3_min.tX, v2.tX);
rv3_max.tX = Max(rv3_max.tX, v2.tX);
rv3_min.tY = Min(rv3_min.tY, v2.tY);
rv3_max.tY = Max(rv3_max.tY, v2.tY);
rv3_min.tZ = Min(rv3_min.tZ, v3.tY);
rv3_max.tZ = Max(rv3_max.tZ, v3.tY);
}
}
}
}
//*********************************************************************************************
void FudgeRange(CVector3<>& rv3_min, CVector3<>& rv3_max, TReal r_expand)
{
rv3_min.tX -= r_expand;
rv3_min.tY -= r_expand;
rv3_max.tX += r_expand;
rv3_max.tY += r_expand;
}
//*********************************************************************************************
void SetCameraProperties(CCamera& cam_new, rptr<CRaster> pras, TReal r_distance,
CVector3<>& rv3_coord_min, CVector3<>& rv3_coord_max)
{
CVector2<> v2_coord_max;
float f_dx = rv3_coord_max.tX - rv3_coord_min.tX;
float f_dy = rv3_coord_max.tY - rv3_coord_min.tY;
// Get absolute max coordinates.
v2_coord_max.tX = Max(Abs(rv3_coord_max.tX), Abs(rv3_coord_min.tX));
v2_coord_max.tY = Max(Abs(rv3_coord_max.tY), Abs(rv3_coord_min.tY));
// Get the camera's existing properties.
CCamera::SProperties camprop = cam_new.campropGetProperties();
//
// Setup the main viewport object.
//
// Set the screen size (for scaling during projection) to the raster size.
camprop.vpViewport.SetSize(pras->iWidth, pras->iHeight);
#if bDEBUG_PRINT_CACHE_VALUES
dprintf("Cache camera: %ld, %ld\n", pras->iWidth, pras->iHeight);
#endif // bDEBUG_PRINT_CACHE_VALUES
camprop.rViewWidth = v2_coord_max.tX / r_distance;
// Set the physical aspect ratio.
camprop.fAspectRatio = v2_coord_max.tX / v2_coord_max.tY;
//
// Set the near and far clipping planes for the object.
//
// Distance of the near clipping plane from the camera.
camprop.rNearClipPlaneDist = rv3_coord_min.tZ;
if (camprop.rNearClipPlaneDist < 0.001f)
camprop.rNearClipPlaneDist = 0.001f;
// Distance of the far clipping plane from the camera.
camprop.rFarClipPlaneDist = rv3_coord_max.tZ;
// Set the properties of the new camera.
cam_new.SetProperties(camprop);
}
//*********************************************************************************************
CVector3<> v3GetCameraPos(const CCamera& cam)
{
// Use a predicted position if the settings allow for it.
return cam.pr3VPresence(rcsRenderCacheSettings.bUseCameraPrediction).v3Pos;
}
//*********************************************************************************************
//
// SRenderCacheSettings implementation.
//
//*****************************************************************************************
//
// Member functions.
//
//*****************************************************************************************
void SRenderCacheSettings::SetMaxAngleCylinder(int i_degrees)
{
Assert(i_degrees > 0);
Assert(i_degrees < 90);
double d_radians = double(i_degrees) * 3.14159 / 180.0;
float f_tan_alpha = float(1.0 / tan(d_radians));
fMaxAcceptCylinder = f_tan_alpha * f_tan_alpha + 1.0f;
iMaxAcceptAngleCylinder = i_degrees;
}
//*****************************************************************************************
//
char* SRenderCacheSettings::pcSave
(
char* pc
) const
//
// Saves the render cache settings to a buffer.
//
//**************************************
{
// Save version number.
pc = pcSaveT(pc, iCacheSceneVersion);
pc = pcSaveT(pc, iMaxAcceptAngleCylinder);
if (prenMain && prenMain->pSettings)
pc = pcSaveT(pc, prenMain->pSettings->fDetailReduceFactor);
else
pc = pcSaveT(pc, 1.0f);
pc = pcSaveT(pc, rPixelsPerArea);
pc = pcSaveT(pc, rPixelsPerLine);
pc = pcSaveT(pc, rMinPolygonMesh);
pc = pcSaveT(pc, bUseCameraPrediction);
pc = pcSaveT(pc, bFasterPhysics);
pc = pcSaveT(pc, iMaxObjectsPerCache);
pc = pcSaveT(pc, fEfficiencyArea);
pc = pcSaveT(pc, fDistortionWeight);
return pc;
}
//*****************************************************************************************
//
const char* SRenderCacheSettings::pcLoad
(
const char* pc
)
//
// Loads the render cache settings.
//
//**************************************
{
int iVersion;
float f_dummy;
int i_dummy;
bool b_dummy;
pc = pcLoadT(pc, &iVersion);
switch (iVersion)
{
case 1:
pc = pcLoadT(pc, &f_dummy);
pc = pcLoadT(pc, &iMaxAcceptAngleCylinder);
pc = pcLoadT(pc, &f_dummy);
pc = pcLoadT(pc, &i_dummy);
pc = pcLoadT(pc, &prenMain->pSettings->fDetailReduceFactor);
pc = pcLoadT(pc, &rPixelsPerArea);
pc = pcLoadT(pc, &rPixelsPerLine);
pc = pcLoadT(pc, &f_dummy);
pc = pcLoadT(pc, &rMinPolygonMesh);
pc = pcLoadT(pc, &f_dummy);
pc = pcLoadT(pc, &bUseCameraPrediction);
pc = pcLoadT(pc, &b_dummy);
pc = pcLoadT(pc, &b_dummy);
pc = pcLoadT(pc, &bFasterPhysics);
pc = pcLoadT(pc, &i_dummy);
pc = pcLoadT(pc, &f_dummy);
pc = pcLoadT(pc, &iMaxObjectsPerCache);
pc = pcLoadT(pc, &fEfficiencyArea);
pc = pcLoadT(pc, &fDistortionWeight);
pc = pcLoadT(pc, &f_dummy);
pc = pcLoadT(pc, &f_dummy);
pc = pcLoadT(pc, &f_dummy);
break;
case 2:
pc = pcLoadT(pc, &iMaxAcceptAngleCylinder);
pc = pcLoadT(pc, &prenMain->pSettings->fDetailReduceFactor);
pc = pcLoadT(pc, &rPixelsPerArea);
pc = pcLoadT(pc, &rPixelsPerLine);
pc = pcLoadT(pc, &rMinPolygonMesh);
pc = pcLoadT(pc, &bUseCameraPrediction);
pc = pcLoadT(pc, &bFasterPhysics);
pc = pcLoadT(pc, &iMaxObjectsPerCache);
pc = pcLoadT(pc, &fEfficiencyArea);
pc = pcLoadT(pc, &fDistortionWeight);
break;
default:
AlwaysAssert("Unknown version of render cache settings");
}
// Reset partitions for render cache use.
wWorld.InitializePartitions();
return pc;
}
//
// Maintain the lists of moving and stopped partitions.
//
//*********************************************************************************************
void AddToMovingList(CPartition* ppart)
{
ppartlistMoved.push_back(ppart);
}
//*********************************************************************************************
void AddToStoppedList(CPartition* ppart)
{
ppartlistStopped.push_back(ppart);
}
//*********************************************************************************************
void BeginCacheUpdate()
{
CPartition::IncrementFrameCount();
}
//*********************************************************************************************
void EndCacheUpdate()
{
Assert(pwWorld);
//
// For now, the simplest thing may be the best. Simply mark the partition and its parents
// as uncacheable for a frame.
//
// To do:
// Changed partition parameters to reflect objects added to partition nodes.
//
TPPartitionList::iterator it = ppartlistMoved.begin();
for (; it != ppartlistMoved.end(); ++it)
{
Assert(*it);
if (rcsRenderCacheSettings.bFasterPhysics)
{
(*it)->SetCacheNoBuild();
}
else
{
Assert(pwWorld->ppartPartitionList());
{
//
// Create a query with a slightly expanded bounding volume.
//
CBoundVol* pbv = (CBoundVol*)(*it)->pbvBoundingVol();
Assert(pbv);
if (pbv->ebvGetType() == ebvBOX)
{
CBoundVolBox bvb((static_cast<CBoundVolBox*>(pbv))->v3GetMax() * 1.05f);
CPartitionSpaceQuery psq((*it)->pr3Presence(), bvb);
pwWorld->ppartPartitionList()->SetCacheNoBuildPart(*it);
}
else
{
CPartitionSpaceQuery psq((*it)->pr3Presence(), pbv->fMaxExtent() * 1.05f);
pwWorld->ppartPartitionList()->SetCacheNoBuildPart(*it);
}
}
}
}
// Get rid of lists.
DumpMoveStopLists();
}
//*********************************************************************************************
void DumpMoveStopLists()
{
ppartlistMoved.erase(ppartlistMoved.begin(), ppartlistMoved.end());
ppartlistStopped.erase(ppartlistStopped.begin(), ppartlistStopped.end());
}
//*********************************************************************************************
void CollectCacheGarbage()
{
if (rcsRenderCacheSettings.bFreezeCaches)
return;
// Allocate a local array of partitions with caches to be destroyed.
CMLArray(CPartition*, appart, renclRenderCacheList.partlistCached.size());
// Find the unused partitions.
CRenderCacheList::TCacheSet::iterator it = renclRenderCacheList.partlistCached.begin();
for (; it != renclRenderCacheList.partlistCached.end(); ++it)
{
Assert(*it);
Assert((*it)->prencGet());
// If the partition has an unused cache, push it to the list.
if (!(*it)->prencGet()->bIsCurrentFrameKey())
appart << (*it);
}
// Remove unused partitions.
for (uint u = 0; u < appart.uLen; ++u)
{
Assert(appart[u]);
appart[u]->DeleteRenderCache();
}
}
//*********************************************************************************************
void AddUnseenCaches(CScheduler& scheduler, const CCamera& cam, CRenderContext& renc,
CPartition* ppart)
{
Assert(ppart);
return;
//if (!rcsRenderCacheSettings.bBuildNonVisible)
//return;
// Get the pointer to an existing cache if there is one.
CRenderCache* prenc = ppart->prencGet();
// Ignore if the partition is already included for the current frame.
if (prenc)
{
if (prenc->bIsCurrentFrameKey())
return;
if (!prenc->bEvaluate())
{
prenc->UpdateFrameKey();
return;
}
}
//
// Use distance culling to reject the partition if possible.
//
// Get the distance square.
float f_distance_sqr = ppart->fDistanceFromGlobalCameraSqr();
// Cull if out of range.
if (!ppart->bInRange(f_distance_sqr))
return;
/*
// Determine if the partition should be cached.
if (bShouldCache(ppart, cam, f_distance_sqr, false))
{
// Create a dummy intersect list.
CLArray(COcclude*, apoc, 0);
// Invoke the scheduler, passing along all the pipeline stuff.
ppart->prencGet()->SetVisible();
new (scheduler) CScheduleCache
(
scheduler, // Scheduler used for scheduling caches.
ppart, // Cached partition.
renc, // Render context.
apoc // List of intersecting occlusion objects.
);
ppart->prencGet()->UpdateFrameKey(false);
return;
}
*/
// Call this function recursively on the child partitions.
if (!ppart->prencGet())
{
CPartition* ppartc = ppart->ppartChildren();
if (ppartc)
{
// Iterate through the children and call this function recursively.
for (CPartition::iterator it = ppartc->begin(); it != ppartc->end(); ++it)
AddUnseenCaches(scheduler, cam, renc, *it);
}
}
}
//
// Global variables.
//
TPPartitionList ppartlistMoved;
TPPartitionList ppartlistStopped;