Files
RP411/MUNGA/BOXIRAMP.cpp
T
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00

911 lines
26 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
);
//#############################################################################
//##################### 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;
}