tr1/output: add drawing mesh spheres to debug command

This commit is contained in:
walkawayy 2025-03-06 00:33:04 -05:00
parent b43153e47b
commit 73d5c88a2e
8 changed files with 82 additions and 1 deletions

View file

@ -1,5 +1,6 @@
## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr1-4.8.3...develop) - ××××-××-××
- added support for custom levels to use `disable_floor` in the gameflow, similar to TR2's Floating Islands (#2541)
- added drawing of object mesh spheres to the `/debug` console command
- changed the Controls screen to hide the reset and unbind texts when changing a key (#2103)
- fixed several instances of the camera going out of bounds (#1034)
- fixed the bear AI fix option being applied in the Vilcabamba demo (#2559, regression from 4.8)

View file

@ -51,7 +51,7 @@ Currently supported commands:
- `/debug on`
`/debug off`
Enables or disables the debug mode. Draws all room triggers and portals.
Enables or disables the debug mode. Draws all room triggers, portals, and object mesh spheres.
- `/endlevel`
`/nextlevel`

View file

@ -100,6 +100,7 @@ CFG_INT32(g_Config, rendering.texture_filter, GFX_TF_BILINEAR)
CFG_INT32(g_Config, rendering.fbo_filter, GFX_TF_NN)
CFG_BOOL(g_Config, rendering.enable_debug_triggers, false)
CFG_BOOL(g_Config, rendering.enable_debug_portals, false)
CFG_BOOL(g_Config, rendering.enable_debug_spheres, false)
CFG_BOOL(g_Config, rendering.enable_wireframe, false)
CFG_DOUBLE(g_Config, rendering.wireframe_width, 2.5)
CFG_BOOL(g_Config, rendering.enable_perspective_filter, true)

View file

@ -193,6 +193,11 @@ void GFX_Context_SetDisplayFilter(const GFX_TEXTURE_FILTER filter)
m_Context.config.display_filter = filter;
}
bool GFX_Context_GetWireframeMode(void)
{
return m_Context.config.enable_wireframe;
}
void GFX_Context_SetWireframeMode(const bool enable)
{
m_Context.config.enable_wireframe = enable;

View file

@ -204,6 +204,7 @@ typedef struct {
GFX_TEXTURE_FILTER fbo_filter;
bool enable_debug_triggers;
bool enable_debug_portals;
bool enable_debug_spheres;
bool enable_wireframe;
double wireframe_width;
bool enable_vsync;

View file

@ -11,6 +11,7 @@ bool GFX_Context_Attach(void *window_handle, GFX_GL_BACKEND backend);
void GFX_Context_Detach(void);
void GFX_Context_SetDisplayFilter(GFX_TEXTURE_FILTER filter);
bool GFX_Context_GetWireframeMode(void);
void GFX_Context_SetWireframeMode(bool enable);
void GFX_Context_SetLineWidth(int32_t line_width);
void GFX_Context_SetVSync(bool vsync);

View file

@ -9,6 +9,7 @@
static bool *const m_AllOptions[] = {
&g_Config.rendering.enable_debug_portals,
&g_Config.rendering.enable_debug_triggers,
&g_Config.rendering.enable_debug_spheres,
nullptr,
};

View file

@ -76,6 +76,7 @@ static const char *m_ImageExtensions[] = {
".png", ".jpg", ".jpeg", ".pcx", nullptr,
};
static void M_DrawSphere(const XYZ_32 pos, const int32_t radius);
static void M_DrawFlatFace3s(const FACE3 *faces, int32_t count);
static void M_DrawFlatFace4s(const FACE4 *faces, int32_t count);
static void M_DrawTexturedFace3s(const FACE3 *faces, int32_t count);
@ -93,6 +94,66 @@ static void M_CalcRoomVertices(const ROOM_MESH *mesh);
static void M_CalcRoomVerticesWibble(const ROOM_MESH *mesh);
static void M_CalcWibbleTable(void);
static void M_DrawSphere(const XYZ_32 pos, const int32_t radius)
{
bool wireframe_state = GFX_Context_GetWireframeMode();
GFX_Context_SetWireframeMode(true);
RGBA_8888 color = { .r = 255, .g = 255, .b = 255, .a = 128 };
if (wireframe_state) {
color = (RGBA_8888) { .r = 0, .g = 0, .b = 0, .a = 128 };
}
S_Output_DisableTextureMode();
S_Output_SetBlendingMode(GFX_BLEND_MODE_NORMAL);
// More subdivisions means smoother spheres.
const int32_t subdivisions = 12;
PHD_VBUF vertices[(subdivisions + 1) * (subdivisions + 1)];
int32_t index = 0;
for (int32_t i = 0; i <= subdivisions; i++) {
const float theta = (M_PI * i) / subdivisions; // Latitude angle
const float sin_theta = sinf(theta);
const float cos_theta = cosf(theta);
for (int32_t j = 0; j <= subdivisions; j++) {
const float phi = (2 * M_PI * j) / subdivisions; // Longitude angle
const float sin_phi = sinf(phi);
const float cos_phi = cosf(phi);
// Convert spherical coordinates to 3D points.
XYZ_16 vertex_pos = {
.x = pos.x + radius * cos_phi * sin_theta,
.y = pos.y + radius * cos_theta,
.z = pos.z + radius * sin_phi * sin_theta,
};
M_CalcVertex(&vertices[index], vertex_pos);
vertices[index].g = HIGH_LIGHT;
index++;
}
}
for (int32_t i = 0; i < subdivisions; i++) {
for (int32_t j = 0; j < subdivisions; j++) {
const int32_t index_0 = i * (subdivisions + 1) + j;
const int32_t index_1 = (i + 1) * (subdivisions + 1) + j;
const int32_t index_2 = (i + 1) * (subdivisions + 1) + (j + 1);
const int32_t index_3 = i * (subdivisions + 1) + (j + 1);
S_Output_DrawFlatTriangle(
&vertices[index_0], &vertices[index_1], &vertices[index_2],
color);
S_Output_DrawFlatTriangle(
&vertices[index_0], &vertices[index_2], &vertices[index_3],
color);
}
}
S_Output_SetBlendingMode(GFX_BLEND_MODE_OFF);
GFX_Context_SetWireframeMode(wireframe_state);
}
static void M_DrawFlatFace3s(const FACE3 *const faces, const int32_t count)
{
S_Output_DisableTextureMode();
@ -600,6 +661,16 @@ void Output_DrawObjectMesh(const OBJECT_MESH *const mesh, const int32_t clip)
M_DrawObjectFace4EnvMap(mesh->flat_face4s, mesh->num_flat_face4s);
M_DrawObjectFace3EnvMap(mesh->flat_face3s, mesh->num_flat_face3s);
}
if (g_Config.rendering.enable_debug_spheres) {
M_DrawSphere(
(XYZ_32) {
.x = mesh->center.x,
.y = mesh->center.y,
.z = mesh->center.z,
},
mesh->radius);
}
}
void Output_DrawObjectMesh_I(const OBJECT_MESH *const mesh, const int32_t clip)