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>
330 lines
8.2 KiB
C++
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;
|
|
}
|