1
0
mirror of https://github.com/k4zmu2a/SpaceCadetPinball.git synced 2024-11-02 00:42:53 +01:00

Cleaning up maths: part 4.

More by ref args, cleaned up distance_to_flipper, ramp init.
This commit is contained in:
Muzychenko Andrey 2022-05-16 09:28:35 +03:00
parent fdf1f6c9f1
commit 2d2ca0ab2a
6 changed files with 153 additions and 177 deletions

View File

@ -120,7 +120,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Direction = ogRay->Direction;
srcRay.MaxDistance = ogRay->MaxDistance;
srcRay.Origin = ogRay->Origin;
auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
auto distance = maths::distance_to_flipper(srcRay, dstRay);
if (distance == 0.0f)
{
NextBallPosition = dstRay.Origin;
@ -166,14 +166,14 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09f)
if (maths::distance_to_flipper(srcRay, dstRay) >= 1e+09f)
{
srcRay.Direction.X = RotOrigin.X - ogRay->Origin.X;
srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
maths::normalize_2d(srcRay.Direction);
srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09f)
if (maths::distance_to_flipper(srcRay, dstRay) >= 1e+09f)
{
return 1e+09;
}
@ -220,7 +220,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f;
srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
if (maths::distance_to_flipper(&srcRay, &dstRay) >= 1e+09f)
if (maths::distance_to_flipper(srcRay, dstRay) >= 1e+09f)
{
NextBallPosition.X = posX;
NextBallPosition.Y = posY;
@ -249,7 +249,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
srcRay.MaxDistance = ogRay->MaxDistance + 10.0f;
auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
auto distance = maths::distance_to_flipper(srcRay, dstRay);
CollisionDirection = dstRay.Direction;
if (distance >= 1e+09f)
{
@ -265,7 +265,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
srcRay.MinDistance = ogRay->MinDistance;
srcRay.Origin = ogRay->Origin;
srcRay.MaxDistance = rayMaxDistance;
auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
auto distance = maths::distance_to_flipper(srcRay, dstRay);
if (distance < 1e+09f)
{
NextBallPosition = dstRay.Origin;
@ -389,7 +389,7 @@ void TFlipperEdge::place_in_grid()
void TFlipperEdge::set_control_points(float timeNow)
{
maths::SinCos(flipper_angle(timeNow), &flipper_sin_angle, &flipper_cos_angle);
maths::SinCos(flipper_angle(timeNow), flipper_sin_angle, flipper_cos_angle);
A1 = A1Src;
A2 = A2Src;
B1 = B1Src;
@ -404,8 +404,8 @@ void TFlipperEdge::set_control_points(float timeNow)
void TFlipperEdge::build_edges_in_motion()
{
maths::line_init(&lineA, A1.X, A1.Y, A2.X, A2.Y);
maths::line_init(&lineB, B1.X, B1.Y, B2.X, B2.Y);
maths::line_init(lineA, A1.X, A1.Y, A2.X, A2.Y);
maths::line_init(lineB, B1.X, B1.Y, B2.X, B2.Y);
circlebase.RadiusSq = CirclebaseRadiusSq;
circlebase.Center.X = RotOrigin.X;
circlebase.Center.Y = RotOrigin.Y;

View File

@ -11,7 +11,7 @@ TLine::TLine(TCollisionComponent* collCmp, char* activeFlag, unsigned int collis
Y0 = y0;
X1 = x1;
Y1 = y1;
maths::line_init(&Line, x0, y0, x1, y1);
maths::line_init(Line, x0, y0, x1, y1);
}
TLine::TLine(TCollisionComponent* collCmp, char* activeFlag, unsigned int collisionGroup, const vector2& start,
@ -21,7 +21,7 @@ TLine::TLine(TCollisionComponent* collCmp, char* activeFlag, unsigned int collis
Y0 = start.Y;
X1 = end.X;
Y1 = end.Y;
maths::line_init(&Line, X0, Y0, X1, Y1);
maths::line_init(Line, X0, Y0, X1, Y1);
}
void TLine::Offset(float offset)
@ -33,12 +33,12 @@ void TLine::Offset(float offset)
Y0 += offY;
X1 += offX;
Y1 += offY;
maths::line_init(&Line, X0, Y0, X1, Y1);
maths::line_init(Line, X0, Y0, X1, Y1);
}
float TLine::FindCollisionDistance(ray_type* ray)
{
return maths::ray_intersect_line(ray, &Line);
return maths::ray_intersect_line(*ray, Line);
}
void TLine::EdgeCollision(TBall* ball, float coef)

View File

@ -14,7 +14,7 @@
TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
{
visualStruct visual{};
vector2 end{}, start{}, end2{}, start2{}, start3{}, end3{};
vector2 wall1End{}, wall1Start{}, wall2Start{}, wall2End{};
MessageField = 0;
UnusedBaseFlag = 1;
@ -22,60 +22,51 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
CollisionGroup = visual.CollisionGroup;
BallFieldMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f);
RampFlag1 = static_cast<int>(loader::query_float_attribute(groupIndex, 0, 1305, 0));
BallZOffsetFlag = static_cast<int>(loader::query_float_attribute(groupIndex, 0, 1305, 0));
auto floatArr3Plane = loader::query_float_attribute(groupIndex, 0, 1300);
RampPlaneCount = static_cast<int>(floor(*floatArr3Plane));
RampPlane = reinterpret_cast<ramp_plane_type*>(floatArr3Plane + 1);
auto floatArr4 = loader::query_float_attribute(groupIndex, 0, 1303);
end.X = floatArr4[2];
end.Y = floatArr4[3];
start.X = floatArr4[4];
start.Y = floatArr4[5];
Line1 = new TLine(this, &ActiveFlag, 1 << static_cast<int>(floor(floatArr4[0])), start, end);
EdgeList.push_back(Line1);
if (Line1)
{
auto wall0Arr = loader::query_float_attribute(groupIndex, 0, 1303);
auto wall0CollisionGroup = 1 << static_cast<int>(floor(wall0Arr[0]));
auto wall0Pts = reinterpret_cast<wall_point_type*>(wall0Arr + 2);
Line1 = new TLine(this, &ActiveFlag, wall0CollisionGroup, wall0Pts->Pt1, wall0Pts->Pt0);
Line1->WallValue = nullptr;
Line1->place_in_grid();
}
EdgeList.push_back(Line1);
auto floatArr5WallPoint = loader::query_float_attribute(groupIndex, 0, 1301);
Wall1PointFirst = 1 << static_cast<int>(floor(floatArr5WallPoint[0]));
auto wallPt1_2 = static_cast<int>(floor(floatArr5WallPoint[1]));
Wall1PointLast = floatArr5WallPoint[7];
auto wall1Arr = loader::query_float_attribute(groupIndex, 0, 1301);
Wall1CollisionGroup = 1 << static_cast<int>(floor(wall1Arr[0]));
auto wall1Enabled = static_cast<int>(floor(wall1Arr[1]));
Wall1BallOffset = wall1Arr[7];
maths::find_closest_edge(
RampPlane,
RampPlaneCount,
reinterpret_cast<wall_point_type*>(floatArr5WallPoint + 3),
end2,
start2);
Line2 = new TLine(this, &ActiveFlag, CollisionGroup, start2, end2);
EdgeList.push_back(Line2);
if (Line2)
{
reinterpret_cast<wall_point_type*>(wall1Arr + 3),
wall1End,
wall1Start);
Line2 = new TLine(this, &ActiveFlag, CollisionGroup, wall1Start, wall1End);
Line2->WallValue = nullptr;
Line2->place_in_grid();
}
EdgeList.push_back(Line2);
auto floatArr6WallPoint = loader::query_float_attribute(groupIndex, 0, 1302);
auto wall2Pt1_2 = static_cast<int>(floor(floatArr6WallPoint[1]));
Wall2PointFirst = 1 << static_cast<int>(floor(floatArr6WallPoint[0]));
Wall2PointLast = floatArr6WallPoint[7];
auto wall2Arr = loader::query_float_attribute(groupIndex, 0, 1302);
Wall2CollisionGroup = 1 << static_cast<int>(floor(wall2Arr[0]));
auto wall2Enabled = static_cast<int>(floor(wall2Arr[1]));
Wall2BallOffset = wall2Arr[7];
maths::find_closest_edge(
RampPlane,
RampPlaneCount,
reinterpret_cast<wall_point_type*>(floatArr6WallPoint + 3),
end3,
start3);
Line3 = new TLine(this, &ActiveFlag, CollisionGroup, start3, end3);
EdgeList.push_back(Line3);
if (Line3)
{
reinterpret_cast<wall_point_type*>(wall2Arr + 3),
wall2End,
wall2Start);
Line3 = new TLine(this, &ActiveFlag, CollisionGroup, wall2Start, wall2End);
Line3->WallValue = nullptr;
Line3->place_in_grid();
}
EdgeList.push_back(Line3);
auto xMin = 1000000000.0f;
@ -96,30 +87,26 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
{
auto& point1 = *pointOrder[pt], point2 = *pointOrder[pt + 1];
auto collisionGroup = 0;
if (point1 != end2 || point2 != start2)
if (point1 == wall1End && point2 == wall1Start)
{
if (point1 != end3 || point2 != start3)
if (wall1Enabled)
collisionGroup = Wall1CollisionGroup;
}
else if (point1 == wall2End && point2 == wall2Start)
{
if (wall2Enabled)
collisionGroup = Wall2CollisionGroup;
}
else
collisionGroup = visual.CollisionGroup;
}
else if (wall2Pt1_2)
{
collisionGroup = Wall2PointFirst;
}
}
else if (wallPt1_2)
{
collisionGroup = Wall1PointFirst;
}
if (collisionGroup)
{
auto line = new TLine(this, &ActiveFlag, collisionGroup, point1, point2);
EdgeList.push_back(line);
if (line)
{
line->WallValue = &plane;
line->place_in_grid();
}
EdgeList.push_back(line);
}
}
@ -186,17 +173,15 @@ void TRamp::Collision(TBall* ball, vector2* nextPosition, vector2* direction, fl
ball->CollisionFlag = 0;
if (edge == Line2)
{
ball->FieldFlag = Wall1PointFirst;
if (!RampFlag1)
return;
ball->Position.Z = ball->Offset + Wall1PointLast;
ball->FieldFlag = Wall1CollisionGroup;
if (BallZOffsetFlag)
ball->Position.Z = ball->Offset + Wall1BallOffset;
}
else
{
ball->FieldFlag = Wall2PointFirst;
if (!RampFlag1)
return;
ball->Position.Z = ball->Offset + Wall2PointLast;
ball->FieldFlag = Wall2CollisionGroup;
if (BallZOffsetFlag)
ball->Position.Z = ball->Offset + Wall2BallOffset;
}
}
}

