mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-17 15:20:17 +01:00
Cleaning up maths: part 4.
More by ref args, cleaned up distance_to_flipper, ramp init.
This commit is contained in:
parent
fdf1f6c9f1
commit
2d2ca0ab2a
6 changed files with 153 additions and 177 deletions
|
@ -120,7 +120,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
|
||||||
srcRay.Direction = ogRay->Direction;
|
srcRay.Direction = ogRay->Direction;
|
||||||
srcRay.MaxDistance = ogRay->MaxDistance;
|
srcRay.MaxDistance = ogRay->MaxDistance;
|
||||||
srcRay.Origin = ogRay->Origin;
|
srcRay.Origin = ogRay->Origin;
|
||||||
auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
|
auto distance = maths::distance_to_flipper(srcRay, dstRay);
|
||||||
if (distance == 0.0f)
|
if (distance == 0.0f)
|
||||||
{
|
{
|
||||||
NextBallPosition = dstRay.Origin;
|
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.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
|
||||||
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
|
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
|
||||||
srcRay.MaxDistance = ogRay->MaxDistance + 10.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.X = RotOrigin.X - ogRay->Origin.X;
|
||||||
srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
|
srcRay.Direction.Y = RotOrigin.Y - ogRay->Origin.Y;
|
||||||
maths::normalize_2d(srcRay.Direction);
|
maths::normalize_2d(srcRay.Direction);
|
||||||
srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
|
srcRay.Origin.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
|
||||||
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 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;
|
return 1e+09;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
|
||||||
srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f;
|
srcRay.Origin.X = posX - srcRay.Direction.X * 5.0f;
|
||||||
srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f;
|
srcRay.Origin.Y = posY - srcRay.Direction.Y * 5.0f;
|
||||||
srcRay.MaxDistance = ogRay->MaxDistance + 10.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.X = posX;
|
||||||
NextBallPosition.Y = posY;
|
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.X = ogRay->Origin.X - srcRay.Direction.X * 5.0f;
|
||||||
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
|
srcRay.Origin.Y = ogRay->Origin.Y - srcRay.Direction.Y * 5.0f;
|
||||||
srcRay.MaxDistance = ogRay->MaxDistance + 10.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;
|
CollisionDirection = dstRay.Direction;
|
||||||
if (distance >= 1e+09f)
|
if (distance >= 1e+09f)
|
||||||
{
|
{
|
||||||
|
@ -265,7 +265,7 @@ float TFlipperEdge::FindCollisionDistance(ray_type* ray)
|
||||||
srcRay.MinDistance = ogRay->MinDistance;
|
srcRay.MinDistance = ogRay->MinDistance;
|
||||||
srcRay.Origin = ogRay->Origin;
|
srcRay.Origin = ogRay->Origin;
|
||||||
srcRay.MaxDistance = rayMaxDistance;
|
srcRay.MaxDistance = rayMaxDistance;
|
||||||
auto distance = maths::distance_to_flipper(&srcRay, &dstRay);
|
auto distance = maths::distance_to_flipper(srcRay, dstRay);
|
||||||
if (distance < 1e+09f)
|
if (distance < 1e+09f)
|
||||||
{
|
{
|
||||||
NextBallPosition = dstRay.Origin;
|
NextBallPosition = dstRay.Origin;
|
||||||
|
@ -389,7 +389,7 @@ void TFlipperEdge::place_in_grid()
|
||||||
|
|
||||||
void TFlipperEdge::set_control_points(float timeNow)
|
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;
|
A1 = A1Src;
|
||||||
A2 = A2Src;
|
A2 = A2Src;
|
||||||
B1 = B1Src;
|
B1 = B1Src;
|
||||||
|
@ -404,8 +404,8 @@ void TFlipperEdge::set_control_points(float timeNow)
|
||||||
|
|
||||||
void TFlipperEdge::build_edges_in_motion()
|
void TFlipperEdge::build_edges_in_motion()
|
||||||
{
|
{
|
||||||
maths::line_init(&lineA, A1.X, A1.Y, A2.X, A2.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);
|
maths::line_init(lineB, B1.X, B1.Y, B2.X, B2.Y);
|
||||||
circlebase.RadiusSq = CirclebaseRadiusSq;
|
circlebase.RadiusSq = CirclebaseRadiusSq;
|
||||||
circlebase.Center.X = RotOrigin.X;
|
circlebase.Center.X = RotOrigin.X;
|
||||||
circlebase.Center.Y = RotOrigin.Y;
|
circlebase.Center.Y = RotOrigin.Y;
|
||||||
|
|
|
@ -11,7 +11,7 @@ TLine::TLine(TCollisionComponent* collCmp, char* activeFlag, unsigned int collis
|
||||||
Y0 = y0;
|
Y0 = y0;
|
||||||
X1 = x1;
|
X1 = x1;
|
||||||
Y1 = y1;
|
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,
|
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;
|
Y0 = start.Y;
|
||||||
X1 = end.X;
|
X1 = end.X;
|
||||||
Y1 = end.Y;
|
Y1 = end.Y;
|
||||||
maths::line_init(&Line, X0, Y0, X1, Y1);
|
maths::line_init(Line, X0, Y0, X1, Y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLine::Offset(float offset)
|
void TLine::Offset(float offset)
|
||||||
|
@ -33,12 +33,12 @@ void TLine::Offset(float offset)
|
||||||
Y0 += offY;
|
Y0 += offY;
|
||||||
X1 += offX;
|
X1 += offX;
|
||||||
Y1 += offY;
|
Y1 += offY;
|
||||||
maths::line_init(&Line, X0, Y0, X1, Y1);
|
maths::line_init(Line, X0, Y0, X1, Y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
float TLine::FindCollisionDistance(ray_type* ray)
|
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)
|
void TLine::EdgeCollision(TBall* ball, float coef)
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table, groupIndex, false)
|
||||||
{
|
{
|
||||||
visualStruct visual{};
|
visualStruct visual{};
|
||||||
vector2 end{}, start{}, end2{}, start2{}, start3{}, end3{};
|
vector2 wall1End{}, wall1Start{}, wall2Start{}, wall2End{};
|
||||||
|
|
||||||
MessageField = 0;
|
MessageField = 0;
|
||||||
UnusedBaseFlag = 1;
|
UnusedBaseFlag = 1;
|
||||||
|
@ -22,60 +22,51 @@ TRamp::TRamp(TPinballTable* table, int groupIndex) : TCollisionComponent(table,
|
||||||
CollisionGroup = visual.CollisionGroup;
|
CollisionGroup = visual.CollisionGroup;
|
||||||
|
|
||||||
BallFieldMult = loader::query_float_attribute(groupIndex, 0, 701, 0.2f);
|
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);
|
auto floatArr3Plane = loader::query_float_attribute(groupIndex, 0, 1300);
|
||||||
RampPlaneCount = static_cast<int>(floor(*floatArr3Plane));
|
RampPlaneCount = static_cast<int>(floor(*floatArr3Plane));
|
||||||
RampPlane = reinterpret_cast<ramp_plane_type*>(floatArr3Plane + 1);
|
RampPlane = reinterpret_cast<ramp_plane_type*>(floatArr3Plane + 1);
|
||||||
|
|
||||||
auto floatArr4 = loader::query_float_attribute(groupIndex, 0, 1303);
|
auto wall0Arr = loader::query_float_attribute(groupIndex, 0, 1303);
|
||||||
end.X = floatArr4[2];
|
auto wall0CollisionGroup = 1 << static_cast<int>(floor(wall0Arr[0]));
|
||||||
end.Y = floatArr4[3];
|
auto wall0Pts = reinterpret_cast<wall_point_type*>(wall0Arr + 2);
|
||||||
start.X = floatArr4[4];
|
Line1 = new TLine(this, &ActiveFlag, wall0CollisionGroup, wall0Pts->Pt1, wall0Pts->Pt0);
|
||||||
start.Y = floatArr4[5];
|
|
||||||
Line1 = new TLine(this, &ActiveFlag, 1 << static_cast<int>(floor(floatArr4[0])), start, end);
|
|
||||||
EdgeList.push_back(Line1);
|
|
||||||
if (Line1)
|
|
||||||
{
|
|
||||||
Line1->WallValue = nullptr;
|
Line1->WallValue = nullptr;
|
||||||
Line1->place_in_grid();
|
Line1->place_in_grid();
|
||||||
}
|
EdgeList.push_back(Line1);
|
||||||
|
|
||||||
auto floatArr5WallPoint = loader::query_float_attribute(groupIndex, 0, 1301);
|
auto wall1Arr = loader::query_float_attribute(groupIndex, 0, 1301);
|
||||||
Wall1PointFirst = 1 << static_cast<int>(floor(floatArr5WallPoint[0]));
|
Wall1CollisionGroup = 1 << static_cast<int>(floor(wall1Arr[0]));
|
||||||
auto wallPt1_2 = static_cast<int>(floor(floatArr5WallPoint[1]));
|
auto wall1Enabled = static_cast<int>(floor(wall1Arr[1]));
|
||||||
Wall1PointLast = floatArr5WallPoint[7];
|
Wall1BallOffset = wall1Arr[7];
|
||||||
maths::find_closest_edge(
|
maths::find_closest_edge(
|
||||||
RampPlane,
|
RampPlane,
|
||||||
RampPlaneCount,
|
RampPlaneCount,
|
||||||
reinterpret_cast<wall_point_type*>(floatArr5WallPoint + 3),
|
reinterpret_cast<wall_point_type*>(wall1Arr + 3),
|
||||||
end2,
|
wall1End,
|
||||||
start2);
|
wall1Start);
|
||||||
Line2 = new TLine(this, &ActiveFlag, CollisionGroup, start2, end2);
|
|
||||||
EdgeList.push_back(Line2);
|
Line2 = new TLine(this, &ActiveFlag, CollisionGroup, wall1Start, wall1End);
|
||||||
if (Line2)
|
|
||||||
{
|
|
||||||
Line2->WallValue = nullptr;
|
Line2->WallValue = nullptr;
|
||||||
Line2->place_in_grid();
|
Line2->place_in_grid();
|
||||||
}
|
EdgeList.push_back(Line2);
|
||||||
|
|
||||||
auto floatArr6WallPoint = loader::query_float_attribute(groupIndex, 0, 1302);
|
auto wall2Arr = loader::query_float_attribute(groupIndex, 0, 1302);
|
||||||
auto wall2Pt1_2 = static_cast<int>(floor(floatArr6WallPoint[1]));
|
Wall2CollisionGroup = 1 << static_cast<int>(floor(wall2Arr[0]));
|
||||||
Wall2PointFirst = 1 << static_cast<int>(floor(floatArr6WallPoint[0]));
|
auto wall2Enabled = static_cast<int>(floor(wall2Arr[1]));
|
||||||
Wall2PointLast = floatArr6WallPoint[7];
|
Wall2BallOffset = wall2Arr[7];
|
||||||
maths::find_closest_edge(
|
maths::find_closest_edge(
|
||||||
RampPlane,
|
RampPlane,
|
||||||
RampPlaneCount,
|
RampPlaneCount,
|
||||||
reinterpret_cast<wall_point_type*>(floatArr6WallPoint + 3),
|
reinterpret_cast<wall_point_type*>(wall2Arr + 3),
|
||||||
end3,
|
wall2End,
|
||||||
start3);
|
wall2Start);
|
||||||
Line3 = new TLine(this, &ActiveFlag, CollisionGroup, start3, end3);
|
|
||||||
EdgeList.push_back(Line3);
|
Line3 = new TLine(this, &ActiveFlag, CollisionGroup, wall2Start, wall2End);
|
||||||
if (Line3)
|
|
||||||
{
|
|
||||||
Line3->WallValue = nullptr;
|
Line3->WallValue = nullptr;
|
||||||
Line3->place_in_grid();
|
Line3->place_in_grid();
|
||||||
}
|
EdgeList.push_back(Line3);
|
||||||
|
|
||||||
|
|
||||||
auto xMin = 1000000000.0f;
|
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& point1 = *pointOrder[pt], point2 = *pointOrder[pt + 1];
|
||||||
auto collisionGroup = 0;
|
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;
|
collisionGroup = visual.CollisionGroup;
|
||||||
}
|
|
||||||
else if (wall2Pt1_2)
|
|
||||||
{
|
|
||||||
collisionGroup = Wall2PointFirst;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (wallPt1_2)
|
|
||||||
{
|
|
||||||
collisionGroup = Wall1PointFirst;
|
|
||||||
}
|
|
||||||
if (collisionGroup)
|
if (collisionGroup)
|
||||||
{
|
{
|
||||||
auto line = new TLine(this, &ActiveFlag, collisionGroup, point1, point2);
|
auto line = new TLine(this, &ActiveFlag, collisionGroup, point1, point2);
|
||||||
EdgeList.push_back(line);
|
|
||||||
if (line)
|
|
||||||
{
|
|
||||||
line->WallValue = &plane;
|
line->WallValue = &plane;
|
||||||
line->place_in_grid();
|
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;
|
ball->CollisionFlag = 0;
|
||||||
if (edge == Line2)
|
if (edge == Line2)
|
||||||
{
|
{
|
||||||
ball->FieldFlag = Wall1PointFirst;
|
ball->FieldFlag = Wall1CollisionGroup;
|
||||||
if (!RampFlag1)
|
if (BallZOffsetFlag)
|
||||||
return;
|
ball->Position.Z = ball->Offset + Wall1BallOffset;
|
||||||
ball->Position.Z = ball->Offset + Wall1PointLast;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ball->FieldFlag = Wall2PointFirst;
|
ball->FieldFlag = Wall2CollisionGroup;
|
||||||
if (!RampFlag1)
|
if (BallZOffsetFlag)
|
||||||
return;
|
ball->Position.Z = ball->Offset + Wall2BallOffset;
|
||||||
ball->Position.Z = ball->Offset + Wall2PointLast;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,15 @@ public:
|
||||||
int Scores[4]{};
|
int Scores[4]{};
|
||||||
field_effect_type Field{};
|
field_effect_type Field{};
|
||||||
int CollisionGroup;
|
int CollisionGroup;
|
||||||
int RampFlag1;
|
bool BallZOffsetFlag;
|
||||||
int RampPlaneCount;
|
int RampPlaneCount;
|
||||||
float BallFieldMult;
|
float BallFieldMult;
|
||||||
ramp_plane_type* RampPlane;
|
ramp_plane_type* RampPlane;
|
||||||
TEdgeSegment* Line2;
|
TEdgeSegment* Line2;
|
||||||
TEdgeSegment* Line3;
|
TEdgeSegment* Line3;
|
||||||
TEdgeSegment* Line1;
|
TEdgeSegment* Line1;
|
||||||
int Wall1PointFirst;
|
int Wall1CollisionGroup;
|
||||||
int Wall2PointFirst;
|
int Wall2CollisionGroup;
|
||||||
float Wall1PointLast;
|
float Wall1BallOffset;
|
||||||
float Wall2PointLast;
|
float Wall2BallOffset;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.Origin = { x0, y0 };
|
||||||
line->Direction.X = x1 - x0;
|
line.Direction.X = x1 - x0;
|
||||||
line->Direction.Y = y1 - y0;
|
line.Direction.Y = y1 - y0;
|
||||||
normalize_2d(line->Direction);
|
normalize_2d(line.Direction);
|
||||||
|
|
||||||
// Clockwise perpendicular to the line direction vector
|
// 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;
|
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;
|
lineStart = y0;
|
||||||
lineEnd = y1;
|
lineEnd = y1;
|
||||||
}
|
}
|
||||||
|
|
||||||
line->MinCoord = std::min(lineStart, lineEnd);
|
line.MinCoord = std::min(lineStart, lineEnd);
|
||||||
line->MaxCoord = std::max(lineStart, lineEnd);
|
line.MaxCoord = std::max(lineStart, lineEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the distance from ray origin to the ray-line segment intersection point.
|
// 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
|
// V1 vector between ray origin and line origin
|
||||||
// V2 ray direction
|
// V2 ray direction
|
||||||
// V3 line perpendicular clockwise
|
// V3 line perpendicular clockwise
|
||||||
auto v1 = vector_sub(ray->Origin, line->Origin);
|
auto v1 = vector_sub(ray.Origin, line.Origin);
|
||||||
auto v2 = line->Direction;
|
auto v2 = line.Direction;
|
||||||
auto v3 = vector2{ -ray->Direction.Y, ray->Direction.X };
|
auto v3 = vector2{ -ray.Direction.Y, ray.Direction.X };
|
||||||
|
|
||||||
// Project line on ray perpendicular, no intersection if ray is pointing away from the line
|
// Project line on ray perpendicular, no intersection if ray is pointing away from the line
|
||||||
auto v2DotV3 = DotProduct(v2, v3);
|
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)
|
// Distance to the intersect point: (V2 X V1) / (V2 dot V3)
|
||||||
auto distance = cross(v2, v1) / v2DotV3;
|
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.X = distance * ray.Direction.X + ray.Origin.X;
|
||||||
line->RayIntersect.Y = distance * ray->Direction.Y + ray->Origin.Y;
|
line.RayIntersect.Y = distance * ray.Direction.Y + ray.Origin.Y;
|
||||||
|
|
||||||
// Check if intersection point is inside line segment
|
// Check if intersection point is inside line segment
|
||||||
auto testPoint = line->Direction.X != 0.0f ? line->RayIntersect.X : line->RayIntersect.Y;
|
auto testPoint = line.Direction.X != 0.0f ? line.RayIntersect.X : line.RayIntersect.Y;
|
||||||
if (testPoint >= line->MinCoord && testPoint <= line->MaxCoord)
|
if (testPoint >= line.MinCoord && testPoint <= line.MaxCoord)
|
||||||
{
|
{
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
@ -223,7 +224,8 @@ float maths::basic_collision(TBall* ball, vector2* nextPosition, vector2* direct
|
||||||
{
|
{
|
||||||
ball->Position.X = nextPosition->X;
|
ball->Position.X = nextPosition->X;
|
||||||
ball->Position.Y = nextPosition->Y;
|
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)
|
if (proj < 0)
|
||||||
{
|
{
|
||||||
proj = -proj;
|
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;
|
ball->Acceleration.Y = (dy1 + ball->Acceleration.Y) * smoothness + dy1 * elasticity;
|
||||||
normalize_2d(ball->Acceleration);
|
normalize_2d(ball->Acceleration);
|
||||||
}
|
}
|
||||||
|
|
||||||
float projSpeed = proj * ball->Speed;
|
float projSpeed = proj * ball->Speed;
|
||||||
float newSpeed = ball->Speed - (1.0f - elasticity) * projSpeed;
|
float newSpeed = ball->Speed - (1.0f - elasticity) * projSpeed;
|
||||||
ball->Speed = newSpeed;
|
ball->Speed = newSpeed;
|
||||||
|
@ -265,87 +268,75 @@ float maths::Distance(const vector2& vec1, const vector2& vec2)
|
||||||
return sqrt(Distance_Squared(vec1, 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);
|
sinOut = sin(angle);
|
||||||
*cosOut = cos(angle);
|
cosOut = cos(angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void maths::RotatePt(vector2& point, float sin, float cos, const vector2& origin)
|
void maths::RotatePt(vector2& point, float sin, float cos, const vector2& origin)
|
||||||
{
|
{
|
||||||
auto dirX = point.X - origin.X;
|
auto xOffset = point.X - origin.X;
|
||||||
auto dirY = point.Y - origin.Y;
|
auto yOffset = point.Y - origin.Y;
|
||||||
point.X = dirX * cos - dirY * sin + origin.X;
|
point.X = xOffset * cos - yOffset * sin + origin.X;
|
||||||
point.Y = dirX * sin + dirY * cos + origin.Y;
|
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 distance = 1000000000.0f;
|
||||||
auto distanceType = -1;
|
auto distanceType = FlipperIntersect::none;
|
||||||
auto newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineA);
|
auto newDistance = ray_intersect_line(ray1, TFlipperEdge::lineA);
|
||||||
if (newDistance < 1000000000.0f)
|
|
||||||
{
|
|
||||||
distance = newDistance;
|
|
||||||
distanceType = 0;
|
|
||||||
}
|
|
||||||
newDistance = ray_intersect_circle(*ray1, TFlipperEdge::circlebase);
|
|
||||||
if (newDistance < distance)
|
if (newDistance < distance)
|
||||||
{
|
{
|
||||||
distance = newDistance;
|
distance = newDistance;
|
||||||
distanceType = 2;
|
distanceType = FlipperIntersect::lineA;
|
||||||
}
|
}
|
||||||
newDistance = ray_intersect_circle(*ray1, TFlipperEdge::circleT1);
|
newDistance = ray_intersect_circle(ray1, TFlipperEdge::circlebase);
|
||||||
if (newDistance < distance)
|
if (newDistance < distance)
|
||||||
{
|
{
|
||||||
distance = newDistance;
|
distance = newDistance;
|
||||||
distanceType = 3;
|
distanceType = FlipperIntersect::circlebase;
|
||||||
}
|
}
|
||||||
newDistance = ray_intersect_line(ray1, &TFlipperEdge::lineB);
|
newDistance = ray_intersect_circle(ray1, TFlipperEdge::circleT1);
|
||||||
if (newDistance < distance)
|
if (newDistance < distance)
|
||||||
{
|
{
|
||||||
distance = newDistance;
|
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;
|
case FlipperIntersect::lineA:
|
||||||
if (distanceType)
|
ray2.Direction = TFlipperEdge::lineA.PerpendicularC;
|
||||||
{
|
ray2.Origin = TFlipperEdge::lineA.RayIntersect;
|
||||||
if (distanceType != 1)
|
break;
|
||||||
{
|
case FlipperIntersect::lineB:
|
||||||
float dirY;
|
ray2.Direction = TFlipperEdge::lineB.PerpendicularC;
|
||||||
ray2->Origin.X = distance * ray1->Direction.X + ray1->Origin.X;
|
ray2.Origin = TFlipperEdge::lineB.RayIntersect;
|
||||||
ray2->Origin.Y = distance * ray1->Direction.Y + ray1->Origin.Y;
|
break;
|
||||||
if (distanceType == 2)
|
case FlipperIntersect::circlebase:
|
||||||
{
|
case FlipperIntersect::circleT1:
|
||||||
ray2->Direction.X = ray2->Origin.X - TFlipperEdge::circlebase.Center.X;
|
ray2.Origin.X = distance * ray1.Direction.X + ray1.Origin.X;
|
||||||
dirY = ray2->Origin.Y - TFlipperEdge::circlebase.Center.Y;
|
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;
|
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)
|
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,
|
void maths::find_closest_edge(ramp_plane_type* planes, int planeCount, wall_point_type* wall, vector2& lineEnd,
|
||||||
vector2& lineStart)
|
vector2& lineStart)
|
||||||
{
|
{
|
||||||
vector2 wallEnd{}, wallStart{};
|
float distance = 1000000000.0f;
|
||||||
|
|
||||||
wallStart.X = wall->X0;
|
|
||||||
wallStart.Y = wall->Y0;
|
|
||||||
wallEnd.Y = wall->Y1;
|
|
||||||
wallEnd.X = wall->X1;
|
|
||||||
|
|
||||||
float maxDistance = 1000000000.0f;
|
|
||||||
for (auto index = 0; index < planeCount; index++)
|
for (auto index = 0; index < planeCount; index++)
|
||||||
{
|
{
|
||||||
auto& plane = planes[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& point1 = *pointOrder[pt], point2 = *pointOrder[pt + 1];
|
||||||
|
|
||||||
auto distance = Distance(wallStart, point1) + Distance(wallEnd, point2);
|
auto newDistance = Distance(wall->Pt0, point1) + Distance(wall->Pt1, point2);
|
||||||
if (distance < maxDistance)
|
if (newDistance < distance)
|
||||||
{
|
{
|
||||||
maxDistance = distance;
|
distance = newDistance;
|
||||||
lineEnd = point1;
|
lineEnd = point1;
|
||||||
lineStart = point2;
|
lineStart = point2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,10 +59,8 @@ struct line_type
|
||||||
|
|
||||||
struct wall_point_type
|
struct wall_point_type
|
||||||
{
|
{
|
||||||
float X0;
|
vector2 Pt0;
|
||||||
float Y0;
|
vector2 Pt1;
|
||||||
float X1;
|
|
||||||
float Y1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ramp_plane_type
|
struct ramp_plane_type
|
||||||
|
@ -76,6 +74,15 @@ struct ramp_plane_type
|
||||||
vector2 FieldForce;
|
vector2 FieldForce;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class FlipperIntersect
|
||||||
|
{
|
||||||
|
none = -1,
|
||||||
|
lineA = 0,
|
||||||
|
lineB = 1,
|
||||||
|
circlebase = 2,
|
||||||
|
circleT1 = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class maths
|
class maths
|
||||||
{
|
{
|
||||||
|
@ -84,8 +91,8 @@ public:
|
||||||
static bool rectangle_clip(const rectangle_type& rect1, const rectangle_type& rect2, rectangle_type* dstRect);
|
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 ray_intersect_circle(const ray_type& ray, const circle_type& circle);
|
||||||
static float normalize_2d(vector2& vec);
|
static float normalize_2d(vector2& vec);
|
||||||
static void line_init(line_type* line, float x0, float y0, float x1, float y1);
|
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 float ray_intersect_line(const ray_type& ray, line_type& line);
|
||||||
static void cross(const vector3& vec1, const vector3& vec2, vector3& dstVec);
|
static void cross(const vector3& vec1, const vector3& vec2, vector3& dstVec);
|
||||||
static float cross(const vector2& vec1, const vector2& vec2);
|
static float cross(const vector2& vec1, const vector2& vec2);
|
||||||
static float magnitude(const vector3& vec);
|
static float magnitude(const vector3& vec);
|
||||||
|
@ -97,9 +104,9 @@ public:
|
||||||
static float Distance_Squared(const vector2& vec1, const vector2& vec2);
|
static float Distance_Squared(const vector2& vec1, const vector2& vec2);
|
||||||
static float DotProduct(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 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 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 RotateVector(vector2& vec, float angle);
|
||||||
static void find_closest_edge(ramp_plane_type* plane, int planeCount, wall_point_type* wall, vector2& lineEnd,
|
static void find_closest_edge(ramp_plane_type* plane, int planeCount, wall_point_type* wall, vector2& lineEnd,
|
||||||
vector2& lineStart);
|
vector2& lineStart);
|
||||||
|
|
Loading…
Reference in a new issue