Files
CydandClaude Fable 5 fdd9ac9d97 Initial import: Tesla Release 4.10 (Tesla:BattleTech & Tesla:Red Planet)
Archival snapshot of the Virtual World Entertainment Tesla cockpit
software, 1994-1996: MUNGA engine and L4 pod layer source (Borland
C++ 5.0), BT/RP game code, and game content (models, audio, maps,
gauges, Division renderer data). Includes third-party libraries:
Division dVS/DPL graphics, HMI SOS audio, WATTCP networking.

Files are preserved byte-for-byte (.gitattributes disables all
line-ending conversion). README.md documents the layout, target
hardware, and toolchain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 13:21:58 -05:00

330 lines
8.2 KiB
C++

//===========================================================================//
// File: boxlist.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box based spatialization //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/08/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXLIST_HPP)
# include <boxlist.hpp>
#endif
//#############################################################################
//######################### BoundingBoxListNode #########################
//#############################################################################
MemoryBlock
BoundingBoxListNode::AllocatedMemory(
sizeof(BoundingBoxListNode),
500,
50,
"BoundingBoxList Nodes"
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
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;
}