From 02583632871dbe013ea0c47fb4434b49bceabf3d Mon Sep 17 00:00:00 2001 From: oz Date: Sat, 21 Nov 2020 18:14:40 +0300 Subject: [PATCH] TEdgeSegment v1. --- SpaceCadetPinball/SpaceCadetPinball.vcxproj | 8 ++ .../SpaceCadetPinball.vcxproj.filters | 36 +++++ SpaceCadetPinball/TCircle.cpp | 16 +++ SpaceCadetPinball/TCircle.h | 12 ++ SpaceCadetPinball/TCollisionComponent.cpp | 2 + SpaceCadetPinball/TCollisionComponent.h | 5 + SpaceCadetPinball/TEdgeSegment.cpp | 10 ++ SpaceCadetPinball/TEdgeSegment.h | 23 +++ SpaceCadetPinball/TLine.cpp | 38 +++++ SpaceCadetPinball/TLine.h | 17 +++ SpaceCadetPinball/maths.cpp | 133 +++++++++++++++++- SpaceCadetPinball/maths.h | 42 ++++++ 12 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 SpaceCadetPinball/TCircle.cpp create mode 100644 SpaceCadetPinball/TCircle.h create mode 100644 SpaceCadetPinball/TCollisionComponent.cpp create mode 100644 SpaceCadetPinball/TCollisionComponent.h create mode 100644 SpaceCadetPinball/TEdgeSegment.cpp create mode 100644 SpaceCadetPinball/TEdgeSegment.h create mode 100644 SpaceCadetPinball/TLine.cpp create mode 100644 SpaceCadetPinball/TLine.h diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj b/SpaceCadetPinball/SpaceCadetPinball.vcxproj index 5bcbfb4..ccbfe7e 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj +++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj @@ -172,9 +172,12 @@ + + + @@ -185,6 +188,7 @@ + @@ -228,9 +232,12 @@ + + + @@ -241,6 +248,7 @@ + diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters index 514302a..08f0e7d 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters +++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters @@ -19,6 +19,18 @@ {33813da8-81ac-449c-b19a-9756272519b9} + + {0aa40751-a44a-400e-8809-ee817161e8e0} + + + {d70e7fca-2294-41a4-9cf8-78052bdb9aa4} + + + {01aed326-d2ec-457a-b99f-08ef32ed97fa} + + + {7ed2796a-da4b-4edd-8783-53e45d8d1c88} + @@ -168,6 +180,18 @@ Header Files + + Header Files\TEdgeSegment + + + Header Files\TCollisionComponent + + + Header Files\TEdgeSegment + + + Header Files\TEdgeSegment + @@ -314,6 +338,18 @@ Source Files + + Source Files\TEdgeSegment + + + Source Files\TCollisionComponent + + + Source Files\TEdgeSegment + + + Source Files\TEdgeSegment + diff --git a/SpaceCadetPinball/TCircle.cpp b/SpaceCadetPinball/TCircle.cpp new file mode 100644 index 0000000..2ae524b --- /dev/null +++ b/SpaceCadetPinball/TCircle.cpp @@ -0,0 +1,16 @@ +#include "pch.h" +#include "TCircle.h" + +TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visualFlag, float* floatArr, + float radius): TEdgeSegment(collComp, someFlagPtr, visualFlag) +{ + Circle.RadiusSq = radius * radius; + Circle.X = *floatArr; + Circle.Y = floatArr[1]; + Circle.Unknown2 = floatArr[2]; +} + +double TCircle::FindCollisionDistance(ray_type* ray) +{ + return maths::ray_intersect_circle(ray, &Circle); +} \ No newline at end of file diff --git a/SpaceCadetPinball/TCircle.h b/SpaceCadetPinball/TCircle.h new file mode 100644 index 0000000..f675dc3 --- /dev/null +++ b/SpaceCadetPinball/TCircle.h @@ -0,0 +1,12 @@ +#pragma once +#include "maths.h" +#include "TEdgeSegment.h" + +class TCircle : + public TEdgeSegment +{ + circle_type Circle; + + TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned int visualFlag, float* floatArr, float radius); + double FindCollisionDistance(ray_type* ray) override; +}; diff --git a/SpaceCadetPinball/TCollisionComponent.cpp b/SpaceCadetPinball/TCollisionComponent.cpp new file mode 100644 index 0000000..dae0a13 --- /dev/null +++ b/SpaceCadetPinball/TCollisionComponent.cpp @@ -0,0 +1,2 @@ +#include "pch.h" +#include "TCollisionComponent.h" diff --git a/SpaceCadetPinball/TCollisionComponent.h b/SpaceCadetPinball/TCollisionComponent.h new file mode 100644 index 0000000..7175d95 --- /dev/null +++ b/SpaceCadetPinball/TCollisionComponent.h @@ -0,0 +1,5 @@ +#pragma once +class TCollisionComponent +{ +}; + diff --git a/SpaceCadetPinball/TEdgeSegment.cpp b/SpaceCadetPinball/TEdgeSegment.cpp new file mode 100644 index 0000000..87234c2 --- /dev/null +++ b/SpaceCadetPinball/TEdgeSegment.cpp @@ -0,0 +1,10 @@ +#include "pch.h" +#include "TEdgeSegment.h" + +TEdgeSegment::TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned visualFlag) +{ + this->CollisionComponent = collComp; + this->PinbCompFlag2Ptr = someFlag; + this->VisualFlag = visualFlag; + this->Unknown3_0 = 0; +} diff --git a/SpaceCadetPinball/TEdgeSegment.h b/SpaceCadetPinball/TEdgeSegment.h new file mode 100644 index 0000000..369b5f3 --- /dev/null +++ b/SpaceCadetPinball/TEdgeSegment.h @@ -0,0 +1,23 @@ +#pragma once +#include "TCollisionComponent.h" +#include "maths.h" +#include "TBall.h" + +class TEdgeSegment +{ +public: + TCollisionComponent* CollisionComponent; + char* PinbCompFlag2Ptr; + char Unknown3_0; + char Unknown3_1; + char Unknown3_2; + char Unknown3_3; + char Unknown4; + int VisualFlag; + + TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag); + //virtual ~TEdgeSegment() = 0; + virtual void place_in_grid() = 0; + virtual double FindCollisionDistance(ray_type* ray) = 0; + virtual void EdgeCollision(TBall* ball, float coef) = 0; +}; diff --git a/SpaceCadetPinball/TLine.cpp b/SpaceCadetPinball/TLine.cpp new file mode 100644 index 0000000..de2f452 --- /dev/null +++ b/SpaceCadetPinball/TLine.cpp @@ -0,0 +1,38 @@ +#include "pch.h" +#include "TLine.h" + + +TLine::TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, float x0, float y0, float x1, + float y1): TEdgeSegment(collCmp, flagPtr, visualFlag) +{ + Start.X = x0; + Start.Y = y0; + End.X = x1; + End.Y = y1; + maths::line_init(&Line, x0, y0, x1, y1); +} + +TLine::TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, struct vector_type* start, + struct vector_type* end) : TEdgeSegment(collCmp, flagPtr, visualFlag) +{ + Start = *start; + End = *end; + maths::line_init(&Line, Start.X, Start.Y, End.X, End.Y); +} + +void TLine::Offset(float offset) +{ + float offX = offset * Line.PerpendicularL.X; + float offY = offset * Line.PerpendicularL.Y; + + Start.X += offX; + Start.Y += offY; + End.X += offX; + End.Y += offY; + maths::line_init(&Line, Start.X, Start.Y, End.X, End.Y); +} + +double TLine::FindCollisionDistance(ray_type* ray) +{ + return maths::ray_intersect_line(ray, &Line); +} \ No newline at end of file diff --git a/SpaceCadetPinball/TLine.h b/SpaceCadetPinball/TLine.h new file mode 100644 index 0000000..ebfc0cf --- /dev/null +++ b/SpaceCadetPinball/TLine.h @@ -0,0 +1,17 @@ +#pragma once +#include "maths.h" +#include "TEdgeSegment.h" + +class TLine : + public TEdgeSegment +{ +public: + line_type Line; + vector_type Start; + vector_type End; + TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, float x0, float y0, float x1, float y1); + TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, struct vector_type* start, + struct vector_type* end); + void Offset(float offset); + double FindCollisionDistance(ray_type* ray) override; +}; diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index 8541f1b..47e5e57 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -83,7 +83,6 @@ int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectang { int v3; // esi int v4; // edi - int v5; // esi int v6; // esi int v7; // edi @@ -100,7 +99,7 @@ int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectang v4 = rect2->XPosition; } dstRect->Width = v3 + v4 + 1; - v5 = rect1->YPosition; + int v5 = rect1->YPosition; if (v5 >= rect2->YPosition) { dstRect->YPosition = rect2->YPosition; @@ -116,3 +115,133 @@ int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectang dstRect->Height = v6 + v7 + 1; return dstRect->Width <= rect2->Width + rect1->Width && dstRect->Height <= rect2->Height + rect1->Height; } + +float maths::ray_intersect_circle(ray_type* ray, circle_type* circle) +{ + // O - ray origin + // D - ray direction + // C - circle center + // R - circle radius + // L, C - O, vector between O and C + float Lx = circle->X - ray->Origin.X; + float Ly = circle->Y - ray->Origin.Y; + + // Tca, L dot D, projection of L on D + float Tca = Ly * ray->Direction.Y + Lx * ray->Direction.X; + if (Tca < 0.0) // No intersection if Tca is negative + return 1000000000.0f; + + // L dot L, distance from ray origin to circle center + float LMagSq = Ly * Ly + Lx * Lx; + + // If ray origin is inside of the circle + // T0 = Tca - Sqrt(rad^2 - d^2). d = sqrt(L dot L - Tca dot Tca) + if (LMagSq < circle->RadiusSq) + return Tca - sqrt(circle->RadiusSq - LMagSq + Tca * Tca); + + // Thc^2 = rad^2 - d = rad^2 - L dot L + Tca dot Tca + float ThcSq = circle->RadiusSq - LMagSq + Tca * Tca; + if (ThcSq < 0.0) // No intersection if Thc is negative + return 1000000000.0f; + + // T0 = Tca - Thc, distance from origin to first intersection + float T0 = Tca - sqrt(ThcSq); + if (T0 < 0.0 || T0 > ray->MaxDistance) + return 1000000000.0f; + return T0; +} + + +float maths::normalize_2d(vector_type* vec) +{ + float mag = sqrt(vec->X * vec->X + vec->Y * vec->Y); + if (0.0 != mag) + { + vec->X = 1.0f / mag * vec->X; + vec->Y = 1.0f / mag * vec->Y; + } + return mag; +} + + +void maths::line_init(line_type* line, float x0, float y0, float x1, float y1) +{ + float v9; // st7 + bool lineDirection; // pf + float v11; // eax + + line->Direction.X = x1 - x0; + line->Direction.Y = y1 - y0; + normalize_2d(&line->Direction); + line->PerpendicularL.X = line->Direction.Y; + line->PerpendicularL.Y = -line->Direction.X; + line->PreComp1 = -(line->Direction.Y * x0) + (line->Direction.X * y0); + if (line->Direction.X >= 0.000000001 || line->Direction.X <= -0.000000001) + { + v9 = x1; + lineDirection = x0 >= x1; + v11 = x0; + } + else + { + line->Direction.X = 0.0; + v9 = y1; + lineDirection = y0 >= y1; + v11 = y0; + } + if (lineDirection) + { + line->Origin.X = v9; + line->Origin.Y = v11; + } + else + { + line->Origin.Y = v9; + line->Origin.X = v11; + } +} + +float maths::ray_intersect_line(ray_type* ray, line_type* line) +{ + // Similar to https://rootllama.wordpress.com/2014/06/20/ray-line-segment-intersection-test-in-2d/ + float perpDot; // st7 + float result; // st7 + float v4; // st6 + bool v5; // c0 + bool v6; // c3 + float v7; // st6 + + perpDot = line->PerpendicularL.Y * ray->Direction.Y + ray->Direction.X * line->PerpendicularL.X; + if (perpDot < 0.0) + { + result = -((ray->Origin.X * line->PerpendicularL.X + ray->Origin.Y * line->PerpendicularL.Y + line->PreComp1) + / perpDot); + if (result >= -ray->Unknown7 && result <= ray->MaxDistance) + { + line->Unknown9 = result * ray->Direction.X + ray->Origin.X; + v4 = result * ray->Direction.Y + ray->Origin.Y; + line->Unknown10 = v4; + if (0.0 == line->Direction.X) + { + if (v4 >= line->Origin.X) + { + v5 = v4 < line->Origin.Y; + v6 = v4 == line->Origin.Y; + if (v5 || v6) + return result; + return 1000000000.0; + } + } + else if (line->Origin.X <= line->Unknown9) + { + v7 = line->Unknown9; + v5 = v7 < line->Origin.Y; + v6 = v7 == line->Origin.Y; + if (v5 || v6) + return result; + return 1000000000.0; + } + } + } + return 1000000000.0; +} diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index c3433e9..bdd9b45 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -1,5 +1,11 @@ #pragma once +struct vector_type +{ + float X; + float Y; +}; + struct __declspec(align(4)) rectangle_type { @@ -9,10 +15,46 @@ struct __declspec(align(4)) rectangle_type int Height; }; +struct circle_type +{ + float X; + float Y; + float Unknown2; + float RadiusSq; +}; + +struct __declspec(align(4)) ray_type +{ + vector_type Origin; + float Unknown2; + vector_type Direction; + float Unknown5; + float MaxDistance; + float Unknown7; +}; + +struct __declspec(align(4)) line_type +{ + vector_type PerpendicularL; + float Unknown2; + vector_type Direction; + float Unknown5; + float PreComp1; + vector_type Origin; + float Unknown9; + float Unknown10; + float Unknown11; +}; + + class maths { public: static void enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect); static int rectangle_clip(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect); static int overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect); + static float ray_intersect_circle(ray_type* ray, circle_type* circle); + static float normalize_2d(vector_type* 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); };