Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1400 lines
31 KiB
C++
1400 lines
31 KiB
C++
#include "ElementRendererHeaders.hpp"
|
|
#include "GridElement.hpp"
|
|
|
|
//#define SPEW_CULL_INFO "your_name_here"
|
|
|
|
//############################################################################
|
|
//############################ GridElement ################################
|
|
//############################################################################
|
|
|
|
HGOSHEAP
|
|
ElementRenderer::GridElement::s_Heap = NULL;
|
|
|
|
ElementRenderer::GridElement::ClassData*
|
|
ElementRenderer::GridElement::DefaultData = NULL;
|
|
|
|
ElementRenderer::Element::SyncMethod
|
|
ElementRenderer::GridElement::SyncMethods[4]=
|
|
{
|
|
SYNC_METHOD(ListElement, CleanRoot),
|
|
SYNC_METHOD(ListElement, Clean),
|
|
SYNC_METHOD(ListElement, DirtyRoot),
|
|
SYNC_METHOD(ListElement, Dirty)
|
|
};
|
|
|
|
ElementRenderer::Element::CullMethod
|
|
ElementRenderer::GridElement::CullMethods=
|
|
CULL_METHOD(GridElement, Grid, Grid);
|
|
|
|
ElementRenderer::Element::DrawMethod
|
|
ElementRenderer::GridElement::DrawMethods[DrawStateCount]=
|
|
{
|
|
DRAW_METHOD(GridElement, Inherit),
|
|
DRAW_METHOD(GridElement, Override)
|
|
};
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
|
|
Verify(!s_Heap);
|
|
s_Heap = gos_CreateMemoryHeap("Grid", 0, g_LibraryHeap);
|
|
Check_Pointer(s_Heap);
|
|
|
|
DefaultData =
|
|
new ClassData(
|
|
GridElementClassID,
|
|
"ElementRenderer::GridElement",
|
|
BaseClass::DefaultData,
|
|
reinterpret_cast<Factory>(&Make)
|
|
);
|
|
Check_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::TerminateClass()
|
|
{
|
|
Check_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
|
|
Check_Pointer(s_Heap);
|
|
gos_DestroyMemoryHeap(s_Heap);
|
|
s_Heap = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::GridElement::GridElement(
|
|
ClassData *class_data,
|
|
Stuff::MemoryStream *stream,
|
|
int version,
|
|
ShapeHolder shapes
|
|
):
|
|
ListElement(class_data, stream, version, shapes)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(stream);
|
|
|
|
if (version>=11)
|
|
*stream >> m_rowCellCount >> m_columnCellCount;
|
|
else
|
|
{
|
|
int row, col;
|
|
*stream >> row >> col;
|
|
Verify(static_cast<unsigned>(row) <= 255);
|
|
Verify(static_cast<unsigned>(col) <= 255);
|
|
m_rowCellCount = static_cast<BYTE>(row);
|
|
m_columnCellCount = static_cast<BYTE>(col);
|
|
}
|
|
*stream >> m_rowCellSize >> m_columnCellSize >> m_rowOffset >> m_columnOffset;
|
|
|
|
unsigned index = (GetCullMode() == NeverCullMode);
|
|
index |= IsMatrixDirty() ? 2 : 0;
|
|
Verify(index < 4);
|
|
m_sync = SyncMethods[index];
|
|
|
|
m_cameraCull = CullMethods.m_cameraCull;
|
|
m_rayCull = CullMethods.m_rayCull;
|
|
m_sphereTest = CullMethods.m_sphereTest;
|
|
|
|
index = (m_state>>DrawStateBit) & DrawStateMask;
|
|
Verify(index < DrawStateCount);
|
|
m_draw = DrawMethods[index];
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::GridElement::GridElement(
|
|
BYTE rowSize,
|
|
BYTE columnSize,
|
|
Stuff::Scalar row_offset,
|
|
Stuff::Scalar column_offset,
|
|
Stuff::Scalar total_row_size,
|
|
Stuff::Scalar total_column_size,
|
|
ClassData *class_data
|
|
):
|
|
ListElement(class_data)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
m_rowCellCount = rowSize;
|
|
m_columnCellCount = columnSize;
|
|
m_rowOffset = row_offset;
|
|
m_columnOffset = column_offset;
|
|
m_rowCellSize = total_row_size/m_rowCellCount;
|
|
m_columnCellSize = total_column_size/m_columnCellCount;
|
|
|
|
Verify(rowSize*columnSize < 65536);
|
|
m_activeChildren = static_cast<WORD>(rowSize*columnSize);
|
|
SetSize(m_activeChildren);
|
|
|
|
unsigned index = (GetCullMode() == NeverCullMode);
|
|
index |= IsMatrixDirty() ? 2 : 0;
|
|
Verify(index < 4);
|
|
m_sync = SyncMethods[index];
|
|
|
|
m_cameraCull = CullMethods.m_cameraCull;
|
|
m_rayCull = CullMethods.m_rayCull;
|
|
m_sphereTest = CullMethods.m_sphereTest;
|
|
|
|
index = (m_state>>DrawStateBit) & DrawStateMask;
|
|
Verify(index < DrawStateCount);
|
|
m_draw = DrawMethods[index];
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::GridElement::~GridElement()
|
|
{
|
|
Check_Object(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::GridElement*
|
|
ElementRenderer::GridElement::Make(
|
|
Stuff::MemoryStream *stream,
|
|
int version,
|
|
ShapeHolder shapes
|
|
)
|
|
{
|
|
Check_Object(stream);
|
|
|
|
gos_PushCurrentHeap(s_Heap);
|
|
GridElement *element = new GridElement(DefaultData, stream, version, shapes);
|
|
gos_PopCurrentHeap();
|
|
|
|
return element;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::Save(Stuff::MemoryStream *stream)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(stream);
|
|
BaseClass::Save(stream);
|
|
|
|
*stream << m_rowCellCount << m_columnCellCount
|
|
<< m_rowCellSize << m_columnCellSize
|
|
<< m_rowOffset << m_columnOffset;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::AttachIndexedChild(
|
|
BYTE row,
|
|
BYTE column,
|
|
Element *element
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Verify(row*m_columnCellCount+column < m_list.GetLength());
|
|
|
|
m_list[row*m_columnCellCount+column] = element;
|
|
|
|
SetParentElement(element, this);
|
|
|
|
if (element->GetCullMode() != AlwaysCullMode)
|
|
{
|
|
if (element->m_localOBB.sphereRadius > 0.0f || element->AreBoundsWrong())
|
|
element->SetVolumeCullMode();
|
|
else
|
|
element->SetNeverCullMode();
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
WORD
|
|
ElementRenderer::GridElement::FindElementIndex(
|
|
Stuff::Scalar row,
|
|
Stuff::Scalar column
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
column -= m_columnOffset;
|
|
row -= m_rowOffset;
|
|
column /= m_columnCellSize;
|
|
row /= m_rowCellSize;
|
|
if (column>=0.0f && column<m_columnCellCount && row>=0.0f && row<m_rowCellCount)
|
|
{
|
|
WORD index =
|
|
static_cast<WORD>(
|
|
Stuff::Truncate_Float_To_Byte(row)*m_columnCellCount + Stuff::Truncate_Float_To_Byte(column)
|
|
);
|
|
Verify(index < m_list.GetLength());
|
|
return index;
|
|
}
|
|
return static_cast<WORD>(m_list.GetLength());
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::SetSize(WORD max_size)
|
|
{
|
|
Check_Object(this);
|
|
m_list.SetLength(max_size);
|
|
m_activeChildren = max_size;
|
|
for (WORD i=0; i<max_size; ++i)
|
|
m_list[i] = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::SetSize(BYTE rowSize, BYTE columnSize)
|
|
{
|
|
Check_Object(this);
|
|
|
|
if(rowSize != m_rowCellCount || columnSize!= m_columnCellCount)
|
|
{
|
|
m_rowCellCount = rowSize;
|
|
m_columnCellCount = columnSize;
|
|
SetSize(static_cast<WORD>(m_rowCellCount*m_columnCellCount));
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::GetDimensions(
|
|
Stuff::Scalar *row_offset,
|
|
Stuff::Scalar *column_offset,
|
|
Stuff::Scalar *row_cell_size,
|
|
Stuff::Scalar *column_cell_size
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(row_offset);
|
|
Check_Pointer(column_offset);
|
|
Check_Pointer(row_cell_size);
|
|
Check_Pointer(column_cell_size);
|
|
|
|
*row_offset = m_rowOffset;
|
|
*column_offset = m_columnOffset;
|
|
*row_cell_size = m_rowCellSize;
|
|
*column_cell_size = m_columnCellSize;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::SetSyncState()
|
|
{
|
|
Check_Object(this);
|
|
|
|
Verify( GetCullMode() == RootMode || GetCullMode() == NeverCullMode );
|
|
Verify(!IsSyncDeferred() && !AreBoundsWrong());
|
|
|
|
unsigned index = (GetCullMode() == NeverCullMode);
|
|
index |= IsMatrixDirty() ? 2 : 0;
|
|
Verify(index < 4);
|
|
|
|
m_sync = SyncMethods[index];
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::SetCullState()
|
|
{
|
|
Check_Object(this);
|
|
m_cameraCull = CullMethods.m_cameraCull;
|
|
m_rayCull = CullMethods.m_rayCull;
|
|
m_sphereTest = CullMethods.m_sphereTest;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::SetDrawState()
|
|
{
|
|
Check_Object(this);
|
|
unsigned index = (m_state>>DrawStateBit) & DrawStateMask;
|
|
Verify(index < DrawStateCount);
|
|
m_draw = DrawMethods[index];
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
ElementRenderer::GridElement::CastCulledRay(CollisionQuery *query)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(query);
|
|
Verify(!query->m_data);
|
|
|
|
//
|
|
//----------------------
|
|
// Test all the children
|
|
//----------------------
|
|
//
|
|
if (IterateLine(query, TestCell))
|
|
{
|
|
if (!query->m_data)
|
|
query->m_data = m_data;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::Element*
|
|
ElementRenderer::GridElement::FindSmallestElementContainingCulled(SphereTest *test)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(test);
|
|
|
|
//
|
|
//------------------
|
|
// Draw our children
|
|
//------------------
|
|
//
|
|
Element *result = this;
|
|
for (int i=0; i<m_activeChildren; ++i)
|
|
{
|
|
Element *element = m_list[i];
|
|
Check_Object(element);
|
|
Element *temp = element->FindSmallestElementContaining(test);
|
|
if (temp)
|
|
result = temp;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void*
|
|
ElementRenderer::GridElement::TestCell(
|
|
GridElement *grid,
|
|
WORD cell,
|
|
CollisionQuery *query,
|
|
Stuff::Scalar enter,
|
|
Stuff::Scalar leave
|
|
)
|
|
{
|
|
Check_Object(grid);
|
|
Check_Object(query);
|
|
Verify(cell < grid->m_activeChildren);
|
|
|
|
Element *element = grid->m_list[cell];
|
|
Check_Object(element);
|
|
return reinterpret_cast<void*>(element->CastRay(query));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
inline static bool
|
|
Trim(
|
|
Stuff::Scalar dot,
|
|
Stuff::Scalar separation,
|
|
Stuff::Scalar *enter,
|
|
Stuff::Scalar *leave
|
|
)
|
|
{
|
|
Check_Pointer(enter);
|
|
Check_Pointer(leave);
|
|
Verify(Stuff::Small_Enough(dot, 1.0f));
|
|
if (dot > Stuff::SMALL)
|
|
{
|
|
Stuff::Scalar distance = -separation / dot - Stuff::SMALL;
|
|
if (distance < *leave)
|
|
*leave = distance;
|
|
return *enter <= *leave;
|
|
}
|
|
else if (dot < -Stuff::SMALL)
|
|
{
|
|
Stuff::Scalar distance = -separation / dot + Stuff::SMALL;
|
|
if (distance > *enter)
|
|
*enter = distance;
|
|
return *enter <= *leave;
|
|
}
|
|
else
|
|
return separation <= Stuff::SMALL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
inline static bool
|
|
Leave_Trim(
|
|
Stuff::Scalar dot,
|
|
Stuff::Scalar separation,
|
|
Stuff::Scalar *leave
|
|
)
|
|
{
|
|
Check_Pointer(leave);
|
|
Verify(Stuff::Small_Enough(dot, 1.0f));
|
|
if (dot > Stuff::SMALL)
|
|
{
|
|
Stuff::Scalar distance = -separation / dot;
|
|
if (distance < *leave)
|
|
{
|
|
*leave = distance;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void*
|
|
ElementRenderer::GridElement::IterateLine(
|
|
CollisionQuery *query,
|
|
CellTest call_back
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(query);
|
|
Check_Pointer(call_back);
|
|
Verify(query->m_line->m_length >= 0.0f);
|
|
|
|
#if defined(SPEW_CULL_INFO)
|
|
int tested=0;
|
|
#endif
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Find the cell coordinates of the the beginning and end of the m_line
|
|
//-------------------------------------------------------------------
|
|
//
|
|
Stuff::Scalar x_scale = 1.0f / m_columnCellSize;
|
|
Stuff::Scalar z_scale = 1.0f / m_rowCellSize;
|
|
Verify(Stuff::Close_Enough(x_scale, z_scale));
|
|
Check_Object(query->m_line);
|
|
Stuff::Line3D *line = query->m_line;
|
|
Stuff::Scalar x_origin = (line->m_origin.x - m_columnOffset) * x_scale;
|
|
Stuff::Scalar z_origin = (line->m_origin.z - m_rowOffset) * z_scale;
|
|
Stuff::Point3D end;
|
|
line->FindEnd(&end);
|
|
Stuff::Scalar x_end = (end.x - m_columnOffset) * x_scale;
|
|
Stuff::Scalar z_end = (end.z - m_rowOffset) * z_scale;
|
|
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// If the m_line is within a single cell, just test that one. If the cell is
|
|
// outside the grid boundaries, return no hit. We don't use our Truncate
|
|
// functions here because we do not know the extents of the line we are testing
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
BYTE x = static_cast<BYTE>(x_origin);
|
|
BYTE z = static_cast<BYTE>(z_origin);
|
|
if (x == static_cast<BYTE>(x_end) && z == static_cast<BYTE>(z_end))
|
|
{
|
|
#if defined(SPEW_CULL_INFO)
|
|
SPEW((SPEW_CULL_INFO, "single cell test"));
|
|
#endif
|
|
if (x < m_columnCellCount && z < m_rowCellCount)
|
|
return
|
|
(*call_back)(
|
|
this,
|
|
static_cast<WORD>(z*m_columnCellCount + x),
|
|
query,
|
|
0,
|
|
line->m_length
|
|
);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// The m_line crosses cells, so we first have to clip it to the grid
|
|
// boundaries. We will treat the box boundaries as four plane equations
|
|
//----------------------------------------------------------------------
|
|
//
|
|
Stuff::Scalar enter = 0.0f;
|
|
Stuff::Scalar leave = line->m_length;
|
|
if (
|
|
!Trim(
|
|
-line->m_direction.x,
|
|
m_columnOffset - line->m_origin.x,
|
|
&enter,
|
|
&leave
|
|
)
|
|
)
|
|
{
|
|
#if defined(SPEW_CULL_INFO)
|
|
SPEW((SPEW_CULL_INFO, "Line doesn't hit grid"));
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
if (
|
|
!Trim(
|
|
line->m_direction.x,
|
|
line->m_origin.x - (m_columnOffset + m_columnCellCount*m_columnCellSize),
|
|
&enter,
|
|
&leave
|
|
)
|
|
)
|
|
{
|
|
#if defined(SPEW_CULL_INFO)
|
|
SPEW((SPEW_CULL_INFO, "Line doesn't hit grid"));
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
if (
|
|
!Trim(
|
|
-line->m_direction.z,
|
|
m_rowOffset - line->m_origin.z,
|
|
&enter,
|
|
&leave
|
|
)
|
|
)
|
|
{
|
|
#if defined(SPEW_CULL_INFO)
|
|
SPEW((SPEW_CULL_INFO, "Line doesn't hit grid"));
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
if (
|
|
!Trim(
|
|
line->m_direction.z,
|
|
line->m_origin.z - (m_rowOffset + m_rowCellCount*m_rowCellSize),
|
|
&enter,
|
|
&leave
|
|
)
|
|
)
|
|
{
|
|
#if defined(SPEW_CULL_INFO)
|
|
SPEW((SPEW_CULL_INFO, "Line doesn't hit grid"));
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
// Now project the origin and end of the m_line in cell space and cast those
|
|
// into the integer indices we need. The clamps are there to deal with error
|
|
// not caught by trim
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
line->Project(enter, &end);
|
|
x_origin = (end.x - m_columnOffset) * x_scale;
|
|
z_origin = (end.z - m_rowOffset) * z_scale;
|
|
if (x_origin <= 0.0f)
|
|
x = 0;
|
|
else if (x_origin >= m_columnCellCount)
|
|
x = static_cast<BYTE>(m_columnCellCount-1);
|
|
else
|
|
x = Stuff::Truncate_Float_To_Byte(x_origin);
|
|
if (z_origin <= 0.0f)
|
|
z = 0;
|
|
else if (z_origin >= m_rowCellCount)
|
|
z = static_cast<BYTE>(m_rowCellCount-1);
|
|
else
|
|
z = Stuff::Truncate_Float_To_Byte(z_origin);
|
|
Verify(x < m_columnCellCount && z < m_rowCellCount);
|
|
|
|
line->Project(leave, &end);
|
|
x_end = (end.x - m_columnOffset) * x_scale;
|
|
z_end = (end.z - m_rowOffset) * z_scale;
|
|
BYTE last_x, last_z;
|
|
if (x_end <= 0.0f)
|
|
last_x = 0;
|
|
else if (x_end >= m_columnCellCount)
|
|
last_x = static_cast<BYTE>(m_columnCellCount-1);
|
|
else
|
|
last_x = Stuff::Truncate_Float_To_Byte(x_end);
|
|
if (z_end <= 0.0f)
|
|
last_z = 0;
|
|
else if (z_end >= m_rowCellCount)
|
|
last_z = static_cast<BYTE>(m_rowCellCount-1);
|
|
else
|
|
last_z = Stuff::Truncate_Float_To_Byte(z_end);
|
|
Verify(last_x < m_columnCellCount && last_z < m_rowCellCount);
|
|
|
|
//
|
|
//--------------------------------
|
|
// Crawl over the cells one by one
|
|
//--------------------------------
|
|
//
|
|
Stuff::Scalar cell_leave = enter;
|
|
while (true)
|
|
{
|
|
#if defined(SPEW_CULL_INFO)
|
|
++tested;
|
|
#endif
|
|
Verify(x < m_columnCellCount && z < m_rowCellCount);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Clip the m_line to the x boundaries of the current cell and remember
|
|
// way to leave
|
|
//-------------------------------------------------------------------
|
|
//
|
|
enter = cell_leave;
|
|
Stuff::Scalar x_leave = leave;
|
|
int dx=0;
|
|
if (
|
|
Leave_Trim(
|
|
-line->m_direction.x,
|
|
m_columnOffset + x*m_columnCellSize - line->m_origin.x,
|
|
&x_leave
|
|
)
|
|
)
|
|
dx = -1;
|
|
if (
|
|
Leave_Trim(
|
|
line->m_direction.x,
|
|
line->m_origin.x - (m_columnOffset + (x+1)*m_columnCellSize),
|
|
&x_leave
|
|
)
|
|
)
|
|
dx = 1;
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Clip the m_line to the z boundaries of the current cell and remember
|
|
// way to leave
|
|
//-------------------------------------------------------------------
|
|
//
|
|
int dz=0;
|
|
Stuff::Scalar z_leave = leave;
|
|
if (
|
|
Leave_Trim(
|
|
-line->m_direction.z,
|
|
m_rowOffset + z*m_rowCellSize - line->m_origin.z,
|
|
&z_leave
|
|
)
|
|
)
|
|
dz = -1;
|
|
if (
|
|
Leave_Trim(
|
|
line->m_direction.z,
|
|
line->m_origin.z - (m_rowOffset + (z+1)*m_rowCellSize),
|
|
&z_leave
|
|
)
|
|
)
|
|
dz = 1;
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// Pick which axis we leave on first. Make sure we handle corners
|
|
// appropriately
|
|
//----------------------------------------------------------------
|
|
//
|
|
if (x_leave < z_leave-Stuff::SMALL)
|
|
{
|
|
dz = 0;
|
|
cell_leave = x_leave;
|
|
}
|
|
if (z_leave < x_leave-Stuff::SMALL)
|
|
{
|
|
dx = 0;
|
|
cell_leave = z_leave;
|
|
}
|
|
else
|
|
cell_leave = x_leave;
|
|
|
|
//
|
|
//--------------------------------------------------------
|
|
// See if there is anything to hit, and if so, we are done
|
|
//--------------------------------------------------------
|
|
//
|
|
Stuff::Scalar old_length = query->m_line->m_length;
|
|
void *result =
|
|
(*call_back)(
|
|
this,
|
|
static_cast<WORD>(z*m_columnCellCount + x),
|
|
query,
|
|
enter,
|
|
cell_leave
|
|
);
|
|
if (result != NULL)
|
|
{
|
|
#if defined(SPEW_CULL_INFO)
|
|
SPEW((SPEW_CULL_INFO, "Hit! %d of %d cells tested", tested, m_columnCellCount*m_rowCellCount));
|
|
#endif
|
|
if (query->m_line->m_length <= cell_leave)
|
|
return result;
|
|
else
|
|
query->m_line->m_length = old_length;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// If we have reached the end, we are done, otherwise move to the next
|
|
// cell
|
|
//--------------------------------------------------------------------
|
|
//
|
|
if (x == last_x && z == last_z || !dx && !dz)
|
|
break;
|
|
x = static_cast<BYTE>(x + dx);
|
|
z = static_cast<BYTE>(z + dz);
|
|
}
|
|
|
|
|
|
//
|
|
//-------------------------
|
|
// We couldn't hit anything
|
|
//-------------------------
|
|
//
|
|
#if defined(SPEW_CULL_INFO)
|
|
SPEW((SPEW_CULL_INFO, "Missed: %d of %d cells tested", tested, m_columnCellCount*m_rowCellCount));
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
ElementRenderer::GridElement::GridCullMethod(CameraElement *camera)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(camera);
|
|
|
|
return BaseClass::NeverCullMethod(camera);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
ElementRenderer::GridElement::GridSphereTestMethod(SphereTest *query)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(query);
|
|
|
|
return BaseClass::NeverSphereTestMethod(query);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
ElementRenderer::GridElement::GridRayCullMethod(CollisionQuery *query)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(query);
|
|
Verify(!query->m_data);
|
|
|
|
return BaseClass::NeverRayCullMethod(query);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::InheritDrawMethod(
|
|
CameraElement *camera,
|
|
const StateChange *inherited_state,
|
|
int culling_state
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(inherited_state);
|
|
Check_Object(camera);
|
|
Verify(culling_state != -1);
|
|
|
|
//
|
|
//----------------------
|
|
// Draw all the children
|
|
//----------------------
|
|
//
|
|
Stuff::Point3D theCorners[4];
|
|
|
|
theCorners[0].y = 0.0f;
|
|
theCorners[1].y = 0.0f;
|
|
theCorners[2].y = 0.0f;
|
|
theCorners[3].y = 0.0f;
|
|
|
|
const Stuff::Point3D *cullPoints = camera->GetCullPoints();
|
|
|
|
int pxmin, pxmax, pzmin, pzmax, in[5], out[4];
|
|
int i, j, k;
|
|
|
|
pxmin = pxmax = pzmin = pzmax = 0;
|
|
|
|
for(i=1;i<5;i++)
|
|
{
|
|
if(cullPoints[i].x < cullPoints[pxmin].x)
|
|
{
|
|
pxmin = i;
|
|
}
|
|
if(cullPoints[i].x > cullPoints[pxmax].x)
|
|
{
|
|
pxmax = i;
|
|
}
|
|
if(cullPoints[i].z < cullPoints[pzmin].z)
|
|
{
|
|
pzmin = i;
|
|
}
|
|
if(cullPoints[i].z > cullPoints[pzmax].z)
|
|
{
|
|
pzmax = i;
|
|
}
|
|
}
|
|
|
|
int inCount=0, outCount=0;
|
|
|
|
in[inCount++] = pzmin;
|
|
|
|
|
|
if(pzmin!=pxmin)
|
|
{
|
|
in[inCount++] = pxmin;
|
|
|
|
if(pxmin!=pzmax)
|
|
{
|
|
in[inCount++] = pzmax;
|
|
|
|
if(pzmax!=pxmax && pxmax!=pzmin)
|
|
{
|
|
in[inCount++] = pxmax;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
in[inCount++] = pxmax;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
in[inCount++] = pzmax;
|
|
Verify(pzmax!=pxmax && pxmax!=pzmin);
|
|
in[inCount++] = pxmax;
|
|
}
|
|
|
|
Verify(inCount<5);
|
|
|
|
for(i=0;i<5;i++)
|
|
{
|
|
for(j=0;j<inCount;j++)
|
|
{
|
|
if(i==in[j])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(j==inCount)
|
|
{
|
|
out[outCount++] = i;
|
|
}
|
|
}
|
|
|
|
Verify(outCount<3);
|
|
|
|
for(i=0;i<outCount;i++)
|
|
{
|
|
for(j=0;j<inCount;j++)
|
|
{
|
|
if(Stuff::Close_Enough(cullPoints[out[i]], cullPoints[in[j]]))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(j<inCount)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for(j=0;j<inCount;j++)
|
|
{
|
|
int end = j+1;
|
|
|
|
if(end==inCount)
|
|
{
|
|
end = 0;
|
|
}
|
|
|
|
Stuff::Vector3D vc;
|
|
|
|
vc.Cross(cullPoints[out[i]], cullPoints[in[j]], cullPoints[in[end]]);
|
|
|
|
if(vc.y > 0.0f)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(j<inCount)
|
|
{
|
|
for(k=inCount;k>j+1;k--)
|
|
{
|
|
in[k] = in[k-1];
|
|
}
|
|
in[j+1] = out[i];
|
|
inCount++;
|
|
}
|
|
}
|
|
|
|
#ifdef _ARMOR
|
|
//
|
|
// Checking for a convex hull
|
|
//
|
|
for(i=0;i<inCount;i++)
|
|
{
|
|
int next = (i+1)%inCount;
|
|
int nextAfter = (i+2)%inCount;
|
|
|
|
Stuff::Vector3D vc;
|
|
vc.Cross(cullPoints[in[next]], cullPoints[in[i]], cullPoints[in[nextAfter]]);
|
|
|
|
Verify(vc.y >= 0.0f);
|
|
}
|
|
#endif
|
|
|
|
#ifdef SPEW_CULL_INFO
|
|
int d = 0;
|
|
#endif
|
|
|
|
const Stuff::Scalar theCageCorrector = 4.5f;
|
|
|
|
int minZ, maxZ, minX, maxX;
|
|
|
|
minZ = (int)floor((cullPoints[pzmin].z-m_rowOffset-theCageCorrector)/m_rowCellSize);
|
|
if(minZ<0)
|
|
{
|
|
minZ = 0;
|
|
}
|
|
maxZ = (int)ceil((cullPoints[pzmax].z-m_rowOffset+theCageCorrector)/m_rowCellSize);
|
|
if(maxZ > m_rowCellCount)
|
|
{
|
|
maxZ = m_rowCellCount;
|
|
}
|
|
|
|
theCorners[0].z = m_rowOffset + minZ*m_rowCellSize;
|
|
theCorners[1].z = theCorners[0].z;
|
|
theCorners[2].z = theCorners[0].z + m_rowCellSize;
|
|
theCorners[3].z = theCorners[2].z;
|
|
|
|
minX = (int)floor((cullPoints[pxmin].x-m_columnOffset-theCageCorrector)/m_columnCellSize);
|
|
if(minX<0)
|
|
{
|
|
minX = 0;
|
|
}
|
|
maxX = (int)ceil((cullPoints[pxmax].x-m_columnOffset+theCageCorrector)/m_columnCellSize);
|
|
if(maxX > m_columnCellCount)
|
|
{
|
|
maxX = m_columnCellCount;
|
|
}
|
|
|
|
for (j=minZ; j<maxZ; ++j)
|
|
{
|
|
|
|
theCorners[0].x = m_columnOffset + minX*m_columnCellSize;
|
|
theCorners[1].x = theCorners[0].x + m_columnCellSize;
|
|
theCorners[2].x = theCorners[1].x;
|
|
theCorners[3].x = theCorners[0].x;
|
|
|
|
// bool inOrOut = false;
|
|
for (i=minX; i<maxX; ++i)
|
|
{
|
|
/*
|
|
if(inOrOut==false)
|
|
{
|
|
//
|
|
// Check the x-max side
|
|
//
|
|
int end, k, p1 = -1, p2 = -1;
|
|
for(k=0;k<inCount;++k)
|
|
{
|
|
end = k+1;
|
|
|
|
if(end>=inCount)
|
|
{
|
|
end = 0;
|
|
}
|
|
|
|
if(cullPoints[in[end]].z > cullPoints[in[k]].z)
|
|
{
|
|
if(p1 < 0 && theCorners[1].z > cullPoints[in[k]].z && theCorners[1].z < cullPoints[in[end]].z)
|
|
{
|
|
p1 = k;
|
|
}
|
|
if(p2 < 0 && theCorners[2].z > cullPoints[in[k]].z && theCorners[2].z < cullPoints[in[end]].z)
|
|
{
|
|
p2 = k;
|
|
}
|
|
}
|
|
}
|
|
if(p1<0 && p2<0)
|
|
{
|
|
if(theCorners[1].x > cullPoints[pxmin].x)
|
|
{
|
|
inOrOut = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
Stuff::Vector3D vc;
|
|
if(p1==p2)
|
|
{
|
|
end = p1+1;
|
|
|
|
if(end>=inCount)
|
|
{
|
|
end = 0;
|
|
}
|
|
|
|
vc.Cross(theCorners[1], cullPoints[in[p1]], cullPoints[in[end]]);
|
|
|
|
if(vc.y < 0.0f)
|
|
{
|
|
inOrOut = true;
|
|
}
|
|
else
|
|
{
|
|
end = p2+1;
|
|
|
|
if(end>=inCount)
|
|
{
|
|
end = 0;
|
|
}
|
|
|
|
vc.Cross(theCorners[2], cullPoints[in[p2]], cullPoints[in[end]]);
|
|
|
|
if(vc.y < 0.0f)
|
|
{
|
|
inOrOut = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(p2<0)
|
|
{
|
|
end = p1+1;
|
|
|
|
if(end>=inCount)
|
|
{
|
|
end = 0;
|
|
}
|
|
|
|
vc.Cross(theCorners[1], cullPoints[in[p1]], cullPoints[in[end]]);
|
|
|
|
if(vc.y < 0.0f)
|
|
{
|
|
inOrOut = true;
|
|
}
|
|
}
|
|
|
|
if(p1<0)
|
|
{
|
|
end = p2+1;
|
|
|
|
if(end>=inCount)
|
|
{
|
|
end = 0;
|
|
}
|
|
|
|
vc.Cross(theCorners[2], cullPoints[in[p2]], cullPoints[in[end]]);
|
|
|
|
if(vc.y < 0.0f)
|
|
{
|
|
inOrOut = true;
|
|
}
|
|
}
|
|
if(p1>=0 && p2>=0)
|
|
{
|
|
Verify(p2>p1);
|
|
for(k=p1+1;k<p2+1;k++)
|
|
{
|
|
if(theCorners[1].x > cullPoints[in[k]].x)
|
|
{
|
|
inOrOut = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check the x-max side
|
|
//
|
|
}
|
|
|
|
if(inOrOut==true)
|
|
*/
|
|
{
|
|
Element *element = m_list[j*m_columnCellCount+i];
|
|
Check_Object(element);
|
|
|
|
#ifdef _ARMOR
|
|
if(element->GetCullMode() == VolumeCullMode)
|
|
{
|
|
Verify(element->GetWorldOBB().localToParent.entries[3] >= theCorners[0].x);
|
|
Verify(element->GetWorldOBB().localToParent.entries[3] <= theCorners[1].x);
|
|
Verify(element->GetWorldOBB().localToParent.entries[11] >= theCorners[0].z);
|
|
Verify(element->GetWorldOBB().localToParent.entries[11] <= theCorners[3].z);
|
|
}
|
|
#endif
|
|
|
|
camera->DrawElement(element, inherited_state);
|
|
|
|
#ifdef SPEW_CULL_INFO
|
|
d++;
|
|
#endif
|
|
}
|
|
|
|
theCorners[0].x += m_columnCellSize;
|
|
theCorners[1].x += m_columnCellSize;
|
|
theCorners[2].x += m_columnCellSize;
|
|
theCorners[3].x += m_columnCellSize;
|
|
}
|
|
theCorners[0].z += m_rowCellSize;
|
|
theCorners[1].z += m_rowCellSize;
|
|
theCorners[2].z += m_rowCellSize;
|
|
theCorners[3].z += m_rowCellSize;
|
|
}
|
|
#ifdef SPEW_CULL_INFO
|
|
SPEW((SPEW_CULL_INFO, "Drawn: %d Culled: %d", d, (m_rowCellCount*m_columnCellCount)-d));
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::GridElement::OverrideDrawMethod(
|
|
CameraElement *camera,
|
|
const StateChange *inherited_state,
|
|
int culling_state
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(inherited_state);
|
|
Check_Object(camera);
|
|
Verify(culling_state != -1);
|
|
|
|
//
|
|
//-------------------
|
|
// Mix the properties
|
|
//-------------------
|
|
//
|
|
Check_Object(m_stateChange);
|
|
StateChange mixed;
|
|
mixed.Mix(*inherited_state, *m_stateChange);
|
|
MixLights(
|
|
mixed.m_lights,
|
|
inherited_state->m_lights,
|
|
m_stateChange->m_lights
|
|
);
|
|
|
|
//
|
|
//----------------------
|
|
// Draw all the children
|
|
//----------------------
|
|
//
|
|
Stuff::Point3D theCorners[4];
|
|
|
|
theCorners[0].y = 0.0f;
|
|
theCorners[1].y = 0.0f;
|
|
theCorners[2].y = 0.0f;
|
|
theCorners[3].y = 0.0f;
|
|
|
|
const Stuff::Point3D *cullPoints = camera->GetCullPoints();
|
|
|
|
int pxmin, pxmax, pzmin, pzmax, in[5], out[4];
|
|
int i, j, k;
|
|
|
|
pxmin = pxmax = pzmin = pzmax = 0;
|
|
|
|
for(i=1;i<5;i++)
|
|
{
|
|
if(cullPoints[i].x < cullPoints[pxmin].x)
|
|
{
|
|
pxmin = i;
|
|
}
|
|
if(cullPoints[i].x > cullPoints[pxmax].x)
|
|
{
|
|
pxmax = i;
|
|
}
|
|
if(cullPoints[i].z < cullPoints[pzmin].z)
|
|
{
|
|
pzmin = i;
|
|
}
|
|
if(cullPoints[i].z > cullPoints[pzmax].z)
|
|
{
|
|
pzmax = i;
|
|
}
|
|
}
|
|
|
|
int inCount=0, outCount=0;
|
|
|
|
in[inCount++] = pzmin;
|
|
|
|
|
|
if(pzmin!=pxmin)
|
|
{
|
|
in[inCount++] = pxmin;
|
|
|
|
if(pxmin!=pzmax)
|
|
{
|
|
in[inCount++] = pzmax;
|
|
|
|
if(pzmax!=pxmax && pxmax!=pzmin)
|
|
{
|
|
in[inCount++] = pxmax;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
in[inCount++] = pxmax;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
in[inCount++] = pzmax;
|
|
Verify(pzmax!=pxmax && pxmax!=pzmin);
|
|
in[inCount++] = pxmax;
|
|
}
|
|
|
|
Verify(inCount<5);
|
|
|
|
for(i=0;i<5;i++)
|
|
{
|
|
for(j=0;j<inCount;j++)
|
|
{
|
|
if(i==in[j])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(j==inCount)
|
|
{
|
|
out[outCount++] = i;
|
|
}
|
|
}
|
|
|
|
Verify(outCount<3);
|
|
|
|
for(i=0;i<outCount;i++)
|
|
{
|
|
for(j=0;j<inCount;j++)
|
|
{
|
|
if(Stuff::Close_Enough(cullPoints[out[i]], cullPoints[in[j]]))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(j<inCount)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for(j=0;j<inCount;j++)
|
|
{
|
|
int end = j+1;
|
|
|
|
if(end==inCount)
|
|
{
|
|
end = 0;
|
|
}
|
|
|
|
Stuff::Vector3D vc;
|
|
|
|
vc.Cross(cullPoints[out[i]], cullPoints[in[j]], cullPoints[in[end]]);
|
|
|
|
if(vc.y > 0.0f)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(j<inCount)
|
|
{
|
|
for(k=inCount;k>j+1;k--)
|
|
{
|
|
in[k] = in[k-1];
|
|
}
|
|
in[j+1] = out[i];
|
|
inCount++;
|
|
}
|
|
}
|
|
|
|
#ifdef SPEW_CULL_INFO
|
|
int d = 0;
|
|
#endif
|
|
|
|
int minZ, maxZ, minX, maxX;
|
|
|
|
minZ = (int)floor((cullPoints[pzmin].z-m_rowOffset)/m_rowCellSize);
|
|
if(minZ<0)
|
|
{
|
|
minZ = 0;
|
|
}
|
|
maxZ = (int)ceil((cullPoints[pzmax].z-m_rowOffset)/m_rowCellSize);
|
|
if(maxZ > m_rowCellCount)
|
|
{
|
|
maxZ = m_rowCellCount;
|
|
}
|
|
|
|
theCorners[0].z = m_rowOffset + minZ*m_rowCellSize;
|
|
theCorners[1].z = theCorners[0].z;
|
|
theCorners[2].z = theCorners[0].z + m_rowCellSize;
|
|
theCorners[3].z = theCorners[2].z;
|
|
|
|
minX = (int)floor((cullPoints[pxmin].x-m_columnOffset)/m_columnCellSize);
|
|
if(minX<0)
|
|
{
|
|
minX = 0;
|
|
}
|
|
maxX = (int)ceil((cullPoints[pxmax].x-m_columnOffset)/m_columnCellSize);
|
|
if(maxX > m_columnCellCount)
|
|
{
|
|
maxX = m_columnCellCount;
|
|
}
|
|
|
|
for (j=minZ; j<maxZ; ++j)
|
|
{
|
|
|
|
theCorners[0].x = m_columnOffset + minX*m_columnCellSize;
|
|
theCorners[1].x = theCorners[0].x + m_columnCellSize;
|
|
theCorners[2].x = theCorners[1].x;
|
|
theCorners[3].x = theCorners[0].x;
|
|
|
|
for (i=minX; i<maxX; ++i)
|
|
{
|
|
if(1)
|
|
{
|
|
Element *element = m_list[j*m_columnCellCount+i];
|
|
Check_Object(element);
|
|
camera->DrawElement(element, inherited_state);
|
|
#ifdef SPEW_CULL_INFO
|
|
d++;
|
|
}
|
|
else
|
|
{
|
|
nd++;
|
|
#endif
|
|
}
|
|
|
|
theCorners[0].x += m_rowCellSize;
|
|
theCorners[1].x += m_rowCellSize;
|
|
theCorners[2].x += m_rowCellSize;
|
|
theCorners[3].x += m_rowCellSize;
|
|
}
|
|
theCorners[0].z += m_columnCellSize;
|
|
theCorners[1].z += m_columnCellSize;
|
|
theCorners[2].z += m_columnCellSize;
|
|
theCorners[3].z += m_columnCellSize;
|
|
}
|
|
#ifdef SPEW_CULL_INFO
|
|
SPEW((SPEW_CULL_INFO, "Drawn: %d Culled: %d", d, nd));
|
|
#endif
|
|
}
|