The-Simpsons-Hit-and-Run/game/code/render/Culling/CellBlock.cpp

317 lines
9.2 KiB
C++

#include <render/culling/CellBlock.h>
#include <render/culling/VectorLib.h>
#include <render/culling/FloatFuncs.h>
CellBlock::CellBlock(){}
CellBlock::~CellBlock(){}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/*
void CellBlock::Init
(
int iSize,
BlockCoord& irBlockCoord,
Vector3f& irGranularities
)
{
mBlockCoord = irBlockCoord;
mGranularities = irGranularities;
Allocate( iSize );
}
*/
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::Init
(
FixedArray<Vector3f>& irPoints,
Vector3f& irGranularities
)
{
/////////////////////////////////////////////////////////////
// TODO -
//
// 1) Resolve: Find out whether any platforms round negative
// numbers toward Zero (ie, the sensible, magnitude driven way)
// as ARM says it's platform dependant
/////////////////////////////////////////////////////////////
theVectorLib().FindBounds( mBounds, irPoints );
mGranularities = irGranularities;
mBlockCoord.Init( mBounds, mGranularities );
Allocate( mBlockCoord.mExtents[0] * mBlockCoord.mExtents[1] * mBlockCoord.mExtents[2] );
//BoundCellsByGranularities();
Add( irPoints );
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::Init
(
FixedArray<Vector3f>& irPoints,
FixedArray<int>& irPointWeights,
Vector3f& irGranularities
)
{
theVectorLib().FindBounds( mBounds, irPoints );
mGranularities = irGranularities;
mBlockCoord.Init( mBounds, mGranularities );
Allocate( mBlockCoord.mExtents[0] * mBlockCoord.mExtents[1] * mBlockCoord.mExtents[2] );
//BoundCellsByGranularities();
Add( irPoints, irPointWeights );
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/*void CellBlock::BoundCellsByGranularities()
{
Bounds3f CurBounds;
for( int i=mBlockCoord.mExtents[0]; i>=0; i-- )
{
for( int j=mBlockCoord.mExtents[1]; j>=0; j-- )
{
for( int k=mBlockCoord.mExtents[2]; k>=0; k-- )
{
CurBounds.mMin.Set( mBlockCoord.mOffset.x + i*mGranularities.x,
mBlockCoord.mOffset.y + j*mGranularities.y,
mBlockCoord.mOffset.z + k*mGranularities.z );
CurBounds.mMax.Set( mBlockCoord.mOffset.x + (i+1)*mGranularities.x,
mBlockCoord.mOffset.y + (j+1)*mGranularities.y,
mBlockCoord.mOffset.z + (k+1)*mGranularities.z );
GetCell(i,j,k).SetBounds( CurBounds );
}
}
}
}
*/
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::Add( FixedArray<Vector3f>& irPoints )
{
rAssert( IsSetUp() );
int i;
for( i=(irPoints.mSize-1); i>-1; i-- )
{
mpData[ CellIndex(irPoints[i]) ].AccVertex(irPoints[i]) ;
}
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::Add
(
FixedArray<Vector3f>& irPoints,
FixedArray<int>& irPointWeights
)
{
rAssert( IsSetUp() );
int i;
for( i=(irPoints.mSize-1); i>-1; i-- )
{
operator[](CellIndex(irPoints[i])).AccVertex( irPoints[i], irPointWeights[i] );
}
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::Add( Vector3f& irPoint )
{
rAssert( IsSetUp() );
mpData[ CellIndex(irPoint) ].AccVertex(irPoint);
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::GenerateCells()
{
for( int i=mSize-1; i>-1; i-- )
{
mpData[i].GenerateCell();
}
SetCellsBlockData();
}
/////////////////////////////////////////////////////////////
// Translate Extracts the Data from this Object destructively
//
// The Object is emptied of its translation-salient data, as
// said data takes on a new representation.
/////////////////////////////////////////////////////////////
void CellBlock::Translate( FixedArray<Cell>& orCellArray, Vector3i& orSpans )
{
//
// Extract the array without allocations
//
orCellArray.Clear();
orCellArray.mSize = mSize;
orCellArray.mpData = mpData;
mpData = NULL;
orSpans.Set( mBlockCoord.mExtents );
}
/////////////////////////////////////////////////////////////
// Only extracts the non-empty cells from the cell matrix
// More expensive than the simple Translate, as it requires
// two iterative passes and an extra alloc and free.
/////////////////////////////////////////////////////////////
void CellBlock::TranslateNonEmpty( FixedArray<Cell>& orCellArray, Vector3i& orSpans )
{
int emptyCells = CountEmptyCells();
orCellArray.Clear();
orCellArray.Allocate( mSize - emptyCells );
for( int j = 0, i=mSize-1; i>-1; i-- )
{
if( mpData[i].RenderWeight() > 0 )
{
orCellArray.mpData[j] = mpData[i];
j++;
}
}
Clear();
orSpans.Set( mBlockCoord.mExtents );
}
/////////////////////////////////////////////////////////////
// Only extracts the non-empty cells from the cell matrix
// More expensive than the simple Translate, as it requires
// two iterative passes and an extra alloc and free.
/////////////////////////////////////////////////////////////
void CellBlock::ExtractNonEmptyCells( FixedArray<Cell>& orCellArray )
{
int emptyCells = CountEmptyCells();
orCellArray.Allocate( mSize - emptyCells );
for( int j = 0, i=mSize-1; i>-1; i-- )
{
if( mpData[i].RenderWeight() > 0 )
{
orCellArray.mpData[j] = mpData[i];
j++;
}
}
Clear();
}
/////////////////////////////////////////////////////////////
// Counts all the Cells which have not been seeded with
// non-zero render weights
/////////////////////////////////////////////////////////////
int CellBlock::CountEmptyCells()
{
int Count=0;
for( int i=mSize-1; i>-1; i-- )
{
if( mpData[i].RenderWeight() < 1 )
{
Count++;
}
}
return Count;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::ExtractCells( FixedArray<Cell>& orCellArray )
{
//
// Extract the array without allocations
//
orCellArray.Clear();
orCellArray.mSize = mSize;
orCellArray.mpData = mpData;
mpData = NULL;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::ExtractDims( Vector3i& orSpans )
{
orSpans.Set( mBlockCoord.mExtents );
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::ExtractBounds( Bounds3f& orBounds )
{
orBounds = mBounds;
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
int CellBlock::CellIndex( Vector3f& irPoint )
{
Vector3f index3f;
Vector3f AdjustedGranularities;
AdjustedGranularities.Mult( mGranularities, 1.0f+FloatFuncs::MinRemainder );
index3f.Sub( irPoint, mBlockCoord.mOffset);
index3f.Div( index3f, AdjustedGranularities );//mGranularities );
return CellIndex( (int)index3f[0], (int)index3f[1], (int)index3f[2] );
// return( ((int)(index3f[0]) * mBlockCoord.mExtents[1] * mBlockCoord.mExtents[2]) +
// ((int)(index3f[1]) * mBlockCoord.mExtents[2]) +
// (int)(index3f[2]) );
}
Cell& CellBlock::GetCell( int iX, int iY, int iZ )
{
return mpData[CellIndex(iX, iY, iZ)];
}
int CellBlock::CellIndex( int iX, int iY, int iZ )
{
return( ((iX) * mBlockCoord.mExtents[1] * mBlockCoord.mExtents[2]) +
((iY) * mBlockCoord.mExtents[2]) +
(iZ) );
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
void CellBlock::SetCellsBlockData()
{
Bounds3f Bounds;
Vector3i Index;
for( Index.mX=0; Index.mX<mBlockCoord.mExtents[0]; Index.mX++ )
{
for( Index.mY=0; Index.mY<mBlockCoord.mExtents[1]; Index.mY++ )
{
for( Index.mZ=0; Index.mZ<mBlockCoord.mExtents[2]; Index.mZ++ )
{
Bounds.mMin.Set( mBlockCoord.mOffset.x + ((float)Index.mX)*mGranularities.x,
mBlockCoord.mOffset.y + ((float)Index.mY)*mGranularities.y,
mBlockCoord.mOffset.z + ((float)Index.mZ)*mGranularities.z );
Bounds.mMax.Set( Bounds.mMin.x+mGranularities.x,
Bounds.mMin.y+mGranularities.y,
Bounds.mMin.z+mGranularities.z );
GetCell(Index.mX,Index.mY,Index.mZ).SetBounds( Bounds );
GetCell(Index.mX,Index.mY,Index.mZ).SetBlockIndex( Index );
}
}
}
}