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

931 lines
28 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(PLANE_HPP)
# include <plane.hpp>
#endif
extern Logical
BoxedRampContainsLine(
Line *line,
const Plane& plane,
Scalar enters,
Scalar leaves
);
//#############################################################################
//##################### BoxedInvertedRampFacingNegativeZ ################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingNegativeZ::BoxedInvertedRampFacingNegativeZ(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
InvertedRampFacingNegativeZType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingNegativeZ::~BoxedInvertedRampFacingNegativeZ()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeZ::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);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = extents.maxY - minY;
Scalar z = extents.minZ - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/z yields
// rise*z <= y*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return z*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeZ::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/z yields
// rise*z <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedInvertedRampFacingNegativeZ::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);
//
//----------------------------------------------------------------
// If the point is above the ramp, it will hit the top of the ramp
//----------------------------------------------------------------
//
if (point.y > maxY)
{
return point.y - maxY;
}
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - minZ;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
return (z*rise <= y*run) ? 0.0f : -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeZ::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.x = 0.0f;
ramp.normal.y = minZ - maxZ;
ramp.normal.z = maxY - minY;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.z /= temp;
ramp.offset = maxY*ramp.normal.y + maxZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeZ::TestInstance() const
{
return solidType == InvertedRampFacingNegativeZType;
}
//#############################################################################
//##################### BoxedInvertedRampFacingPositiveZ ################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingPositiveZ::BoxedInvertedRampFacingPositiveZ(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
InvertedRampFacingPositiveZType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingPositiveZ::~BoxedInvertedRampFacingPositiveZ()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveZ::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);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = extents.maxY - minY;
Scalar z = extents.maxZ - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/z yields
// rise*z >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveZ::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/z yields
// rise*z >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedInvertedRampFacingPositiveZ::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);
//
//----------------------------------------------------------------
// If the point is above the ramp, it will hit the top of the ramp
//----------------------------------------------------------------
//
if (point.y > maxY)
{
return point.y - maxY;
}
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - maxZ;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
return (z*rise >= y*run) ? 0.0f : -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveZ::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.x = 0.0f;
ramp.normal.y = minZ - maxZ;
ramp.normal.z = minY - maxY;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.z /= temp;
ramp.offset = minY*ramp.normal.y + maxZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveZ::TestInstance() const
{
return solidType == InvertedRampFacingPositiveZType;
}
//#############################################################################
//##################### BoxedInvertedRampFacingNegativeX ################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingNegativeX::BoxedInvertedRampFacingNegativeX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
InvertedRampFacingNegativeXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingNegativeX::~BoxedInvertedRampFacingNegativeX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeX::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);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.minX - minX;
Scalar y = extents.maxY - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/x yields
// rise*x <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar y = point.y - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/x yields
// rise*x <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedInvertedRampFacingNegativeX::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);
//
//----------------------------------------------------------------
// If the point is above the ramp, it will hit the top of the ramp
//----------------------------------------------------------------
//
if (point.y > maxY)
{
return point.y - maxY;
}
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar y = point.y - minY;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
return (x*rise <= y*run) ? 0.0f : -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.y = minX - maxX;
ramp.normal.x = maxY - minY;
ramp.normal.z = 0.0f;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.x /= temp;
ramp.offset = minY*ramp.normal.y + minX*ramp.normal.x;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeX::TestInstance() const
{
return solidType == InvertedRampFacingNegativeXType;
}
//#############################################################################
//##################### BoxedInvertedRampFacingPositiveX ################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingPositiveX::BoxedInvertedRampFacingPositiveX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
InvertedRampFacingPositiveXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingPositiveX::~BoxedInvertedRampFacingPositiveX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveX::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);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.maxX - maxX;
Scalar y = extents.maxY - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/x yields
// rise*x >= x*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar y = point.y - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/x yields
// rise*x >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedInvertedRampFacingPositiveX::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);
//
//----------------------------------------------------------------
// If the point is above the ramp, it will hit the top of the ramp
//----------------------------------------------------------------
//
if (point.y > maxY)
{
return point.y - maxY;
}
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar y = point.y - minY;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
return (x*rise >= y*run) ? 0.0f : -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.y = minX - maxX;
ramp.normal.x = minY - maxY;
ramp.normal.z = 0.0f;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.x /= temp;
ramp.offset = maxY*ramp.normal.y + minX*ramp.normal.x;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveX::TestInstance() const
{
return solidType == InvertedRampFacingPositiveXType;
}