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>
This commit is contained in:
@@ -0,0 +1,464 @@
|
||||
#include "munga.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "boxsolid.h"
|
||||
#include "line.h"
|
||||
|
||||
//#############################################################################
|
||||
//############################### BoxedCone #############################
|
||||
//#############################################################################
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
BoxedCone::BoxedCone(
|
||||
const ExtentBox &extents,
|
||||
BoxedSolid::Material material,
|
||||
Simulation *owner,
|
||||
BoxedSolid *next_solid
|
||||
):
|
||||
BoxedSolid(extents, ConeType, material, owner, next_solid)
|
||||
{
|
||||
Check_Pointer(this);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
BoxedCone::~BoxedCone()
|
||||
{
|
||||
Check_Pointer(this);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
BoxedCone::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);
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// Find the center point in the XZ plane of the cone, and find the biggest
|
||||
// radius of the cone by measuring in the X axis, along with its height
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D center;
|
||||
center.x = (minX + maxX) * 0.5f;
|
||||
center.y = minY;
|
||||
center.z = (minZ + maxZ) * 0.5f;
|
||||
Scalar radius = maxX - center.x;
|
||||
Verify(!Small_Enough(radius));
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Convert the closest point in the slice to the coordinates of the cone,
|
||||
// putting the apex of the cone at the origin, then make sure that the point
|
||||
// isn't in one of the corners of the box
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D nearest(center);
|
||||
extents.Constrain(&nearest);
|
||||
center.y = maxY;
|
||||
nearest.Subtract(center,nearest);
|
||||
Scalar r = nearest.x*nearest.x + nearest.z*nearest.z;
|
||||
if (r > radius*radius)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Compute the distance from the axis, and then see if the slope of the line
|
||||
// from the cone apex to the test point is less than the slope of the cone
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
r = Sqrt(r);
|
||||
Scalar height = maxY - minY;
|
||||
return r*height <= nearest.y*radius;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
BoxedCone::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);
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// Find the center point in the XZ plane of the cone, and find the biggest
|
||||
// radius of the cone by measuring in the X axis, along with its height
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D center;
|
||||
center.x = (minX + maxX) * 0.5f;
|
||||
center.y = maxY;
|
||||
center.z = (minZ + maxZ) * 0.5f;
|
||||
Scalar radius = maxX - center.x;
|
||||
Verify(!Small_Enough(radius));
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Convert the closest point in the slice to the coordinates of the cone,
|
||||
// putting the apex of the cone at the origin, then make sure that the point
|
||||
// isn't in one of the corners of the box
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D nearest;
|
||||
nearest.Subtract(center, point);
|
||||
Scalar r = nearest.x*nearest.x + nearest.z*nearest.z;
|
||||
if (r > radius*radius)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Compute the distance from the axis, and then see if the slope of the line
|
||||
// from the cone apex to the test point is less than the slope of the cone
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
r = Sqrt(r);
|
||||
Scalar height = maxY - minY;
|
||||
return r*height <= nearest.y*radius;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Scalar
|
||||
BoxedCone::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);
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
// Find the center point in the XZ plane of the cone, and find the biggest
|
||||
// radius of the cone by measuring in the X axis, along with its height
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D center;
|
||||
center.x = (minX + maxX) * 0.5f;
|
||||
center.y = maxY;
|
||||
center.z = (minZ + maxZ) * 0.5f;
|
||||
Scalar radius = maxX - center.x;
|
||||
Verify(!Small_Enough(radius));
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Convert the closest point in the slice to the coordinates of the cone,
|
||||
// putting the apex of the cone at the origin, then make sure that the point
|
||||
// isn't in one of the corners of the box
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D nearest;
|
||||
nearest.Subtract(point, center);
|
||||
Scalar r = nearest.x*nearest.x + nearest.z*nearest.z;
|
||||
if (r > radius*radius)
|
||||
{
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Compute the distance from the axis, and then see if the slope of the line
|
||||
// from the cone apex to the test point is less than the slope of the cone
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
r = Sqrt(r);
|
||||
Scalar height = maxY - minY;
|
||||
nearest.y += r*(height/radius);
|
||||
return Max(nearest.y,0.0f);
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// This function is a helper function used in the derivation for the terms of
|
||||
// the quadratic equation to find t when colliding a line and a cone. I'm not
|
||||
// real clear on the physical representation of this kind of dot product
|
||||
//
|
||||
static Scalar
|
||||
Special_Cone_Dot_Product(
|
||||
const Vector3D &v1,
|
||||
const Vector3D &v2,
|
||||
Scalar squared_tan
|
||||
)
|
||||
{
|
||||
return v1.x*v2.x - squared_tan*v1.y*v2.y + v1.z*v2.z;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
BoxedCone::HitByBounded(
|
||||
Line *line,
|
||||
Scalar enters,
|
||||
Scalar leaves
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(line);
|
||||
|
||||
Verify(enters <= leaves);
|
||||
Verify(leaves >= 0.0f);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Find out the size of the box, and set up the height and maximum radius of
|
||||
// the cone, along with the squared tangent of the spread angle
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D center;
|
||||
center.x = (minX + maxX) * 0.5f;
|
||||
center.y = maxY;
|
||||
center.z = (minZ + maxZ) * 0.5f;
|
||||
Scalar radius = maxX - center.x;
|
||||
Scalar height = maxY - minY;
|
||||
Verify(!Small_Enough(height));
|
||||
Scalar squared_tan = radius*radius/(height*height);
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
// Find the line between the point of the cone and the origin of our line,
|
||||
// then set up the conditions for the quadratic equation. The following
|
||||
// equation sets up a*t^2 + b*t + c = 0. The terms a, b, and c are derived
|
||||
// by solving the following equations for t:
|
||||
//
|
||||
// p == line->origin + line->direction * t
|
||||
// r == p - cone->apex
|
||||
// r.x^2 + r.z^2 == tan^2(cone_angle)*r.y^2
|
||||
//
|
||||
// The special cone dot product function is a handy way to reduce the
|
||||
// complexity of the problem
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D v;
|
||||
v.Subtract(line->origin,center);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// If the line diverges from the axis at the same angle as the spread angle,
|
||||
// we need to find the closest point on the line to the axis. We then drop
|
||||
// a vertical plane containing the line through the cone at this point, thus
|
||||
// generating a hyperbola. We then solve the hyperbola vs. line equation to
|
||||
// get our intersection point
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
Scalar a =
|
||||
Special_Cone_Dot_Product(line->direction, line->direction, squared_tan);
|
||||
if (Small_Enough(a))
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
//-----------------------------------------------
|
||||
// Otherwise, continue solving the first equation
|
||||
//-----------------------------------------------
|
||||
//
|
||||
else
|
||||
{
|
||||
Scalar b =
|
||||
2.0f * Special_Cone_Dot_Product(v, line->direction, squared_tan);
|
||||
Scalar c = Special_Cone_Dot_Product(v, v, squared_tan);
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// Now, use the quadratic equation to determine where the two points
|
||||
// intersect the cone. If there is no solution, than the line missed the
|
||||
// cone
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
Verify(!Small_Enough(a));
|
||||
Scalar t = -b / (2.0f * a);
|
||||
Scalar i = b*b - 4.0f*a*c;
|
||||
|
||||
if (i < 0.0f)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
// If the interval is zero, then the line hits the cone in one spot only
|
||||
// (a tangential hit). Check to see if hits the lower half of the conic
|
||||
// equation (our cone)
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
if (Small_Enough(i))
|
||||
{
|
||||
Scalar y = v.y + line->direction.y * t;
|
||||
if (y > 0.0f)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------
|
||||
// It hit the lower cone, so see if it was entering or leaving the
|
||||
// cone
|
||||
//----------------------------------------------------------------
|
||||
//
|
||||
if (line->direction.y > 0.0f)
|
||||
{
|
||||
//
|
||||
//-------------------------------------------------------------
|
||||
// The line is leaving the cone, so see if we need to reset the
|
||||
// leaving distance
|
||||
//-------------------------------------------------------------
|
||||
//
|
||||
if (t < leaves)
|
||||
{
|
||||
leaves = t;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//------------------------------------------------------------
|
||||
// The line is entering the cone, so see if we need to set the
|
||||
// entering distance
|
||||
//------------------------------------------------------------
|
||||
//
|
||||
else if (t > enters)
|
||||
{
|
||||
enters = t;
|
||||
}
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
// See if we still have a collision with the cone, and if so, set the
|
||||
// new line length
|
||||
//-------------------------------------------------------------------
|
||||
//
|
||||
if (enters > leaves || enters > line->length || leaves < 0.0f)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
line->length = Max(enters, 0.0f);
|
||||
return True;
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
// If the interval is non-zero, then the conic section was struck in two
|
||||
// places. Find out the lengths to those places and the y values for
|
||||
// those points
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
i = Sqrt(i) / (2.0f * a);
|
||||
Scalar t1,t2;
|
||||
if (i > 0.0f)
|
||||
{
|
||||
t1 = t - i;
|
||||
t2 = t + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = t + i;
|
||||
t2 = t - i;
|
||||
}
|
||||
Scalar y1 = v.y + line->direction.y * t1;
|
||||
Scalar y2 = v.y + line->direction.y * t2;
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
// There are four combinations of the signs of the y values. Each has a
|
||||
// different effect on missing/hitting, entering or leaving distances.
|
||||
// First check to see if only the upper conic was hit
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
if (y1 > 0.0f)
|
||||
{
|
||||
if (y2 > 0.0f)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
// The ray is entering our conic, so set the distance appropriately
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
if (t2 > enters)
|
||||
{
|
||||
enters = t2;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
// See if the ray is leaving the lower conic, and if so, set the leaving
|
||||
// distance accordingly
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
else
|
||||
{
|
||||
if (y2 > 0.0f)
|
||||
{
|
||||
if (t1 < leaves)
|
||||
{
|
||||
leaves = t1;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
// Both spots are in the lower conic, so set both leaving and entering
|
||||
// distances
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
else
|
||||
{
|
||||
if (t1 > enters)
|
||||
{
|
||||
enters = t1;
|
||||
}
|
||||
if (t2 < leaves)
|
||||
{
|
||||
leaves = t2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
// See if we still have a collision with the cone, and if so, set the new
|
||||
// line length
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
if (enters > leaves || enters > line->length || leaves < 0.0f)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
line->length = Max(enters, 0.0f);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
BoxedCone::TestInstance() const
|
||||
{
|
||||
return solidType == ConeType;
|
||||
}
|
||||
Reference in New Issue
Block a user