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.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;

View File

@ -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)

View File

@ -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->WallValue = nullptr;
Line1 = new TLine(this, &ActiveFlag, 1 << static_cast<int>(floor(floatArr4[0])), start, end); Line1->place_in_grid();
EdgeList.push_back(Line1); EdgeList.push_back(Line1);
if (Line1)
{
Line1->WallValue = nullptr;
Line1->place_in_grid();
}
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);
Line2 = new TLine(this, &ActiveFlag, CollisionGroup, wall1Start, wall1End);
Line2->WallValue = nullptr;
Line2->place_in_grid();
EdgeList.push_back(Line2); EdgeList.push_back(Line2);
if (Line2)
{
Line2->WallValue = nullptr;
Line2->place_in_grid();
}
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);
Line3 = new TLine(this, &ActiveFlag, CollisionGroup, wall2Start, wall2End);
Line3->WallValue = nullptr;
Line3->place_in_grid();
EdgeList.push_back(Line3); EdgeList.push_back(Line3);
if (Line3)
{
Line3->WallValue = nullptr;
Line3->place_in_grid();
}
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;
collisionGroup = visual.CollisionGroup;
}
else if (wall2Pt1_2)
{
collisionGroup = Wall2PointFirst;
}
} }
else if (wallPt1_2) else if (point1 == wall2End && point2 == wall2Start)
{ {
collisionGroup = Wall1PointFirst; if (wall2Enabled)
collisionGroup = Wall2CollisionGroup;
} }
else
collisionGroup = visual.CollisionGroup;
if (collisionGroup) if (collisionGroup)
{ {
auto line = new TLine(this, &ActiveFlag, collisionGroup, point1, point2); auto line = new TLine(this, &ActiveFlag, collisionGroup, point1, point2);
line->WallValue = &plane;
line->place_in_grid();
EdgeList.push_back(line); EdgeList.push_back(line);
if (line)
{
line->WallValue = &plane;
line->place_in_grid();
}
} }
} }
@ -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;
} }
} }
} }

View File

@ -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;
}; };

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.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 ?
else TFlipperEdge::circlebase.Center : TFlipperEdge::circleT1.Center);
{ normalize_2d(ray2.Direction);
ray2->Direction.X = ray2->Origin.X - TFlipperEdge::circleT1.Center.X; break;
dirY = ray2->Origin.Y - TFlipperEdge::circleT1.Center.Y; case FlipperIntersect::none:
} default:
ray2->Direction.Y = dirY; break;
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;
return distance;
} }
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;
} }

View File

@ -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);