Files
BT412/engine/MUNGA/BOXRAMP.cpp
T
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00

925 lines
28 KiB
C++

#include "munga.h"
#pragma hdrstop
#include "boxsolid.h"
#include "plane.h"
#include "line.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampContainsLine(
Line *line,
const Plane& plane,
Scalar enters,
Scalar leaves
)
{
//
//------------------------------------------------------------------------
// Find the perpendicular distance from the origin of the ray to the ramp,
// and find the direction of the ray relative to the ramp
//------------------------------------------------------------------------
//
Scalar distance = plane.DistanceTo(line->origin);
Scalar drift = line->direction*plane.normal;
//
//--------------------------------------------------------------------------
// If the ray is going out of the ramp and the origin of the
// ray is in the half-space that the plane's normal points to
//--------------------------------------------------------------------------
//
if (drift > 0 && distance > 0)
{
return False;
}
//
//--------------------------------------------------------------------------
// If the ray is parallel to the ramp, the ray will hit if the origin of the
// ray is not in the half-space that the plane's normal points to
//--------------------------------------------------------------------------
//
if (!drift)
{
if (distance <= 0.0f)
{
line->length = Max(enters, 0.0f);
return True;
}
return False;
}
//
//--------------------------------------------------------------------
// Otherwise, if the plane faces the ray, check to see how far the ray
// travels before hitting it
//--------------------------------------------------------------------
//
if (drift < 0.0f)
{
distance /= -drift;
//
//-----------------------------------------------------------------------
// If the ray strikes the plane after all other facing surfaces, then the
// ray enters the solid through this plane. So check to make sure that
// the ray does not miss the plane as clipped by the other surfaces, and
// if it hits, return this distance as the projection length. If the ray
// enters the ramp through an edge face of the bounding box, set the line
// length to the entering value calculated for the box
//-----------------------------------------------------------------------
//
if (distance > enters)
{
if (distance > leaves || distance > line->length)
{
return False;
}
enters = distance;
}
line->length = Max(enters, 0.0f);
return True;
}
//
//------------------------------------------------------------------------
// If the plane faces away from the ray, check to see how far the ray
// travels before exiting it, and ensure this is not before the ray enters
// the object
//------------------------------------------------------------------------
//
distance /= -drift;
if (distance >= enters)
{
line->length = Max(enters, 0.0f);
return True;
}
return False;
}
//#############################################################################
//######################### BoxedRampFacingNegativeZ ####################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingNegativeZ::BoxedRampFacingNegativeZ(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, RampFacingNegativeZType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingNegativeZ::~BoxedRampFacingNegativeZ()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeZ::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.minY - minY;
Scalar z = extents.minZ - 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;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeZ::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
BoxedRampFacingNegativeZ::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);
//
//----------------------------------------------------------------------
// 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
//-------------------------------------------------------------------
//
y -= (rise/run)*z;
return Max(y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeZ::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 = maxZ - minZ;
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 + minZ*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
BoxedRampFacingNegativeZ::TestInstance() const
{
return solidType == RampFacingNegativeZType;
}
//#############################################################################
//######################### BoxedRampFacingPositiveZ ####################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingPositiveZ::BoxedRampFacingPositiveZ(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, RampFacingPositiveZType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingPositiveZ::~BoxedRampFacingPositiveZ()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveZ::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.minY - minY;
Scalar z = extents.maxZ - minZ;
//
//------------------------------------------------------------------------
// 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
BoxedRampFacingPositiveZ::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
BoxedRampFacingPositiveZ::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);
//
//----------------------------------------------------------------------
// 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
//-------------------------------------------------------------------
//
y -= (rise/run)*z;
return Max(y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveZ::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 = maxZ - minZ;
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 + minZ*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
BoxedRampFacingPositiveZ::TestInstance() const
{
return solidType == RampFacingPositiveZType;
}
//#############################################################################
//######################### BoxedRampFacingNegativeX ####################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingNegativeX::BoxedRampFacingNegativeX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, RampFacingNegativeXType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingNegativeX::~BoxedRampFacingNegativeX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeX::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.minX - maxX;
Scalar y = extents.minY - 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
BoxedRampFacingNegativeX::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
BoxedRampFacingNegativeX::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);
//
//----------------------------------------------------------------------
// 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
//-------------------------------------------------------------------
//
y -= (rise/run)*x;
return Max(y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeX::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 = maxX - minX;
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 = 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
BoxedRampFacingNegativeX::TestInstance() const
{
return solidType == RampFacingNegativeXType;
}
//#############################################################################
//######################### BoxedRampFacingPositiveX ####################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingPositiveX::BoxedRampFacingPositiveX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, RampFacingPositiveXType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingPositiveX::~BoxedRampFacingPositiveX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveX::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.maxX - minX;
Scalar y = extents.minY - 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
BoxedRampFacingPositiveX::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
BoxedRampFacingPositiveX::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);
//
//----------------------------------------------------------------------
// 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
//-------------------------------------------------------------------
//
y -= (rise/run)*x;
return Max(y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveX::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 = maxX - minX;
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 = 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
BoxedRampFacingPositiveX::TestInstance() const
{
return solidType == RampFacingPositiveXType;
}