2021-01-09 17:11:03 +01:00
|
|
|
#include "pch.h"
|
|
|
|
#include "TFlipperEdge.h"
|
|
|
|
|
|
|
|
|
2022-08-23 07:14:28 +02:00
|
|
|
#include "pb.h"
|
2021-01-09 17:11:03 +01:00
|
|
|
#include "TLine.h"
|
|
|
|
#include "TPinballTable.h"
|
|
|
|
#include "TTableLayer.h"
|
|
|
|
|
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* activeFlag, unsigned int collisionGroup,
|
|
|
|
TPinballTable* table,
|
|
|
|
vector3* origin, vector3* vecT1, vector3* vecT2, float extendSpeed, float retractSpeed,
|
|
|
|
float collMult, float elasticity, float smoothness): TEdgeSegment(
|
|
|
|
collComp, activeFlag, collisionGroup)
|
2021-01-09 17:11:03 +01:00
|
|
|
{
|
2022-12-28 06:47:44 +01:00
|
|
|
vector3 crossProd{}, vecOriginT1{}, vecOriginT2{};
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2021-01-23 11:33:30 +01:00
|
|
|
Elasticity = elasticity;
|
|
|
|
Smoothness = smoothness;
|
2021-01-10 13:22:06 +01:00
|
|
|
CollisionMult = collMult;
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2022-05-13 10:15:30 +02:00
|
|
|
T1Src = static_cast<vector2>(*vecT1);
|
|
|
|
T2Src = static_cast<vector2>(*vecT2);
|
2021-01-09 17:11:03 +01:00
|
|
|
RotOrigin.X = origin->X;
|
|
|
|
RotOrigin.Y = origin->Y;
|
|
|
|
|
|
|
|
CirclebaseRadius = origin->Z + table->CollisionCompOffset;
|
|
|
|
CirclebaseRadiusMSq = CirclebaseRadius * 1.01f * (CirclebaseRadius * 1.01f);
|
|
|
|
CirclebaseRadiusSq = CirclebaseRadius * CirclebaseRadius;
|
|
|
|
|
2021-01-10 13:22:06 +01:00
|
|
|
CircleT1Radius = vecT1->Z + table->CollisionCompOffset;
|
2021-01-09 17:11:03 +01:00
|
|
|
CircleT1RadiusMSq = CircleT1Radius * 1.01f * (CircleT1Radius * 1.01f);
|
|
|
|
CircleT1RadiusSq = CircleT1Radius * CircleT1Radius;
|
|
|
|
|
2022-12-28 06:47:44 +01:00
|
|
|
vecOriginT1.X = vecT1->X - origin->X;
|
|
|
|
vecOriginT1.Y = vecT1->Y - origin->Y;
|
|
|
|
vecOriginT1.Z = 0.0;
|
|
|
|
maths::normalize_2d(vecOriginT1);
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2022-12-28 06:47:44 +01:00
|
|
|
vecOriginT2.X = vecT2->X - origin->X;
|
|
|
|
vecOriginT2.Y = vecT2->Y - origin->Y;
|
|
|
|
vecOriginT2.Z = 0.0;
|
|
|
|
maths::normalize_2d(vecOriginT2);
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2022-12-28 06:47:44 +01:00
|
|
|
AngleMax = acos(maths::DotProduct(vecOriginT1, vecOriginT2));
|
|
|
|
maths::cross(vecOriginT1, vecOriginT2, crossProd);
|
2021-02-18 10:53:25 +01:00
|
|
|
if (crossProd.Z < 0.0f)
|
2021-01-09 17:11:03 +01:00
|
|
|
AngleMax = -AngleMax;
|
2022-12-28 06:47:44 +01:00
|
|
|
|
2022-09-08 09:51:33 +02:00
|
|
|
FlipperFlag = MessageCode::TFlipperNull;
|
2022-08-23 07:14:28 +02:00
|
|
|
AngleDst = 0.0;
|
|
|
|
|
|
|
|
// 3DPB and FT have different formats for flipper speed:
|
|
|
|
// 3DPB: Time it takes for flipper to go from source to destination, in sec.
|
|
|
|
// FT: Flipper movement speed, in radians per sec.
|
2023-03-04 15:31:23 +01:00
|
|
|
if (!pb::FullTiltMode)
|
2022-08-23 07:14:28 +02:00
|
|
|
{
|
|
|
|
auto angleMax = std::abs(AngleMax);
|
2023-03-04 15:31:23 +01:00
|
|
|
retractSpeed = angleMax / retractSpeed;
|
|
|
|
extendSpeed = angleMax / extendSpeed;
|
2022-08-23 07:14:28 +02:00
|
|
|
}
|
2023-03-04 15:31:23 +01:00
|
|
|
ExtendSpeed = extendSpeed;
|
|
|
|
RetractSpeed = retractSpeed;
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
const vector2 perpOriginT1Cc = {-vecOriginT1.Y, vecOriginT1.X};
|
2022-12-28 06:47:44 +01:00
|
|
|
A2Src.X = perpOriginT1Cc.X * CirclebaseRadius + origin->X;
|
|
|
|
A2Src.Y = perpOriginT1Cc.Y * CirclebaseRadius + origin->Y;
|
|
|
|
A1Src.X = perpOriginT1Cc.X * CircleT1Radius + vecT1->X;
|
|
|
|
A1Src.Y = perpOriginT1Cc.Y * CircleT1Radius + vecT1->Y;
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
const vector2 perpOriginT1C = {vecOriginT1.Y, -vecOriginT1.X};
|
2022-12-28 06:47:44 +01:00
|
|
|
B1Src.X = perpOriginT1C.X * CirclebaseRadius + origin->X;
|
|
|
|
B1Src.Y = perpOriginT1C.Y * CirclebaseRadius + origin->Y;
|
|
|
|
B2Src.X = perpOriginT1C.X * CircleT1Radius + vecT1->X;
|
|
|
|
B2Src.Y = perpOriginT1C.Y * CircleT1Radius + vecT1->Y;
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2021-02-18 10:53:25 +01:00
|
|
|
if (AngleMax < 0.0f)
|
2021-01-09 17:11:03 +01:00
|
|
|
{
|
2022-05-13 10:15:30 +02:00
|
|
|
std::swap(A1Src, B1Src);
|
|
|
|
std::swap(A2Src, B2Src);
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
2021-01-10 13:22:06 +01:00
|
|
|
auto dx = vecT1->X - RotOrigin.X;
|
|
|
|
auto dy = vecT1->Y - RotOrigin.Y;
|
|
|
|
auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT1->Z;
|
2023-03-04 15:31:23 +01:00
|
|
|
DistanceDiv = distance1;
|
2021-01-09 17:11:03 +01:00
|
|
|
DistanceDivSq = distance1 * distance1;
|
2023-03-04 15:31:23 +01:00
|
|
|
InvT1Radius = 1.0f / CircleT1Radius * 1.5f;
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
if (AngleMax <= 0.0f)
|
|
|
|
{
|
|
|
|
ExtendSpeed = -ExtendSpeed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RetractSpeed = -RetractSpeed;
|
|
|
|
}
|
|
|
|
set_control_points(CurrentAngle);
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void TFlipperEdge::port_draw()
|
|
|
|
{
|
2023-03-04 15:31:23 +01:00
|
|
|
set_control_points(CurrentAngle);
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
float TFlipperEdge::FindCollisionDistance(ray_type* ray)
|
|
|
|
{
|
2023-03-04 15:31:23 +01:00
|
|
|
ray_type dstRay{};
|
|
|
|
if (ControlPointDirtyFlag)
|
|
|
|
set_control_points(CurrentAngle);
|
|
|
|
auto distance = maths::distance_to_flipper(this, *ray, dstRay);
|
|
|
|
if (distance >= 1e9f)
|
|
|
|
return 1e9f;
|
|
|
|
|
|
|
|
NextBallPosition = dstRay.Origin;
|
|
|
|
CollisionDirection = dstRay.Direction;
|
|
|
|
return distance;
|
|
|
|
}
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
void TFlipperEdge::EdgeCollision(TBall* ball, float distance)
|
|
|
|
{
|
|
|
|
if (FlipperFlag == MessageCode::TFlipperNull)
|
2021-01-10 13:22:06 +01:00
|
|
|
{
|
2023-03-04 15:31:23 +01:00
|
|
|
maths::basic_collision(
|
|
|
|
ball,
|
|
|
|
&NextBallPosition,
|
|
|
|
&CollisionDirection,
|
|
|
|
Elasticity,
|
|
|
|
Smoothness,
|
|
|
|
1e9f,
|
|
|
|
0);
|
|
|
|
return;
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
2023-03-04 15:31:23 +01:00
|
|
|
|
|
|
|
auto someProduct = (NextBallPosition.Y - T1.Y) * (RotOrigin.X - T1.X) -
|
|
|
|
(NextBallPosition.X - T1.X) * (RotOrigin.Y - T1.Y);
|
|
|
|
|
|
|
|
bool someFlag = false;
|
|
|
|
if (someProduct <= 0)
|
2021-01-10 13:22:06 +01:00
|
|
|
{
|
2023-03-04 15:31:23 +01:00
|
|
|
if (AngleMax > 0)
|
|
|
|
someFlag = true;
|
|
|
|
}
|
|
|
|
else if (AngleMax <= 0)
|
|
|
|
{
|
|
|
|
someFlag = true;
|
|
|
|
}
|
2021-01-10 13:22:06 +01:00
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
if (FlipperFlag == MessageCode::TFlipperRetract)
|
|
|
|
{
|
|
|
|
someFlag ^= true;
|
|
|
|
CollisionLinePerp = LineB.PerpendicularC;
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
2021-01-10 13:22:06 +01:00
|
|
|
else
|
|
|
|
{
|
2023-03-04 15:31:23 +01:00
|
|
|
CollisionLinePerp = LineA.PerpendicularC;
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
auto dx = NextBallPosition.X - RotOrigin.X;
|
|
|
|
auto dy = NextBallPosition.Y - RotOrigin.Y;
|
|
|
|
auto distanceSq = dy * dy + dx * dx;
|
|
|
|
if (someFlag)
|
2021-01-09 17:11:03 +01:00
|
|
|
{
|
2023-03-04 15:31:23 +01:00
|
|
|
float boost = 0;
|
|
|
|
if (circlebase.RadiusSq * 1.01f < distanceSq)
|
2021-01-09 17:11:03 +01:00
|
|
|
{
|
2023-03-04 15:31:23 +01:00
|
|
|
auto v21 = std::fabs(MoveSpeed) * std::sqrt(distanceSq / DistanceDivSq);
|
|
|
|
auto dot1 = maths::DotProduct(CollisionLinePerp, CollisionDirection);
|
|
|
|
if (dot1 >= 0)
|
|
|
|
boost = CollisionMult * dot1 * v21;
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
auto threshold = boost <= 0.0f ? 1e9f : -1.0f;
|
2021-01-09 17:11:03 +01:00
|
|
|
maths::basic_collision(
|
|
|
|
ball,
|
|
|
|
&NextBallPosition,
|
|
|
|
&CollisionDirection,
|
2021-01-23 11:33:30 +01:00
|
|
|
Elasticity,
|
|
|
|
Smoothness,
|
|
|
|
threshold,
|
|
|
|
boost);
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
else
|
2023-03-04 15:31:23 +01:00
|
|
|
{
|
|
|
|
auto elasticity = Elasticity;
|
|
|
|
if (circlebase.RadiusSq * 1.01f < distanceSq)
|
|
|
|
elasticity = (1.0f - std::sqrt(distanceSq / DistanceDivSq)) * Elasticity;
|
|
|
|
maths::basic_collision(ball, &NextBallPosition, &CollisionDirection, elasticity, Smoothness, 1e9f, 0.0);
|
|
|
|
}
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
2022-12-28 06:47:44 +01:00
|
|
|
void TFlipperEdge::place_in_grid(RectF* aabb)
|
2021-01-09 17:11:03 +01:00
|
|
|
{
|
2022-12-28 06:47:44 +01:00
|
|
|
auto xMax = std::max(std::max(T2Src.X + CircleT1Radius, T1Src.X + CircleT1Radius), RotOrigin.X + CirclebaseRadius);
|
|
|
|
auto yMax = std::max(std::max(T2Src.Y + CircleT1Radius, T1Src.Y + CircleT1Radius), RotOrigin.Y + CirclebaseRadius);
|
|
|
|
auto xMin = std::min(std::min(T2Src.X - CircleT1Radius, T1Src.X - CircleT1Radius), RotOrigin.X - CirclebaseRadius);
|
|
|
|
auto yMin = std::min(std::min(T2Src.Y - CircleT1Radius, T1Src.Y - CircleT1Radius), RotOrigin.Y - CirclebaseRadius);
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2022-12-28 06:47:44 +01:00
|
|
|
if (aabb)
|
|
|
|
{
|
|
|
|
aabb->Merge({xMax, yMax, xMin, yMin});
|
|
|
|
}
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2022-12-28 06:47:44 +01:00
|
|
|
TTableLayer::edges_insert_square(yMin, xMin, yMax, xMax, this, nullptr);
|
2023-03-04 15:31:23 +01:00
|
|
|
|
|
|
|
auto offset = 1.0f / InvT1Radius + pb::ball_min_smth;
|
|
|
|
XMin = xMin - offset;
|
|
|
|
YMin = yMin - offset;
|
|
|
|
XMax = xMax + offset;
|
|
|
|
YMax = yMax + offset;
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
void TFlipperEdge::set_control_points(float angle)
|
2021-01-09 17:11:03 +01:00
|
|
|
{
|
2022-08-23 07:14:28 +02:00
|
|
|
float sin, cos;
|
2023-03-04 15:31:23 +01:00
|
|
|
maths::SinCos(angle, sin, cos);
|
2021-01-09 17:11:03 +01:00
|
|
|
A1 = A1Src;
|
|
|
|
A2 = A2Src;
|
|
|
|
B1 = B1Src;
|
|
|
|
B2 = B2Src;
|
|
|
|
T1 = T1Src;
|
2022-08-23 07:14:28 +02:00
|
|
|
maths::RotatePt(A1, sin, cos, RotOrigin);
|
|
|
|
maths::RotatePt(A2, sin, cos, RotOrigin);
|
|
|
|
maths::RotatePt(T1, sin, cos, RotOrigin);
|
|
|
|
maths::RotatePt(B1, sin, cos, RotOrigin);
|
|
|
|
maths::RotatePt(B2, sin, cos, RotOrigin);
|
2023-03-04 15:31:23 +01:00
|
|
|
maths::line_init(LineA, A1.X, A1.Y, A2.X, A2.Y);
|
|
|
|
maths::line_init(LineB, B1.X, B1.Y, B2.X, B2.Y);
|
2022-08-23 07:14:28 +02:00
|
|
|
circlebase = {RotOrigin, CirclebaseRadiusSq};
|
|
|
|
circleT1 = {T1, CircleT1RadiusSq};
|
2023-03-04 15:31:23 +01:00
|
|
|
ControlPointDirtyFlag = false;
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
float TFlipperEdge::flipper_angle_delta(float timeDelta)
|
2021-01-09 17:11:03 +01:00
|
|
|
{
|
2022-09-08 09:51:33 +02:00
|
|
|
if (FlipperFlag == MessageCode::TFlipperNull)
|
2023-03-04 15:31:23 +01:00
|
|
|
return 0.0f;
|
2021-01-09 17:11:03 +01:00
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
const auto deltaAngle = MoveSpeed * timeDelta;
|
|
|
|
if (std::fabs(deltaAngle) > AngleRemainder)
|
|
|
|
return AngleDst - CurrentAngle;
|
|
|
|
return deltaAngle;
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
int TFlipperEdge::SetMotion(MessageCode code)
|
2021-01-09 17:11:03 +01:00
|
|
|
{
|
|
|
|
switch (code)
|
|
|
|
{
|
2022-09-08 09:51:33 +02:00
|
|
|
case MessageCode::TFlipperExtend:
|
2023-03-04 15:31:23 +01:00
|
|
|
AngleRemainder = std::fabs(AngleMax - CurrentAngle);
|
2022-08-23 07:14:28 +02:00
|
|
|
AngleDst = AngleMax;
|
2023-03-04 15:31:23 +01:00
|
|
|
MoveSpeed = ExtendSpeed;
|
2021-01-09 17:11:03 +01:00
|
|
|
break;
|
2022-09-08 09:51:33 +02:00
|
|
|
case MessageCode::TFlipperRetract:
|
2023-03-04 15:31:23 +01:00
|
|
|
AngleRemainder = std::fabs(CurrentAngle);
|
2022-08-23 07:14:28 +02:00
|
|
|
AngleDst = 0.0f;
|
2023-03-04 15:31:23 +01:00
|
|
|
MoveSpeed = RetractSpeed;
|
2021-01-09 17:11:03 +01:00
|
|
|
break;
|
2022-09-08 09:51:33 +02:00
|
|
|
case MessageCode::Reset:
|
2023-03-04 15:31:23 +01:00
|
|
|
AngleRemainder = 0.0f;
|
2022-08-23 07:14:28 +02:00
|
|
|
AngleDst = 0.0f;
|
|
|
|
break;
|
2021-01-09 17:11:03 +01:00
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
2023-03-04 15:31:23 +01:00
|
|
|
if (AngleRemainder == 0.0f)
|
2022-09-08 09:51:33 +02:00
|
|
|
code = MessageCode::TFlipperNull;
|
2022-08-23 07:14:28 +02:00
|
|
|
|
2021-01-10 13:22:06 +01:00
|
|
|
FlipperFlag = code;
|
2022-09-08 09:51:33 +02:00
|
|
|
return static_cast<int>(code);
|
2021-01-09 17:11:03 +01:00
|
|
|
}
|