Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
312 lines
6.9 KiB
C++
312 lines
6.9 KiB
C++
#include "munga.h"
|
|
#pragma hdrstop
|
|
|
|
#include "boxlist.h"
|
|
|
|
//#############################################################################
|
|
//######################### BoundingBoxListNode #########################
|
|
//#############################################################################
|
|
|
|
MemoryBlock *BoundingBoxListNode::GetAllocatedMemory()
|
|
{
|
|
static MemoryBlock allocatedMemory(sizeof(BoundingBoxListNode), 500, 50, "BoundingBoxList Nodes");
|
|
return &allocatedMemory;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
BoundingBoxListNode::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|
|
|
|
//#############################################################################
|
|
//########################### BoundingBoxList ###########################
|
|
//#############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BoundingBoxList::BoundingBoxList()
|
|
{
|
|
root = NULL;
|
|
nodeCount = 0;
|
|
scoreBoard = NULL;
|
|
boundingBoxIndex = NULL;
|
|
isXMajorAxis = True;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BoundingBoxList::~BoundingBoxList()
|
|
{
|
|
if (scoreBoard)
|
|
{
|
|
Unregister_Pointer(scoreBoard);
|
|
delete scoreBoard;
|
|
}
|
|
if (boundingBoxIndex)
|
|
{
|
|
Unregister_Pointer(boundingBoxIndex);
|
|
delete boundingBoxIndex;
|
|
}
|
|
EraseList();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BoundingBoxList::Add(
|
|
BoundingBox* volume,
|
|
const ExtentBox &slice
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(volume);
|
|
|
|
++nodeCount;
|
|
BoundingBoxListNode *node = new BoundingBoxListNode(volume, slice);
|
|
Register_Object(node);
|
|
node->previousNode = root;
|
|
root = node;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BoundingBoxList::Remove(BoundingBox* volume)
|
|
{
|
|
Check(this);
|
|
Check(volume);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Spin through all the boxes until we find the one we are after or until we
|
|
// run off the list
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
BoundingBoxListNode
|
|
*p = NULL,
|
|
*c = root;
|
|
while (c)
|
|
{
|
|
Check(c);
|
|
if (c->boundingBox == volume)
|
|
{
|
|
break;
|
|
}
|
|
p = c;
|
|
c = c->previousNode;
|
|
}
|
|
|
|
//
|
|
//----------------------------------------------
|
|
// Unlink the node from the list if it was found
|
|
//----------------------------------------------
|
|
//
|
|
if (!c)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Check(c);
|
|
if (p)
|
|
{
|
|
Check(p);
|
|
p->previousNode = c->previousNode;
|
|
}
|
|
else
|
|
{
|
|
root = c->previousNode;
|
|
}
|
|
|
|
//
|
|
//-----------------
|
|
// Delete this node
|
|
//-----------------
|
|
//
|
|
--nodeCount;
|
|
Unregister_Object(c);
|
|
delete c;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BoundingBoxList::EraseList()
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
//-----------------------------
|
|
// Delete each node in the list
|
|
//-----------------------------
|
|
//
|
|
BoundingBoxListNode *p = root;
|
|
while (p)
|
|
{
|
|
Check(p);
|
|
BoundingBoxListNode *q = p;
|
|
p = p->previousNode;
|
|
Unregister_Object(q);
|
|
delete q;
|
|
}
|
|
root = NULL;
|
|
nodeCount = 0;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BoundingBox*
|
|
BoundingBoxList::FindBoundingBoxContaining(const Point3D &point)
|
|
{
|
|
Check(this);
|
|
Check(&point);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Spin through each of the boxes in reverse order until we find a box which
|
|
// contains the specified point. It will be default have priority over any
|
|
// boxes put in before it
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
for (BoundingBoxListNode *p=root; p; p = p->previousNode)
|
|
{
|
|
Check(p);
|
|
BoundingBox *box = p->boundingBox;
|
|
Check(box);
|
|
if (box->Contains(point))
|
|
{
|
|
return box;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
BoundingBoxList::FindBoundingBoxesContaining(
|
|
BoundingBox *volume,
|
|
BoundingBoxCollisionList &list
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(volume);
|
|
Check(&list);
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// Spin through each of the boxes in reverse order, looking for
|
|
// intesections between the test volume and the box list
|
|
//-------------------------------------------------------------
|
|
//
|
|
for (BoundingBoxListNode *p=root; p; p = p->previousNode)
|
|
{
|
|
Check(p);
|
|
BoundingBox *box = p->boundingBox;
|
|
Check(box);
|
|
if (box->ExtentBox::Intersects(*volume))
|
|
{
|
|
//
|
|
//----------------------------------------------------------------
|
|
// Build the intersection slice, and make sure that it really does
|
|
// intersect the list box
|
|
//----------------------------------------------------------------
|
|
//
|
|
ExtentBox slice;
|
|
slice.Intersect(*volume, *box);
|
|
if (box->IntersectsBounded(slice))
|
|
{
|
|
|
|
//
|
|
//------------------------------------------------------------
|
|
// It intersects, so add this to the list. If we are out of
|
|
// collisions in the list, we are finished detecting, and just
|
|
// return
|
|
//------------------------------------------------------------
|
|
//
|
|
Verify(list.collisionsLeft);
|
|
list.AddCollisionToList(box, slice);
|
|
if (!list.collisionsLeft)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BoundingBox*
|
|
BoundingBoxList::FindBoundingBoxUnder(
|
|
const Point3D &point,
|
|
Scalar *height
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(&point);
|
|
Check_Pointer(height);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Spin through each of the bounding boxes, keeping track of which box is
|
|
// hit after the shortest distance
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
BoundingBox *best_box = NULL;
|
|
*height = -1.0f;
|
|
for (BoundingBoxListNode *p=root; p; p = p->previousNode)
|
|
{
|
|
Check(p);
|
|
BoundingBox *box = p->boundingBox;
|
|
Check(box);
|
|
|
|
Scalar h = box->FindDistanceBelow(point);
|
|
if (h != -1.0f)
|
|
{
|
|
if (!best_box || *height > h)
|
|
{
|
|
best_box = box;
|
|
*height = h;
|
|
}
|
|
}
|
|
}
|
|
return best_box;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
BoundingBox*
|
|
BoundingBoxList::FindBoundingBoxHitBy(Line *line)
|
|
{
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Spin through each of the boxes, letting each box in turn clip the line
|
|
// lengths
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
BoundingBox *best_box = NULL;
|
|
for (BoundingBoxListNode *p=root; p; p = p->previousNode)
|
|
{
|
|
Check(p);
|
|
BoundingBox *box = p->boundingBox;
|
|
Check(box);
|
|
|
|
Logical h = box->HitBy(line);
|
|
if (h)
|
|
{
|
|
best_box = box;
|
|
}
|
|
}
|
|
return best_box;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
BoundingBoxList::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|