TEdgeSegment v1.

This commit is contained in:
oz 2020-11-21 18:14:40 +03:00
parent dbb69d8976
commit 0258363287
12 changed files with 340 additions and 2 deletions

View File

@ -172,9 +172,12 @@
<ClInclude Include="TBall.h" />
<ClInclude Include="TBlocker.h" />
<ClInclude Include="TBumper.h" />
<ClInclude Include="TCircle.h" />
<ClInclude Include="TCollisionComponent.h" />
<ClInclude Include="TComponentGroup.h" />
<ClInclude Include="TDemo.h" />
<ClInclude Include="TDrain.h" />
<ClInclude Include="TEdgeSegment.h" />
<ClInclude Include="TFlagSpinner.h" />
<ClInclude Include="TFlipper.h" />
<ClInclude Include="TGate.h" />
@ -185,6 +188,7 @@
<ClInclude Include="TLightBargraph.h" />
<ClInclude Include="TLightGroup.h" />
<ClInclude Include="TLightRollover.h" />
<ClInclude Include="TLine.h" />
<ClInclude Include="TOneway.h" />
<ClInclude Include="TPinballComponent.h" />
<ClInclude Include="TPinballTable.h" />
@ -228,9 +232,12 @@
<ClCompile Include="TBall.cpp" />
<ClCompile Include="TBlocker.cpp" />
<ClCompile Include="TBumper.cpp" />
<ClCompile Include="TCircle.cpp" />
<ClCompile Include="TCollisionComponent.cpp" />
<ClCompile Include="TComponentGroup.cpp" />
<ClCompile Include="TDemo.cpp" />
<ClCompile Include="TDrain.cpp" />
<ClCompile Include="TEdgeSegment.cpp" />
<ClCompile Include="TFlagSpinner.cpp" />
<ClCompile Include="TFlipper.cpp" />
<ClCompile Include="TGate.cpp" />
@ -241,6 +248,7 @@
<ClCompile Include="TLightBargraph.cpp" />
<ClCompile Include="TLightGroup.cpp" />
<ClCompile Include="TLightRollover.cpp" />
<ClCompile Include="TLine.cpp" />
<ClCompile Include="TOneway.cpp" />
<ClCompile Include="TPinballComponent.cpp" />
<ClCompile Include="TPinballTable.cpp" />

View File

@ -19,6 +19,18 @@
<Filter Include="Source Files\PinballComponents">
<UniqueIdentifier>{33813da8-81ac-449c-b19a-9756272519b9}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\TEdgeSegment">
<UniqueIdentifier>{0aa40751-a44a-400e-8809-ee817161e8e0}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\TEdgeSegment">
<UniqueIdentifier>{d70e7fca-2294-41a4-9cf8-78052bdb9aa4}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\TCollisionComponent">
<UniqueIdentifier>{01aed326-d2ec-457a-b99f-08ef32ed97fa}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\TCollisionComponent">
<UniqueIdentifier>{7ed2796a-da4b-4edd-8783-53e45d8d1c88}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
@ -168,6 +180,18 @@
<ClInclude Include="zdrv.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TEdgeSegment.h">
<Filter>Header Files\TEdgeSegment</Filter>
</ClInclude>
<ClInclude Include="TCollisionComponent.h">
<Filter>Header Files\TCollisionComponent</Filter>
</ClInclude>
<ClInclude Include="TCircle.h">
<Filter>Header Files\TEdgeSegment</Filter>
</ClInclude>
<ClInclude Include="TLine.h">
<Filter>Header Files\TEdgeSegment</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
@ -314,6 +338,18 @@
<ClCompile Include="zdrv.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TEdgeSegment.cpp">
<Filter>Source Files\TEdgeSegment</Filter>
</ClCompile>
<ClCompile Include="TCollisionComponent.cpp">
<Filter>Source Files\TCollisionComponent</Filter>
</ClCompile>
<ClCompile Include="TCircle.cpp">
<Filter>Source Files\TEdgeSegment</Filter>
</ClCompile>
<ClCompile Include="TLine.cpp">
<Filter>Source Files\TEdgeSegment</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="NatvisFile.natvis" />

View File

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

View File

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

View File

@ -0,0 +1,2 @@
#include "pch.h"
#include "TCollisionComponent.h"

View File

@ -0,0 +1,5 @@
#pragma once
class TCollisionComponent
{
};

View File

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

View File

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

View File

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

17
SpaceCadetPinball/TLine.h Normal file
View File

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

View File

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

View File

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