mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-11-14 19:25:18 -05:00
Added debug overlay v1.
It features various collision info perspective projected and overlayed on the table.
This commit is contained in:
parent
0cb75ecf7f
commit
5461483bb5
15 changed files with 388 additions and 29 deletions
|
@ -170,6 +170,8 @@ set(SOURCE_FILES
|
|||
SpaceCadetPinball/imstb_textedit.h
|
||||
SpaceCadetPinball/imstb_rectpack.h
|
||||
SpaceCadetPinball/imstb_truetype.h
|
||||
SpaceCadetPinball/DebugOverlay.cpp
|
||||
SpaceCadetPinball/DebugOverlay.h
|
||||
)
|
||||
|
||||
# On Windows, include resource file with the icon
|
||||
|
|
255
SpaceCadetPinball/DebugOverlay.cpp
Normal file
255
SpaceCadetPinball/DebugOverlay.cpp
Normal file
|
@ -0,0 +1,255 @@
|
|||
#include "pch.h"
|
||||
#include "DebugOverlay.h"
|
||||
|
||||
#include "maths.h"
|
||||
#include "proj.h"
|
||||
#include "winmain.h"
|
||||
#include "TFlipperEdge.h"
|
||||
#include "TFlipper.h"
|
||||
#include "pb.h"
|
||||
#include "TLine.h"
|
||||
#include "TCircle.h"
|
||||
#include "TPinballTable.h"
|
||||
#include "TEdgeBox.h"
|
||||
#include "TTableLayer.h"
|
||||
#include "TBall.h"
|
||||
#include "render.h"
|
||||
#include "options.h"
|
||||
|
||||
|
||||
gdrv_bitmap8* DebugOverlay::dbScreen = nullptr;
|
||||
|
||||
int SDL_RenderDrawCircle(SDL_Renderer* renderer, int x, int y, int radius)
|
||||
{
|
||||
int offsetx, offsety, d;
|
||||
int status;
|
||||
|
||||
offsetx = 0;
|
||||
offsety = radius;
|
||||
d = radius - 1;
|
||||
status = 0;
|
||||
|
||||
while (offsety >= offsetx) {
|
||||
status += SDL_RenderDrawPoint(renderer, x + offsetx, y + offsety);
|
||||
status += SDL_RenderDrawPoint(renderer, x + offsety, y + offsetx);
|
||||
status += SDL_RenderDrawPoint(renderer, x - offsetx, y + offsety);
|
||||
status += SDL_RenderDrawPoint(renderer, x - offsety, y + offsetx);
|
||||
status += SDL_RenderDrawPoint(renderer, x + offsetx, y - offsety);
|
||||
status += SDL_RenderDrawPoint(renderer, x + offsety, y - offsetx);
|
||||
status += SDL_RenderDrawPoint(renderer, x - offsetx, y - offsety);
|
||||
status += SDL_RenderDrawPoint(renderer, x - offsety, y - offsetx);
|
||||
|
||||
if (status < 0) {
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (d >= 2 * offsetx) {
|
||||
d -= 2 * offsetx + 1;
|
||||
offsetx += 1;
|
||||
}
|
||||
else if (d < 2 * (radius - offsety)) {
|
||||
d += 2 * offsety - 1;
|
||||
offsety -= 1;
|
||||
}
|
||||
else {
|
||||
d += 2 * (offsety - offsetx - 1);
|
||||
offsety -= 1;
|
||||
offsetx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void DebugOverlay::UnInit()
|
||||
{
|
||||
delete dbScreen;
|
||||
dbScreen = nullptr;
|
||||
}
|
||||
|
||||
void DebugOverlay::DrawOverlay()
|
||||
{
|
||||
if (dbScreen == nullptr)
|
||||
{
|
||||
dbScreen = new gdrv_bitmap8(render::vscreen->Width, render::vscreen->Height, false, false);
|
||||
dbScreen->CreateTexture("nearest", SDL_TEXTUREACCESS_TARGET);
|
||||
SDL_SetTextureBlendMode(dbScreen->Texture, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
// Setup overlay rendering
|
||||
Uint8 initialR, initialG, initialB, initialA;
|
||||
auto initialRenderTarget = SDL_GetRenderTarget(winmain::Renderer);
|
||||
SDL_GetRenderDrawColor(winmain::Renderer, &initialR, &initialG, &initialB, &initialA);
|
||||
SDL_SetRenderTarget(winmain::Renderer, dbScreen->Texture);
|
||||
SDL_SetRenderDrawColor(winmain::Renderer, 0, 0, 0, 0);
|
||||
SDL_RenderClear(winmain::Renderer);
|
||||
|
||||
// Draw EdgeManager box grid
|
||||
if (options::Options.DebugOverlayGrid)
|
||||
DrawBoxGrid();
|
||||
|
||||
// Draw all edges registered in TCollisionComponent.EdgeList + flippers
|
||||
if (options::Options.DebugOverlayAllEdges)
|
||||
DrawAllEdges();
|
||||
|
||||
// Draw ball collision
|
||||
if (options::Options.DebugOverlayBallPosition || options::Options.DebugOverlayBallEdges)
|
||||
DrawBallInfo();
|
||||
|
||||
// Restore render target
|
||||
SDL_SetRenderTarget(winmain::Renderer, initialRenderTarget);
|
||||
SDL_SetRenderDrawColor(winmain::Renderer,
|
||||
initialR, initialG, initialB, initialA);
|
||||
|
||||
// Copy overlay with alpha blending
|
||||
SDL_BlendMode blendMode;
|
||||
SDL_GetRenderDrawBlendMode(winmain::Renderer, &blendMode);
|
||||
SDL_SetRenderDrawBlendMode(winmain::Renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_RenderCopy(winmain::Renderer, dbScreen->Texture, nullptr, &render::DestinationRect);
|
||||
SDL_SetRenderDrawBlendMode(winmain::Renderer, blendMode);
|
||||
}
|
||||
|
||||
void DebugOverlay::DrawBoxGrid()
|
||||
{
|
||||
auto& edgeMan = *TTableLayer::edge_manager;
|
||||
|
||||
SDL_SetRenderDrawColor(winmain::Renderer, 0, 255, 0, 255);
|
||||
for (int x = 0; x <= edgeMan.MaxBoxX; x++)
|
||||
{
|
||||
vector2 boxPt{ x * edgeMan.AdvanceX + edgeMan.X , edgeMan.Y };
|
||||
auto pt1 = proj::xform_to_2d(boxPt);
|
||||
boxPt.Y = edgeMan.MaxBoxY * edgeMan.AdvanceY + edgeMan.Y;
|
||||
auto pt2 = proj::xform_to_2d(boxPt);
|
||||
|
||||
SDL_RenderDrawLine(winmain::Renderer, pt1.X, pt1.Y, pt2.X, pt2.Y);
|
||||
}
|
||||
for (int y = 0; y <= edgeMan.MaxBoxY; y++)
|
||||
{
|
||||
vector2 boxPt{ edgeMan.X, y * edgeMan.AdvanceY + edgeMan.Y };
|
||||
auto pt1 = proj::xform_to_2d(boxPt);
|
||||
boxPt.X = edgeMan.MaxBoxX * edgeMan.AdvanceX + edgeMan.X;
|
||||
auto pt2 = proj::xform_to_2d(boxPt);
|
||||
|
||||
SDL_RenderDrawLine(winmain::Renderer, pt1.X, pt1.Y, pt2.X, pt2.Y);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugOverlay::DrawAllEdges()
|
||||
{
|
||||
SDL_SetRenderDrawColor(winmain::Renderer, 0, 200, 200, 255);
|
||||
for (auto cmp : pb::MainTable->ComponentList)
|
||||
{
|
||||
auto collCmp = dynamic_cast<TCollisionComponent*>(cmp);
|
||||
if (collCmp)
|
||||
{
|
||||
for (auto edge : collCmp->EdgeList)
|
||||
{
|
||||
DrawEdge(edge);
|
||||
}
|
||||
}
|
||||
auto flip = dynamic_cast<TFlipper*>(cmp);
|
||||
if (flip)
|
||||
{
|
||||
DrawEdge(flip->FlipperEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugOverlay::DrawBallInfo()
|
||||
{
|
||||
auto& edgeMan = *TTableLayer::edge_manager;
|
||||
for (auto ball : pb::MainTable->BallList)
|
||||
{
|
||||
if (ball->ActiveFlag)
|
||||
{
|
||||
vector2 ballPosition = { ball->Position.X, ball->Position.Y };
|
||||
|
||||
if (options::Options.DebugOverlayBallEdges)
|
||||
{
|
||||
SDL_SetRenderDrawColor(winmain::Renderer, 255, 0, 0, 255);
|
||||
auto x = edgeMan.box_x(ballPosition.X), y = edgeMan.box_y(ballPosition.Y);
|
||||
auto& box = edgeMan.BoxArray[x + y * edgeMan.MaxBoxX];
|
||||
for (auto edge : box.EdgeList)
|
||||
{
|
||||
DrawEdge(edge);
|
||||
}
|
||||
}
|
||||
|
||||
if (options::Options.DebugOverlayBallPosition)
|
||||
{
|
||||
SDL_SetRenderDrawColor(winmain::Renderer, 0, 0, 255, 255);
|
||||
|
||||
auto pt1 = proj::xform_to_2d(ballPosition);
|
||||
SDL_RenderDrawCircle(winmain::Renderer, pt1.X, pt1.Y, 10);
|
||||
|
||||
auto nextPos = ballPosition;
|
||||
maths::vector_add(nextPos, maths::vector_mul(ball->Acceleration, ball->Speed / 10.0f));
|
||||
auto pt2 = proj::xform_to_2d(nextPos);
|
||||
SDL_RenderDrawLine(winmain::Renderer, pt1.X, pt1.Y, pt2.X, pt2.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugOverlay::DrawCicleType(circle_type& circle)
|
||||
{
|
||||
vector2 linePt{ circle.Center.X + sqrt(circle.RadiusSq), circle.Center.Y };
|
||||
auto pt1 = proj::xform_to_2d(circle.Center);
|
||||
auto pt2 = proj::xform_to_2d(linePt);
|
||||
auto radius = abs(pt2.X - pt1.X);
|
||||
|
||||
SDL_RenderDrawCircle(winmain::Renderer, pt1.X, pt1.Y, radius);
|
||||
}
|
||||
|
||||
void DebugOverlay::DrawLineType(line_type& line)
|
||||
{
|
||||
auto pt1 = proj::xform_to_2d(line.Origin);
|
||||
auto pt2 = proj::xform_to_2d(line.End);
|
||||
|
||||
SDL_RenderDrawLine(winmain::Renderer, pt1.X, pt1.Y, pt2.X, pt2.Y);
|
||||
}
|
||||
|
||||
void DebugOverlay::DrawEdge(TEdgeSegment* edge)
|
||||
{
|
||||
if (options::Options.DebugOverlayCollisionMask)
|
||||
{
|
||||
TBall* refBall = nullptr;
|
||||
for (auto ball : pb::MainTable->BallList)
|
||||
{
|
||||
if (ball->ActiveFlag)
|
||||
{
|
||||
refBall = ball;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (refBall != nullptr && (refBall->FieldFlag & edge->CollisionGroup) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
auto line = dynamic_cast<TLine*>(edge);
|
||||
if (line)
|
||||
{
|
||||
DrawLineType(line->Line);
|
||||
return;
|
||||
}
|
||||
|
||||
auto circle = dynamic_cast<TCircle*>(edge);
|
||||
if (circle)
|
||||
{
|
||||
DrawCicleType(circle->Circle);
|
||||
return;
|
||||
}
|
||||
|
||||
auto flip = dynamic_cast<TFlipperEdge*>(edge);
|
||||
if (flip)
|
||||
{
|
||||
flip->set_control_points(pb::time_now);
|
||||
flip->build_edges_in_motion();
|
||||
|
||||
DrawLineType(TFlipperEdge::lineA);
|
||||
DrawLineType(TFlipperEdge::lineB);
|
||||
DrawCicleType(TFlipperEdge::circlebase);
|
||||
DrawCicleType(TFlipperEdge::circleT1);
|
||||
}
|
||||
}
|
22
SpaceCadetPinball/DebugOverlay.h
Normal file
22
SpaceCadetPinball/DebugOverlay.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
struct gdrv_bitmap8;
|
||||
struct circle_type;
|
||||
struct line_type;
|
||||
class TEdgeSegment;
|
||||
|
||||
class DebugOverlay
|
||||
{
|
||||
public:
|
||||
static void UnInit();
|
||||
static void DrawOverlay();
|
||||
private:
|
||||
static gdrv_bitmap8* dbScreen;
|
||||
|
||||
static void DrawCicleType(circle_type& circle);
|
||||
static void DrawLineType(line_type& line);
|
||||
static void DrawEdge(TEdgeSegment* edge);
|
||||
static void DrawBoxGrid();
|
||||
static void DrawAllEdges();
|
||||
static void DrawBallInfo();
|
||||
};
|
|
@ -47,7 +47,7 @@ void GroupData::AddEntry(EntryData* entry)
|
|||
if (srcBmp->BitmapType == BitmapTypes::Spliced)
|
||||
{
|
||||
// Get rid of spliced bitmap early on, to simplify render pipeline
|
||||
auto bmp = new gdrv_bitmap8(srcBmp->Width, srcBmp->Height, srcBmp->Width);
|
||||
auto bmp = new gdrv_bitmap8(srcBmp->Width, srcBmp->Height, true);
|
||||
auto zMap = new zmap_header_type(srcBmp->Width, srcBmp->Height, srcBmp->Width);
|
||||
SplitSplicedBitmap(*srcBmp, *bmp, *zMap);
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
|
|||
if (ListBitmap)
|
||||
ListBitmap->push_back(visual.Bitmap);
|
||||
auto visVec = reinterpret_cast<vector3*>(loader::query_float_attribute(groupIndex, index, 501));
|
||||
auto zDepth = proj::z_distance(visVec);
|
||||
auto zDepth = proj::z_distance(*visVec);
|
||||
VisualZArray[index] = zDepth;
|
||||
}
|
||||
RenderSprite = render::create_sprite(VisualTypes::Ball, nullptr, nullptr, 0, 0, nullptr);
|
||||
|
@ -60,8 +60,6 @@ TBall::TBall(TPinballTable* table) : TPinballComponent(table, -1, false)
|
|||
|
||||
void TBall::Repaint()
|
||||
{
|
||||
int pos2D[2];
|
||||
|
||||
if (CollisionFlag)
|
||||
{
|
||||
Position.Z =
|
||||
|
@ -70,8 +68,8 @@ void TBall::Repaint()
|
|||
Offset + CollisionOffset.Z;
|
||||
}
|
||||
|
||||
proj::xform_to_2d(&Position, pos2D);
|
||||
auto zDepth = proj::z_distance(&Position);
|
||||
auto pos2D = proj::xform_to_2d(Position);
|
||||
auto zDepth = proj::z_distance(Position);
|
||||
|
||||
auto zArrPtr = VisualZArray;
|
||||
auto index = 0u;
|
||||
|
@ -85,8 +83,8 @@ void TBall::Repaint()
|
|||
RenderSprite,
|
||||
bmp,
|
||||
zDepth,
|
||||
pos2D[0] - bmp->Width / 2,
|
||||
pos2D[1] - bmp->Height / 2);
|
||||
pos2D.X - bmp->Width / 2,
|
||||
pos2D.Y - bmp->Height / 2);
|
||||
}
|
||||
|
||||
void TBall::not_again(TEdgeSegment* edge)
|
||||
|
|
|
@ -9,7 +9,15 @@
|
|||
|
||||
ColorRgba gdrv::current_palette[256]{};
|
||||
|
||||
gdrv_bitmap8::gdrv_bitmap8(int width, int height, bool indexed)
|
||||
gdrv_bitmap8::gdrv_bitmap8(int width, int height) : gdrv_bitmap8(width, height, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
gdrv_bitmap8::gdrv_bitmap8(int width, int height, bool indexed) : gdrv_bitmap8(width, height, indexed, true)
|
||||
{
|
||||
}
|
||||
|
||||
gdrv_bitmap8::gdrv_bitmap8(int width, int height, bool indexed, bool bmpBuff)
|
||||
{
|
||||
assertm(width >= 0 && height >= 0, "Negative bitmap8 dimensions");
|
||||
|
||||
|
@ -20,12 +28,14 @@ gdrv_bitmap8::gdrv_bitmap8(int width, int height, bool indexed)
|
|||
BitmapType = BitmapTypes::DibBitmap;
|
||||
Texture = nullptr;
|
||||
IndexedBmpPtr = nullptr;
|
||||
BmpBufPtr1 = nullptr;
|
||||
XPosition = 0;
|
||||
YPosition = 0;
|
||||
Resolution = 0;
|
||||
|
||||
if (indexed)
|
||||
IndexedBmpPtr = new char[Height * IndexedStride];
|
||||
if (bmpBuff)
|
||||
BmpBufPtr1 = new ColorRgba[Height * Stride];
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,9 @@ static_assert(sizeof(ColorRgba) == 4, "Wrong size of RGBA color");
|
|||
|
||||
struct gdrv_bitmap8
|
||||
{
|
||||
gdrv_bitmap8(int width, int height);
|
||||
gdrv_bitmap8(int width, int height, bool indexed);
|
||||
gdrv_bitmap8(int width, int height, bool indexed, bool bmpBuff);
|
||||
gdrv_bitmap8(const struct dat8BitBmpHeader& header);
|
||||
~gdrv_bitmap8();
|
||||
void ScaleIndexed(float scaleX, float scaleY);
|
||||
|
|
|
@ -132,6 +132,7 @@ float maths::normalize_2d(vector2& vec)
|
|||
void maths::line_init(line_type& line, float x0, float y0, float x1, float y1)
|
||||
{
|
||||
line.Origin = { x0, y0 };
|
||||
line.End = { x1, y1 };
|
||||
line.Direction.X = x1 - x0;
|
||||
line.Direction.Y = y1 - y0;
|
||||
normalize_2d(line.Direction);
|
||||
|
@ -219,6 +220,11 @@ vector2 maths::vector_sub(const vector2& vec1, const vector2& vec2)
|
|||
return { vec1.X - vec2.X, vec1.Y - vec2.Y };
|
||||
}
|
||||
|
||||
vector2 maths::vector_mul(const vector2& vec1, float val)
|
||||
{
|
||||
return { vec1.X * val, vec1.Y * val };
|
||||
}
|
||||
|
||||
float maths::basic_collision(TBall* ball, vector2* nextPosition, vector2* direction, float elasticity, float smoothness,
|
||||
float threshold, float boost)
|
||||
{
|
||||
|
|
|
@ -19,9 +19,18 @@ struct vector2
|
|||
|
||||
struct vector3 :vector2
|
||||
{
|
||||
vector3() = default;
|
||||
vector3(float x, float y) : vector3{ x, y, 0 } {}
|
||||
vector3(float x, float y, float z) : vector2{ x, y }, Z(z) {}
|
||||
float Z;
|
||||
};
|
||||
|
||||
struct vector2i
|
||||
{
|
||||
int X;
|
||||
int Y;
|
||||
};
|
||||
|
||||
struct rectangle_type
|
||||
{
|
||||
int XPosition;
|
||||
|
@ -52,6 +61,7 @@ struct line_type
|
|||
vector2 PerpendicularC;
|
||||
vector2 Direction;
|
||||
vector2 Origin;
|
||||
vector2 End;
|
||||
float MinCoord;
|
||||
float MaxCoord;
|
||||
vector2 RayIntersect;
|
||||
|
@ -98,6 +108,7 @@ public:
|
|||
static float magnitude(const vector3& vec);
|
||||
static void vector_add(vector2& vec1Dst, const vector2& vec2);
|
||||
static vector2 vector_sub(const vector2& vec1, const vector2& vec2);
|
||||
static vector2 vector_mul(const vector2& vec1, float val);
|
||||
static float basic_collision(TBall* ball, vector2* nextPosition, vector2* direction, float elasticity,
|
||||
float smoothness,
|
||||
float threshold, float boost);
|
||||
|
|
|
@ -104,6 +104,12 @@ void options::InitPrimary()
|
|||
Options.IntegerScaling = get_int("Integer Scaling", false);
|
||||
Options.SoundVolume = Clamp(get_int("Sound Volume", DefVolume), MinVolume, MaxVolume);
|
||||
Options.MusicVolume = Clamp(get_int("Music Volume", DefVolume), MinVolume, MaxVolume);
|
||||
Options.DebugOverlay = get_int("Debug Overlay", false);
|
||||
Options.DebugOverlayGrid = get_int("Debug Overlay Grid", true);
|
||||
Options.DebugOverlayAllEdges = get_int("Debug Overlay All Edges", true);
|
||||
Options.DebugOverlayBallPosition = get_int("Debug Overlay Ball Position", true);
|
||||
Options.DebugOverlayBallEdges = get_int("Debug Overlay Ball Edges", true);
|
||||
Options.DebugOverlayCollisionMask = get_int("Debug Overlay Collision Mask", true);
|
||||
}
|
||||
|
||||
void options::InitSecondary()
|
||||
|
@ -143,6 +149,12 @@ void options::uninit()
|
|||
set_int("Integer Scaling", Options.IntegerScaling);
|
||||
set_int("Sound Volume", Options.SoundVolume);
|
||||
set_int("Music Volume", Options.MusicVolume);
|
||||
set_int("Debug Overlay", Options.DebugOverlay);
|
||||
set_int("Debug Overlay Grid", Options.DebugOverlayGrid);
|
||||
set_int("Debug Overlay All Edges", Options.DebugOverlayAllEdges);
|
||||
set_int("Debug Overlay Ball Position", Options.DebugOverlayBallPosition);
|
||||
set_int("Debug Overlay Ball Edges", Options.DebugOverlayBallEdges);
|
||||
set_int("Debug Overlay Collision Mask", Options.DebugOverlayCollisionMask);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -80,6 +80,12 @@ struct optionsStruct
|
|||
bool IntegerScaling;
|
||||
int SoundVolume;
|
||||
int MusicVolume;
|
||||
bool DebugOverlay;
|
||||
bool DebugOverlayGrid;
|
||||
bool DebugOverlayAllEdges;
|
||||
bool DebugOverlayBallPosition;
|
||||
bool DebugOverlayBallEdges;
|
||||
bool DebugOverlayCollisionMask;
|
||||
};
|
||||
|
||||
struct ControlRef
|
||||
|
|
|
@ -26,33 +26,42 @@ void proj::init(float* mat4x3, float d, float centerX, float centerY)
|
|||
centery = centerY;
|
||||
}
|
||||
|
||||
void proj::matrix_vector_multiply(mat4_row_major* mat, vector3* vec, vector3* dstVec)
|
||||
vector3 proj::matrix_vector_multiply(const mat4_row_major& mat, const vector3& vec)
|
||||
{
|
||||
const float x = vec->X, y = vec->Y, z = vec->Z;
|
||||
dstVec->X = z * mat->Row0.Z + y * mat->Row0.Y + x * mat->Row0.X + mat->Row0.W;
|
||||
dstVec->Y = z * mat->Row1.Z + y * mat->Row1.Y + x * mat->Row1.X + mat->Row1.W;
|
||||
dstVec->Z = z * mat->Row2.Z + y * mat->Row2.Y + x * mat->Row2.X + mat->Row2.W;
|
||||
vector3 dstVec;
|
||||
const float x = vec.X, y = vec.Y, z = vec.Z;
|
||||
dstVec.X = z * mat.Row0.Z + y * mat.Row0.Y + x * mat.Row0.X + mat.Row0.W;
|
||||
dstVec.Y = z * mat.Row1.Z + y * mat.Row1.Y + x * mat.Row1.X + mat.Row1.W;
|
||||
dstVec.Z = z * mat.Row2.Z + y * mat.Row2.Y + x * mat.Row2.X + mat.Row2.W;
|
||||
return dstVec;
|
||||
}
|
||||
|
||||
float proj::z_distance(vector3* vec)
|
||||
float proj::z_distance(const vector3& vec)
|
||||
{
|
||||
vector3 dstVec{};
|
||||
matrix_vector_multiply(&matrix, vec, &dstVec);
|
||||
return maths::magnitude(dstVec);
|
||||
auto projVec = matrix_vector_multiply(matrix, vec);
|
||||
return maths::magnitude(projVec);
|
||||
}
|
||||
|
||||
void proj::xform_to_2d(vector3* vec, int* dst)
|
||||
vector2i proj::xform_to_2d(const vector2& vec)
|
||||
{
|
||||
vector3 vec3{ vec.X, vec.Y, 0 };
|
||||
return xform_to_2d(vec3);
|
||||
}
|
||||
|
||||
vector2i proj::xform_to_2d(const vector3& vec)
|
||||
{
|
||||
float projCoef;
|
||||
vector3 dstVec2{};
|
||||
|
||||
matrix_vector_multiply(&matrix, vec, &dstVec2);
|
||||
if (dstVec2.Z == 0.0f)
|
||||
auto projVec = matrix_vector_multiply(matrix, vec);
|
||||
if (projVec.Z == 0.0f)
|
||||
projCoef = 999999.88f;
|
||||
else
|
||||
projCoef = d_ / dstVec2.Z;
|
||||
dst[0] = static_cast<int>(dstVec2.X * projCoef + centerx);
|
||||
dst[1] = static_cast<int>(dstVec2.Y * projCoef + centery);
|
||||
projCoef = d_ / projVec.Z;
|
||||
return
|
||||
{
|
||||
static_cast<int>(projVec.X * projCoef + centerx),
|
||||
static_cast<int>(projVec.Y * projCoef + centery)
|
||||
};
|
||||
}
|
||||
|
||||
void proj::recenter(float centerX, float centerY)
|
||||
|
|
|
@ -22,9 +22,10 @@ class proj
|
|||
{
|
||||
public:
|
||||
static void init(float* mat4x3, float d, float centerX, float centerY);
|
||||
static void matrix_vector_multiply(mat4_row_major* mat, vector3* vec, vector3* dstVec);
|
||||
static float z_distance(vector3* vec);
|
||||
static void xform_to_2d(vector3* vec, int* dst);
|
||||
static vector3 matrix_vector_multiply(const mat4_row_major& mat, const vector3& vec);
|
||||
static float z_distance(const vector3& vec);
|
||||
static vector2i xform_to_2d(const vector3& vec);
|
||||
static vector2i xform_to_2d(const vector2& vec);
|
||||
static void recenter(float centerX, float centerY);
|
||||
private:
|
||||
static mat4_row_major matrix;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "score.h"
|
||||
#include "TPinballTable.h"
|
||||
#include "winmain.h"
|
||||
#include "DebugOverlay.h"
|
||||
|
||||
std::vector<render_sprite_type_struct*> render::dirty_list, render::sprite_list, render::ball_list;
|
||||
zmap_header_type* render::background_zmap;
|
||||
|
@ -57,6 +58,7 @@ void render::uninit()
|
|||
ball_list.clear();
|
||||
dirty_list.clear();
|
||||
sprite_list.clear();
|
||||
DebugOverlay::UnInit();
|
||||
}
|
||||
|
||||
void render::recreate_screen_texture()
|
||||
|
@ -585,4 +587,9 @@ void render::PresentVScreen()
|
|||
SDL_RenderCopy(winmain::Renderer, vscreen->Texture, &srcSidebarRect, &dstSidebarRect);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (options::Options.DebugOverlay)
|
||||
{
|
||||
DebugOverlay::DrawOverlay();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -577,6 +577,24 @@ void winmain::RenderUi()
|
|||
{
|
||||
DispGRhistory ^= true;
|
||||
}
|
||||
if (ImGui::MenuItem("Debug Overlay", nullptr, Options.DebugOverlay))
|
||||
{
|
||||
Options.DebugOverlay ^= true;
|
||||
}
|
||||
if (Options.DebugOverlay && ImGui::BeginMenu("Overlay Options"))
|
||||
{
|
||||
if (ImGui::MenuItem("Box Grid", nullptr, Options.DebugOverlayGrid))
|
||||
Options.DebugOverlayGrid ^= true;
|
||||
if (ImGui::MenuItem("All Edges", nullptr, Options.DebugOverlayAllEdges))
|
||||
Options.DebugOverlayAllEdges ^= true;
|
||||
if (ImGui::MenuItem("Ball Position", nullptr, Options.DebugOverlayBallPosition))
|
||||
Options.DebugOverlayBallPosition ^= true;
|
||||
if (ImGui::MenuItem("Ball Box Edges", nullptr, Options.DebugOverlayBallEdges))
|
||||
Options.DebugOverlayBallEdges ^= true;
|
||||
if (ImGui::MenuItem("Apply Collision Mask", nullptr, Options.DebugOverlayCollisionMask))
|
||||
Options.DebugOverlayCollisionMask ^= true;
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Cheats"))
|
||||
{
|
||||
if (ImGui::MenuItem("hidden test", nullptr, pb::cheat_mode))
|
||||
|
|
Loading…
Reference in a new issue