View File

@ -20,15 +20,15 @@ public:
int Scores[4]{};
field_effect_type Field{};
int CollisionGroup;
int RampFlag1;
bool BallZOffsetFlag;
int RampPlaneCount;
float BallFieldMult;
ramp_plane_type* RampPlane;
TEdgeSegment* Line2;
TEdgeSegment* Line3;
TEdgeSegment* Line1;
int Wall1PointFirst;
int Wall2PointFirst;
float Wall1PointLast;
float Wall2PointLast;
int Wall1CollisionGroup;
int Wall2CollisionGroup;
float Wall1BallOffset;
float Wall2BallOffset;
};

View File

@ -129,37 +129,38 @@ float maths::normalize_2d(vector2& vec)
}
void maths::line_init(line_type* line, float x0, float y0, float x1, float y1)
void maths::line_init(line_type& line, float x0, float y0, float x1, float y1)
{
line->Origin = { x0, y0 };
line->Direction.X = x1 - x0;
line->Direction.Y = y1 - y0;
normalize_2d(line->Direction);
line.Origin = { x0, y0 };
line.Direction.X = x1 - x0;
line.Direction.Y = y1 - y0;
normalize_2d(line.Direction);
// Clockwise perpendicular to the line direction vector
line->PerpendicularC = { line->Direction.Y, -line->Direction.X };
line.PerpendicularC = { line.Direction.Y, -line.Direction.X };
auto lineStart = x0, lineEnd = x1;
if (std::abs(line->Direction.X) < 0.000000001f)
if (std::abs(line.Direction.X) < 0.000000001f)
{
line->Direction.X = 0.0;
line.Direction.X = 0.0;
lineStart = y0;
lineEnd = y1;
}
line->MinCoord = std::min(lineStart, lineEnd);
line->MaxCoord = std::max(lineStart, lineEnd);
line.MinCoord = std::min(lineStart, lineEnd);
line.MaxCoord = std::max(lineStart, lineEnd);
}
// Returns the distance from ray origin to the ray-line segment intersection point.
float maths::ray_intersect_line(ray_type* ray, line_type* line)
// Stores ray-line intersection point in line.RayIntersect
float maths::ray_intersect_line(const ray_type& ray, line_type& line)
{
// V1 vector between ray origin and line origin
// V2 ray direction
// V3 line perpendicular clockwise
auto v1 = vector_sub(ray->Origin, line->Origin);
auto v2 = line->Direction;
auto v3 = vector2{ -ray->Direction.Y, ray->Direction.X };
auto v1 = vector_sub(ray.Origin, line.Origin);
auto v2 = line.Direction;
auto v3 = vector2{ -ray.Direction.Y, ray.Direction.X };
// Project line on ray perpendicular, no intersection if ray is pointing away from the line
auto v2DotV3 = DotProduct(v2, v3);
@ -167,14 +168,14 @@ float maths::ray_intersect_line(ray_type* ray, line_type* line)
{
// Distance to the intersect point: (V2 X V1) / (V2 dot V3)
auto distance = cross(v2, v1) / v2DotV3;
if (distance >= -ray->MinDistance && distance <= ray->MaxDistance)
if (distance >= -ray.MinDistance && distance <= ray.MaxDistance)
{
line->RayIntersect.X = distance * ray->Direction.X + ray->Origin.X;
line->RayIntersect.Y = distance * ray->Direction.Y + ray->Origin.Y;
line.RayIntersect.X = distance * ray.Direction.X + ray.Origin.X;
line.RayIntersect.Y = distance * ray.Direction.Y + ray.Origin.Y;
// Check if intersection point is inside line segment
auto testPoint = line->Direction.X != 0.0f ? line->RayIntersect.X : line->RayIntersect.Y;
if (testPoint >= line->MinCoord && testPoint <= line->MaxCoord)
auto testPoint = line.Direction.X != 0.0f ? line.RayIntersect.X : line.RayIntersect.Y;
if (testPoint >= line.MinCoord && testPoint <= line.MaxCoord)
{
return distance;
}
@ -223,7 +224,8 @@ float maths::basic_collision(TBall* ball, vector2* nextPosition, vector2* direct
{
ball->Position.X = nextPosition->X;
ball->Position.Y = nextPosition->Y;
float proj = -(direction->Y * ball->Acceleration.Y + direction->X * ball->Acceleration.X);
auto proj = -DotProduct(*direction, ball->Acceleration);
if (proj < 0)
{
proj = -proj;
@ -236,6 +238,7 @@ float maths::basic_collision(TBall* ball, vector2* nextPosition, vector2* direct
ball->Acceleration.Y = (dy1 + ball->Acceleration.Y) * smoothness + dy1 * elasticity;
normalize_2d(ball->Acceleration);
}
float projSpeed = proj * ball->Speed;
float newSpeed = ball->Speed - (1.0f - elasticity) * projSpeed;
ball->Speed = newSpeed;
@ -265,88 +268,76 @@ float maths::Distance(const vector2& vec1, const vector2& vec2)
return sqrt(Distance_Squared(vec1, vec2));
}
void maths::SinCos(float angle, float* sinOut, float* cosOut)
void maths::SinCos(float angle, float& sinOut, float& cosOut)
{
*sinOut = sin(angle);
*cosOut = cos(angle);
sinOut = sin(angle);
cosOut = cos(angle);
}
void maths::RotatePt(vector2& point, float sin, float cos, const vector2& origin)
{
auto dirX = point.X - origin.X;
auto dirY = point.Y - origin.Y;
point.X = dirX * cos - dirY * sin + origin.X;
point.Y = dirX * sin + dirY * cos + origin.Y;
auto xOffset = point.X - origin.X;
auto yOffset = point.Y - origin.Y;
point.X = xOffset * cos - yOffset * sin + origin.X;
point.Y = xOffset * sin + yOffset * cos + origin.Y;
}
float maths::distance_to_flipper(ray_type* ray1, ray_type* ray2)
// Return the distance from ray1 origin to the intersection point with the closest flipper feature.
// Sets ray2 origin to intersection point, direction to collision direction
float maths::distance_to_flipper(const ray_type& ray1, ray_type& ray2)
{
auto distance = 1000000000.0f;
auto distanceType = -1;
auto newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineA);
if (newDistance < 1000000000.0f)
{
distance = newDistance;
distanceType = 0;
}
newDistance = ray_intersect_circle(*ray1, TFlipperEdge::circlebase);
auto distanceType = FlipperIntersect::none;
auto newDistance = ray_intersect_line(ray1, TFlipperEdge::lineA);
if (newDistance < distance)
{
distance = newDistance;
distanceType = 2;
distanceType = FlipperIntersect::lineA;
}
newDistance = ray_intersect_circle(*ray1, TFlipperEdge::circleT1);
newDistance = ray_intersect_circle(ray1, TFlipperEdge::circlebase);
if (newDistance < distance)
{
distance = newDistance;
distanceType = 3;
distanceType = FlipperIntersect::circlebase;
}
newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineB);
newDistance = ray_intersect_circle(ray1, TFlipperEdge::circleT1);
if (newDistance < distance)
{
distance = newDistance;
distanceType = 1;
distanceType = FlipperIntersect::circleT1;
}
newDistance = ray_intersect_line(ray1, TFlipperEdge::lineB);
if (newDistance < distance)
{
distance = newDistance;
distanceType = FlipperIntersect::lineB;
}
if (!ray2 || distance >= 1000000000.0f)
return distance;
if (distanceType != -1)
switch (distanceType)
{
vector2* nextOrigin;
if (distanceType)
{
if (distanceType != 1)
{
float dirY;
ray2->Origin.X = distance * ray1->Direction.X + ray1->Origin.X;
ray2->Origin.Y = distance * ray1->Direction.Y + ray1->Origin.Y;
if (distanceType == 2)
{
ray2->Direction.X = ray2->Origin.X - TFlipperEdge::circlebase.Center.X;
dirY = ray2->Origin.Y - TFlipperEdge::circlebase.Center.Y;
case FlipperIntersect::lineA:
ray2.Direction = TFlipperEdge::lineA.PerpendicularC;
ray2.Origin = TFlipperEdge::lineA.RayIntersect;
break;
case FlipperIntersect::lineB:
ray2.Direction = TFlipperEdge::lineB.PerpendicularC;
ray2.Origin = TFlipperEdge::lineB.RayIntersect;
break;
case FlipperIntersect::circlebase:
case FlipperIntersect::circleT1:
ray2.Origin.X = distance * ray1.Direction.X + ray1.Origin.X;
ray2.Origin.Y = distance * ray1.Direction.Y + ray1.Origin.Y;
ray2.Direction = vector_sub(ray2.Origin, distanceType == FlipperIntersect::circlebase ?
TFlipperEdge::circlebase.Center : TFlipperEdge::circleT1.Center);
normalize_2d(ray2.Direction);
break;
case FlipperIntersect::none:
default:
break;
}
else
{
ray2->Direction.X = ray2->Origin.X - TFlipperEdge::circleT1.Center.X;
dirY = ray2->Origin.Y - TFlipperEdge::circleT1.Center.Y;
}
ray2->Direction.Y = dirY;
normalize_2d(ray2->Direction);
return distance;
}
ray2->Direction = TFlipperEdge::lineB.PerpendicularC;
nextOrigin = &TFlipperEdge::lineB.RayIntersect;
}
else
{
ray2->Direction = TFlipperEdge::lineA.PerpendicularC;
nextOrigin = &TFlipperEdge::lineA.RayIntersect;
}
ray2->Origin = *nextOrigin;
return distance;
}
return 1000000000.0;
}
void maths::RotateVector(vector2& vec, float angle)
{
@ -365,14 +356,7 @@ void maths::RotateVector(vector2& vec, float angle)
void maths::find_closest_edge(ramp_plane_type* planes, int planeCount, wall_point_type* wall, vector2& lineEnd,
vector2& lineStart)
{
vector2 wallEnd{}, wallStart{};
wallStart.X = wall->X0;
wallStart.Y = wall->Y0;
wallEnd.Y = wall->Y1;
wallEnd.X = wall->X1;
float maxDistance = 1000000000.0f;
float distance = 1000000000.0f;
for (auto index = 0; index < planeCount; index++)
{
auto& plane = planes[index];
@ -382,10 +366,10 @@ void maths::find_closest_edge(ramp_plane_type* planes, int planeCount, wall_poin
{
auto& point1 = *pointOrder[pt], point2 = *pointOrder[pt + 1];
auto distance = Distance(wallStart, point1) + Distance(wallEnd, point2);
if (distance < maxDistance)
auto newDistance = Distance(wall->Pt0, point1) + Distance(wall->Pt1, point2);
if (newDistance < distance)
{
maxDistance = distance;
distance = newDistance;
lineEnd = point1;
lineStart = point2;
}

View File

@ -59,10 +59,8 @@ struct line_type
struct wall_point_type
{
float X0;
float Y0;
float X1;
float Y1;
vector2 Pt0;
vector2 Pt1;
};
struct ramp_plane_type
@ -76,6 +74,15 @@ struct ramp_plane_type
vector2 FieldForce;
};
enum class FlipperIntersect
{
none = -1,
lineA = 0,
lineB = 1,
circlebase = 2,
circleT1 = 3
};
class maths
{
@ -84,8 +91,8 @@ public:
static bool rectangle_clip(const rectangle_type& rect1, const rectangle_type& rect2, rectangle_type* dstRect);
static float ray_intersect_circle(const ray_type& ray, const circle_type& circle);
static float normalize_2d(vector2& vec);
static void line_init(line_type* line, float x0, float y0, float x1, float y1);
static float ray_intersect_line(ray_type* ray, line_type* line);
static void line_init(line_type& line, float x0, float y0, float x1, float y1);
static float ray_intersect_line(const ray_type& ray, line_type& line);
static void cross(const vector3& vec1, const vector3& vec2, vector3& dstVec);
static float cross(const vector2& vec1, const vector2& vec2);
static float magnitude(const vector3& vec);
@ -97,9 +104,9 @@ public:
static float Distance_Squared(const vector2& vec1, const vector2& vec2);
static float DotProduct(const vector2& vec1, const vector2& vec2);
static float Distance(const vector2& vec1, const vector2& vec2);
static void SinCos(float angle, float* sinOut, float* cosOut);
static void SinCos(float angle, float& sinOut, float& cosOut);
static void RotatePt(vector2& point, float sin, float cos, const vector2& origin);
static float distance_to_flipper(ray_type* ray1, ray_type* ray2);
static float distance_to_flipper(const ray_type& ray1, ray_type& ray2);
static void RotateVector(vector2& vec, float angle);
static void find_closest_edge(ramp_plane_type* plane, int planeCount, wall_point_type* wall, vector2& lineEnd,
vector2& lineStart);