Files
BT412/engine/MUNGA/BOXWEDGE.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

873 lines
25 KiB
C++

#include "munga.h"
#pragma hdrstop
#include "boxsolid.h"
#include "plane.h"
extern Logical
BoxedRampContainsLine(
Line *line,
const Plane& plane,
Scalar enters,
Scalar leaves
);
//#############################################################################
//################# BoxedWedgeFacingNegativeZAndPositiveX ###############
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingNegativeZAndPositiveX::BoxedWedgeFacingNegativeZAndPositiveX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
WedgeFacingNegativeZAndPositiveXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingNegativeZAndPositiveX::~BoxedWedgeFacingNegativeZAndPositiveX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndPositiveX::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 = 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 x = extents.maxX - minX;
Scalar z = extents.minZ - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise >= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndPositiveX::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 = 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 x = point.x - minX;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise >= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedWedgeFacingNegativeZAndPositiveX::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 NW corner the ramp is placed
// at the origin
//------------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = 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 x = point.x - minX;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
if (x*rise >= z*run)
{
x = point.y - maxY;
return Max(x,0.0f);
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndPositiveX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
ramp.normal.x = minZ - maxZ;
ramp.normal.y = 0.0f;
ramp.normal.z = maxX - minX;
//
//-----------------------------
// Scale the vector to a normal
//-----------------------------
//
Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp));
temp = Sqrt(temp);
ramp.normal.x /= temp;
ramp.normal.z /= temp;
ramp.offset = maxX*ramp.normal.x + 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
BoxedWedgeFacingNegativeZAndPositiveX::TestInstance() const
{
return solidType == WedgeFacingNegativeZAndPositiveXType;
}
//#############################################################################
//################# BoxedWedgeFacingPositiveZAndNegativeX ###############
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingPositiveZAndNegativeX::BoxedWedgeFacingPositiveZAndNegativeX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
WedgeFacingPositiveZAndNegativeXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingPositiveZAndNegativeX::~BoxedWedgeFacingPositiveZAndNegativeX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndNegativeX::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 = 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 x = extents.minX - maxX;
Scalar z = extents.maxZ - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise >= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndNegativeX::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 = 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 x = point.x - maxX;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise >= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedWedgeFacingPositiveZAndNegativeX::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 NW corner the ramp is placed
// at the origin
//------------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = minZ - maxZ;
//
//-------------------------------------------------------------------
// 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 z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
if (x*rise >= z*run)
{
x = point.y - maxY;
return Max(x,0.0f);
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndNegativeX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
ramp.normal.x = maxZ - minZ;
ramp.normal.y = 0.0f;
ramp.normal.z = minX - maxX;
//
//-----------------------------
// Scale the vector to a normal
//-----------------------------
//
Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp));
temp = Sqrt(temp);
ramp.normal.x /= temp;
ramp.normal.z /= temp;
ramp.offset = maxX*ramp.normal.x + 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
BoxedWedgeFacingPositiveZAndNegativeX::TestInstance() const
{
return solidType == WedgeFacingPositiveZAndNegativeXType;
}
//#############################################################################
//################# BoxedWedgeFacingPositiveZAndPositiveX ###############
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingPositiveZAndPositiveX::BoxedWedgeFacingPositiveZAndPositiveX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
WedgeFacingPositiveZAndPositiveXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingPositiveZAndPositiveX::~BoxedWedgeFacingPositiveZAndPositiveX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndPositiveX::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 = 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 x = extents.maxX - minX;
Scalar z = extents.maxZ - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise <= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndPositiveX::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 = 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 x = point.x - minX;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise <= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedWedgeFacingPositiveZAndPositiveX::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 NW corner the ramp is placed
// at the origin
//------------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = 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 x = point.x - minX;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
if (x*rise <= z*run)
{
x = point.y - maxY;
return Max(x,0.0f);
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndPositiveX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
ramp.normal.x = minZ - maxZ;
ramp.normal.y = 0.0f;
ramp.normal.z = minX - maxX;
//
//-----------------------------
// Scale the vector to a normal
//-----------------------------
//
Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp));
temp = Sqrt(temp);
ramp.normal.x /= temp;
ramp.normal.z /= temp;
ramp.offset = maxX*ramp.normal.x + 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
BoxedWedgeFacingPositiveZAndPositiveX::TestInstance() const
{
return solidType == WedgeFacingPositiveZAndPositiveXType;
}
//#############################################################################
//################# BoxedWedgeFacingNegativeZAndNegativeX ###############
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingNegativeZAndNegativeX::BoxedWedgeFacingNegativeZAndNegativeX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
WedgeFacingNegativeZAndNegativeXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingNegativeZAndNegativeX::~BoxedWedgeFacingNegativeZAndNegativeX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndNegativeX::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 = 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 x = extents.minX - maxX;
Scalar z = extents.minZ - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise <= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndNegativeX::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 = 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 x = point.x - maxX;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise <= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedWedgeFacingNegativeZAndNegativeX::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 NW corner the ramp is placed
// at the origin
//------------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = 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 x = point.x - maxX;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
if (x*rise <= z*run)
{
x = point.y - maxY;
return Max(x,0.0f);
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndNegativeX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
ramp.normal.x = maxZ - minZ;
ramp.normal.y = 0.0f;
ramp.normal.z = maxX - minX;
//
//-----------------------------
// Scale the vector to a normal
//-----------------------------
//
Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp));
temp = Sqrt(temp);
ramp.normal.x /= temp;
ramp.normal.z /= temp;
ramp.offset = minX*ramp.normal.x + 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
BoxedWedgeFacingNegativeZAndNegativeX::TestInstance() const
{
return solidType == WedgeFacingNegativeZAndNegativeXType;
}