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

673 lines
17 KiB
C++

//===========================================================================//
// File: boxsolid.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box collision subtypes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/11/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(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(ORIGIN_HPP)
# include <origin.hpp>
#endif
#if !defined(LINMTRX_HPP)
# include <linmtrx.hpp>
#endif
#if !defined(LINE_HPP)
# include <line.hpp>
#endif
#if !defined(PLANE_HPP)
# include <plane.hpp>
#endif
#if !defined(VECTOR2D_HPP)
# include <vector2d.hpp>
#endif
//#############################################################################
//######################### RightHandedTile ######################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RightHandedTile::RightHandedTile(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid,
Scalar *corners,
Type type
):
BoxedSolid(extents, type, material, owner, next_solid)
{
Check_Pointer(this);
for (int i=0; i<ELEMENTS(cornerHeight); ++i)
{
cornerHeight[i] = corners[i];
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RightHandedTile::~RightHandedTile()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RightHandedTile::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//-------------------------------------------------------------------
// See if the box hits the upper-right triangle anywhere on its plane
//-------------------------------------------------------------------
//
Point3D p0,p1,p2;
p0.x = maxX;
p0.y = cornerHeight[1];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[0];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[3];
p2.z = maxZ;
Plane plane1(p0, p1, p2);
if (plane1.ContainsSomeOf(extents))
{
//
//-------------------------------------------------------------------
// Make sure the XZ projections of the triangle and the box intersect
//-------------------------------------------------------------------
//
return True;
}
//
//------------------------------------------------------------------
// See if the box hits the lower-left triangle anywhere on its plane
//------------------------------------------------------------------
//
p0.x = minX;
p0.y = cornerHeight[2];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[3];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[0];
p2.z = minZ;
Plane plane2(p0, p1, p2);
if (plane2.ContainsSomeOf(extents))
{
//
//-------------------------------------------------------------------
// Make sure the XZ projections of the triangle and the box intersect
//-------------------------------------------------------------------
//
return True;
}
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RightHandedTile::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(maxY >= point.y);
return FindDistanceBelowBounded(point) <= 0.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
RightHandedTile::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//---------------------------------------------------
// Figure out which triangle the point will reside in
//---------------------------------------------------
//
Scalar rise = maxX - minX;
Scalar run = maxZ - minZ;
Verify(rise > SMALL);
Verify(run > SMALL);
Scalar dx = point.x - minX;
Scalar dz = point.z - minZ;
//
//-----------------------------------------------------------------
// Set up the appropriate triangle based upon which have it lies in
//-----------------------------------------------------------------
//
Point3D p0,p1,p2;
if (dx*run > dz*rise)
{
p0.x = maxX;
p0.y = cornerHeight[1];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[0];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[3];
p2.z = maxZ;
}
else
{
p0.x = minX;
p0.y = cornerHeight[2];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[3];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[0];
p2.z = minZ;
}
//
//---------------------------------------------------------------------
// Make a plane out of the triangle, and have the plane solve for the Y
// coordinate
//---------------------------------------------------------------------
//
Plane plane(p0, p1, p2);
Verify(!Small_Enough(plane.normal.y));
Scalar height = point.y - plane.CalculateY(point.x, point.z);
Check_Fpu();
return height;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
static Scalar
LineHitsTriangle(
Line *line,
const Point3D &p0,
const Point3D &p1,
const Point3D &p2,
Scalar *cosine
)
{
//
//--------------------------------------------------------------------------
// Make the plane out of the three corner points, and figure out how far the
// ray must travel to reach this plane. Try some trivial rejections:
// parallel lines, lines starting outside the halfspace heading away from
// the plane, and lines starting outside the halfspace and heading towards
// the plane but are too far away
//--------------------------------------------------------------------------
//
Plane plane(p0, p1, p2);
Scalar length = line->DistanceTo(plane, cosine);
if (
Small_Enough(*cosine)
|| *cosine > 0.0f && length < 0.0f
|| *cosine < 0.0f && length > line->length
)
{
return -1.0f;
}
//
//--------------------------------------------------------
// Project the impact point and triangle unto the XZ plane
//--------------------------------------------------------
//
Point3D impact;
line->Project(length, &impact);
Vector2DOf<Scalar> proj(impact.x - p0.x, impact.z - p0.z);
Scalar x = p1.x - p0.x;
Scalar z = p2.z - p0.z;
//
//-------------------------------------------------------------------------
// Make sure that the area of the triangle made with the test point and the
// first leg is not negative or greater than the area of the triangle made
// by the two legs. The area of the triangle is half the cross product of
// the legs of that triangle
//-------------------------------------------------------------------------
//
Scalar area_ratio = z*x;
Verify(!Small_Enough(area_ratio));
area_ratio = x*proj.y / area_ratio;
Check_Fpu();
if (area_ratio >= 0.0f && area_ratio <= 1.0f)
{
//
//----------------------------------------------------------------------
// The area ratio represents the height of the test triangle relative to
// the given triangle. One edge of the value is represented by
// projecting the second leg a percentage equal to the ratio. The bounds
// of its variance is 1-area_ratio * the first leg of the triangle
//----------------------------------------------------------------------
//
Scalar span = proj.x / x;
Check_Fpu();
if (span >= 0.0f && span+area_ratio <= 1.0f)
{
return length;
}
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RightHandedTile::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Check(this);
Check(line);
Verify(enters <= leaves);
Verify(leaves >= 0.0f);
//
//----------------------------------------------
// See if the line hits the upper-right triangle
//----------------------------------------------
//
Point3D p0,p1,p2;
p0.x = maxX;
p0.y = cornerHeight[1];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[0];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[3];
p2.z = maxZ;
Scalar cosine;
Scalar length = LineHitsTriangle(line, p0, p1, p2, &cosine);
//
//--------------------------------------------------------------
// If we are entering the the plane, set the new entering length
//--------------------------------------------------------------
//
if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves)
{
line->length = length;
return True;
}
//
//---------------------------------------------
// See if the line hits the lower left triangle
//---------------------------------------------
//
p0.x = minX;
p0.y = cornerHeight[2];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[3];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[0];
p2.z = minZ;
length = LineHitsTriangle(line, p0, p1, p2, &cosine);
//
//--------------------------------------------------------------
// If we are entering the the plane, set the new entering length
//--------------------------------------------------------------
//
if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves)
{
line->length = length;
return True;
}
//
//-------------------------------------------
// Neither triangle was entered, so we missed
//-------------------------------------------
//
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RightHandedTile::TestInstance() const
{
return solidType == RightHandedTileType;
}
//#############################################################################
//######################### LeftHandedTile ######################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
LeftHandedTile::LeftHandedTile(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid,
Scalar *corners
):
RightHandedTile(
extents,
material,
owner,
next_solid,
corners,
LeftHandedTileType
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
LeftHandedTile::~LeftHandedTile()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
LeftHandedTile::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//-------------------------------------------------------------------
// See if the box hits the upper-left triangle anywhere on its plane
//-------------------------------------------------------------------
//
Point3D p0,p1,p2;
p0.x = maxX;
p0.y = cornerHeight[2];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[1];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[0];
p2.z = maxZ;
Plane plane1(p0, p1, p2);
if (plane1.ContainsSomeOf(extents))
{
//
//-------------------------------------------------------------------
// Make sure the XZ projections of the triangle and the box intersect
//-------------------------------------------------------------------
//
return True;
}
//
//------------------------------------------------------------------
// See if the box hits the lower-right triangle anywhere on its plane
//------------------------------------------------------------------
//
p0.x = minX;
p0.y = cornerHeight[1];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[2];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[3];
p2.z = minZ;
Plane plane2(p0, p1, p2);
if (plane2.ContainsSomeOf(extents))
{
//
//-------------------------------------------------------------------
// Make sure the XZ projections of the triangle and the box intersect
//-------------------------------------------------------------------
//
return True;
}
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
LeftHandedTile::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//---------------------------------------------------
// Figure out which triangle the point will reside in
//---------------------------------------------------
//
Scalar rise = maxX - minX;
Scalar run = maxZ - minZ;
Verify(rise > SMALL);
Verify(run > SMALL);
Scalar dx = point.x - minX; // HACK - needs to be set up for other diagonal
Scalar dz = point.z - minZ;
//
//-----------------------------------------------------------------
// Set up the appropriate triangle based upon which have it lies in
//-----------------------------------------------------------------
//
Point3D p0,p1,p2;
if (dx*run > dz*rise)
{
p0.x = maxX;
p0.y = cornerHeight[1];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[0];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[3];
p2.z = maxZ;
}
else
{
p0.x = minX;
p0.y = cornerHeight[2];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[3];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[0];
p2.z = minZ;
}
//
//---------------------------------------------------------------------
// Make a plane out of the triangle, and have the plane solve for the Y
// coordinate
//---------------------------------------------------------------------
//
Plane plane(p0, p1, p2);
Verify(!Small_Enough(plane.normal.y));
Scalar height = point.y - plane.CalculateY(point.x, point.z);
Check_Fpu();
return height;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
LeftHandedTile::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Check(this);
Check(line);
Verify(enters <= leaves);
Verify(leaves >= 0.0f);
//
//----------------------------------------------
// See if the line hits the upper-right triangle
//----------------------------------------------
//
Point3D p0,p1,p2;
p0.x = maxX;
p0.y = cornerHeight[2];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[1];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[0];
p2.z = maxZ;
Scalar cosine;
Scalar length = LineHitsTriangle(line, p0, p1, p2, &cosine);
//
//--------------------------------------------------------------
// If we are entering the the plane, set the new entering length
//--------------------------------------------------------------
//
if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves)
{
line->length = length;
return True;
}
//
//---------------------------------------------
// See if the line hits the lower left triangle
//---------------------------------------------
//
p0.x = minX;
p0.y = cornerHeight[1];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[2];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[3];
p2.z = minZ;
length = LineHitsTriangle(line, p0, p1, p2, &cosine);
//
//--------------------------------------------------------------
// If we are entering the the plane, set the new entering length
//--------------------------------------------------------------
//
if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves)
{
line->length = length;
return True;
}
//
//-------------------------------------------
// Neither triangle was entered, so we missed
//-------------------------------------------
//
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
LeftHandedTile::TestInstance() const
{
return solidType == LeftHandedTileType;
}