You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
* crowd pleaser * Fix debug boxes * fix comments * renamed temp graphics head to be consistent --------- Co-authored-by: Fazana <52551480+FazanaJ@users.noreply.github.com>
504 lines
17 KiB
C
504 lines
17 KiB
C
#include <ultra64.h>
|
|
|
|
/**
|
|
* @file debug_box.c
|
|
* Draws 3D boxes for debugging purposes
|
|
* Originally written by Synray, modified by Fazana.
|
|
*
|
|
* How to use:
|
|
*
|
|
* Just call debug_box() whenever you want to draw one!
|
|
*
|
|
* debug_box by default takes two arguments: a center and bounds vec3f.
|
|
* This will draw a box starting from the point (center - bounds) to (center + bounds).
|
|
*
|
|
* Use debug_box_rot to draw a box rotated in the xz-plane.
|
|
*
|
|
* If you want to draw a box by specifying min and max points, use debug_box_pos() instead.
|
|
*/
|
|
|
|
#include "sm64.h"
|
|
#include "game/game_init.h"
|
|
#include "game/geo_misc.h"
|
|
#include "engine/math_util.h"
|
|
#include "engine/colors.h"
|
|
#include "area.h"
|
|
#include "level_update.h"
|
|
#include "print.h"
|
|
#include "engine/surface_collision.h"
|
|
#include "engine/surface_load.h"
|
|
#include "object_list_processor.h"
|
|
#include "behavior_data.h"
|
|
|
|
#include "debug_box.h"
|
|
|
|
#ifdef VISUAL_DEBUG
|
|
|
|
Vtx debug_box_mesh[32] = {
|
|
{{{ 0, 0, -100}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 50, 100, -87}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 50, 0, -87}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 0, 100, -100}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -50, 0, -87}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -50, 100, -87}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -87, 0, -50}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -87, 100, -50}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -100, 0, 0}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -100, 100, 0}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -87, 0, 50}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -87, 100, 50}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -50, 0, 87}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -50, 100, 87}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 0, 0, 100}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 0, 100, 100}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 50, 0, 87}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 50, 100, 87}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 87, 0, 50}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 87, 100, 50}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 100, 0, 0}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 100, 100, 0}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 87, 0, -50}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ 87, 100, -50}, 0, ST_B( 0, 32), {0x00, 0x00, 0x00, 0xFF}}},
|
|
{{{ -100, 0, 100}, 0, ST_B( 0, 32), {0xFF, 0xFF, 0xFF, 0xFF}}},
|
|
{{{ -100, 100, 100}, 0, ST_B( 0, 32), {0xFF, 0xFF, 0xFF, 0xFF}}},
|
|
{{{ -100, 100, -100}, 0, ST_B( 0, 32), {0xFF, 0xFF, 0xFF, 0xFF}}},
|
|
{{{ 100, 0, 100}, 0, ST_B( 0, 32), {0xFF, 0xFF, 0xFF, 0xFF}}},
|
|
{{{ -100, 0, -100}, 0, ST_B( 0, 32), {0xFF, 0xFF, 0xFF, 0xFF}}},
|
|
{{{ 100, 100, -100}, 0, ST_B( 0, 32), {0xFF, 0xFF, 0xFF, 0xFF}}},
|
|
{{{ 100, 100, 100}, 0, ST_B( 0, 32), {0xFF, 0xFF, 0xFF, 0xFF}}},
|
|
{{{ 100, 0, -100}, 0, ST_B( 0, 32), {0xFF, 0xFF, 0xFF, 0xFF}}},
|
|
};
|
|
|
|
Gfx dl_debug_box_verts[] = {
|
|
gsSPVertex(debug_box_mesh, 32, 0),
|
|
gsSP2Triangles(24, 25, 26, 0, 27, 25, 24, 0),
|
|
gsSP2Triangles(28, 27, 24, 0, 24, 26, 28, 0),
|
|
gsSP2Triangles(28, 26, 29, 0, 29, 26, 25, 0),
|
|
gsSP2Triangles(29, 25, 30, 0, 27, 30, 25, 0),
|
|
gsSP2Triangles(31, 30, 27, 0, 28, 31, 27, 0),
|
|
gsSP2Triangles(28, 29, 31, 0, 31, 29, 30, 0),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
Gfx dl_debug_cylinder_verts[] = {
|
|
gsSPVertex(debug_box_mesh, 24, 0),
|
|
gsSP2Triangles( 0, 1, 2, 0x0, 0, 3, 1, 0x0),
|
|
gsSP2Triangles( 4, 3, 0, 0x0, 4, 5, 3, 0x0),
|
|
gsSP2Triangles( 6, 5, 4, 0x0, 6, 7, 5, 0x0),
|
|
gsSP2Triangles( 8, 7, 6, 0x0, 8, 9, 7, 0x0),
|
|
gsSP2Triangles(10, 9, 8, 0x0, 10, 11, 9, 0x0),
|
|
gsSP2Triangles(12, 11, 10, 0x0, 12, 13, 11, 0x0),
|
|
gsSP2Triangles(14, 13, 12, 0x0, 14, 15, 13, 0x0),
|
|
gsSP2Triangles(16, 15, 14, 0x0, 16, 17, 15, 0x0),
|
|
gsSP2Triangles(18, 17, 16, 0x0, 18, 19, 17, 0x0),
|
|
gsSP2Triangles(20, 19, 18, 0x0, 20, 21, 19, 0x0),
|
|
gsSP2Triangles(22, 21, 20, 0x0, 22, 23, 21, 0x0),
|
|
gsSP2Triangles( 2, 23, 22, 0x0, 2, 1, 23, 0x0),
|
|
gsSP2Triangles(23, 1, 3, 0x0, 23, 3, 7, 0x0),
|
|
gsSP2Triangles( 3, 5, 7, 0x0, 7, 15, 23, 0x0),
|
|
gsSP2Triangles( 7, 11, 15, 0x0, 7, 9, 11, 0x0),
|
|
gsSP2Triangles(11, 13, 15, 0x0, 15, 17, 19, 0x0),
|
|
gsSP2Triangles(15, 19, 23, 0x0, 19, 21, 23, 0x0),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
u8 hitboxView = FALSE;
|
|
u8 surfaceView = FALSE;
|
|
|
|
/**
|
|
* Internal struct containing box info
|
|
*/
|
|
struct DebugBox {
|
|
u32 color;
|
|
Vec3s center;
|
|
Vec3s bounds;
|
|
s16 yaw;
|
|
u8 type;
|
|
};
|
|
|
|
struct DebugVert {
|
|
Vec3s pos;
|
|
Vec3f normal;
|
|
};
|
|
|
|
struct DebugBox sBoxes[MAX_DEBUG_BOXES];
|
|
s16 sNumBoxes = 0;
|
|
|
|
extern Mat4 gMatStack[32]; // XXX: Hack
|
|
|
|
/**
|
|
* The debug boxes' default transparency
|
|
*/
|
|
#define DBG_BOX_ALPHA 0x7F
|
|
/**
|
|
* The debug boxes' default color. sCurBoxColor is reset to this every frame.
|
|
*/
|
|
#define DBG_BOX_DEF_COLOR 0xFF000000
|
|
|
|
/**
|
|
* The color that new boxes will be drawn with.
|
|
*/
|
|
u32 sCurBoxColor = DBG_BOX_DEF_COLOR | DBG_BOX_ALPHA;
|
|
|
|
/**
|
|
* The allocated size of a rotated box's dl
|
|
*/
|
|
#define DBG_BOX_DLSIZE ((s32)((6 * sizeof(Gfx)) + (8 * sizeof(Vtx))))
|
|
|
|
/**
|
|
* Sets up the RCP for drawing the boxes
|
|
*/
|
|
static const Gfx dl_debug_box_begin[] = {
|
|
gsDPPipeSync(),
|
|
gsDPSetRenderMode(G_RM_ZB_XLU_SURF, G_RM_NOOP2),
|
|
gsSPClearGeometryMode(G_CULL_BACK),
|
|
gsSPSetGeometryMode(G_ZBUFFER),
|
|
gsSPTexture(0, 0, 0, G_TX_RENDERTILE, G_OFF),
|
|
gsDPSetCombineLERP(0, 0, 0, ENVIRONMENT, 0, 0, 0, ENVIRONMENT, 0, 0, 0, ENVIRONMENT, 0, 0, 0, ENVIRONMENT),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
static const Gfx dl_visual_surface[] = {
|
|
gsDPPipeSync(),
|
|
gsDPSetRenderMode(G_RM_ZB_XLU_DECAL, G_RM_NOOP2),
|
|
gsSPClearGeometryMode(G_LIGHTING),
|
|
gsSPSetGeometryMode(G_ZBUFFER),
|
|
gsSPTexture(0, 0, 0, G_TX_RENDERTILE, G_OFF),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
static const Gfx dl_debug_box_end[] = {
|
|
gsDPPipeSync(),
|
|
gsDPSetRenderMode(G_RM_OPA_SURF, G_RM_OPA_SURF2),
|
|
gsSPSetGeometryMode(G_LIGHTING | G_CULL_BACK),
|
|
gsSPClearGeometryMode(G_ZBUFFER),
|
|
gsSPTexture(0, 0, 0, G_TX_RENDERTILE, G_OFF),
|
|
gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE),
|
|
gsDPSetEnvColor(0xFF, 0xFF, 0xFF, 0xFF),
|
|
gsSPEndDisplayList(),
|
|
};
|
|
|
|
u8 viewCycle = 0;
|
|
|
|
// Puppyprint will call this from elsewhere.
|
|
void debug_box_input(void) {
|
|
if (gPlayer1Controller->buttonPressed & R_JPAD) {
|
|
viewCycle++;
|
|
if (viewCycle > 3) {
|
|
viewCycle = 0;
|
|
}
|
|
hitboxView = viewCycle == 1 || viewCycle == 3;
|
|
surfaceView = viewCycle == 2 || viewCycle == 3;
|
|
}
|
|
}
|
|
|
|
s16 gVisualSurfaceCount;
|
|
s32 gVisualOffset;
|
|
extern s32 gSurfaceNodesAllocated;
|
|
extern s32 gSurfacesAllocated;
|
|
|
|
void iterate_surfaces_visual(s32 x, s32 z, Vtx *verts) {
|
|
struct SurfaceNode *node;
|
|
struct Surface *surf;
|
|
s32 i = 0;
|
|
ColorRGB col = COLOR_RGB_RED;
|
|
|
|
if (is_outside_level_bounds(x, z)) return;
|
|
|
|
s32 cellX = GET_CELL_COORD(x);
|
|
s32 cellZ = GET_CELL_COORD(z);
|
|
|
|
for (i = 0; i < (2 * NUM_SPATIAL_PARTITIONS); i++) {
|
|
switch (i) {
|
|
case 0: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_GREEN ); break;
|
|
case 1: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_GREEN ); break;
|
|
case 2: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_BLUE ); break;
|
|
case 3: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_BLUE ); break;
|
|
case 4: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_RED ); break;
|
|
case 5: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_RED ); break;
|
|
case 6: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_YELLOW); break;
|
|
case 7: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_YELLOW); break;
|
|
}
|
|
|
|
while (node != NULL) {
|
|
surf = node->surface;
|
|
node = node->next;
|
|
|
|
if (SURFACE_IS_INSTANT_WARP(surf->type)) {
|
|
make_vertex(verts, (gVisualSurfaceCount + 0), surf->vertex1[0], surf->vertex1[1], surf->vertex1[2], 0, 0, 0xFF, 0xA0, 0x00, 0x80);
|
|
make_vertex(verts, (gVisualSurfaceCount + 1), surf->vertex2[0], surf->vertex2[1], surf->vertex2[2], 0, 0, 0xFF, 0xA0, 0x00, 0x80);
|
|
make_vertex(verts, (gVisualSurfaceCount + 2), surf->vertex3[0], surf->vertex3[1], surf->vertex3[2], 0, 0, 0xFF, 0xA0, 0x00, 0x80);
|
|
} else {
|
|
make_vertex(verts, (gVisualSurfaceCount + 0), surf->vertex1[0], surf->vertex1[1], surf->vertex1[2], 0, 0, col[0], col[1], col[2], 0x80);
|
|
make_vertex(verts, (gVisualSurfaceCount + 1), surf->vertex2[0], surf->vertex2[1], surf->vertex2[2], 0, 0, col[0], col[1], col[2], 0x80);
|
|
make_vertex(verts, (gVisualSurfaceCount + 2), surf->vertex3[0], surf->vertex3[1], surf->vertex3[2], 0, 0, col[0], col[1], col[2], 0x80);
|
|
}
|
|
|
|
gVisualSurfaceCount += 3;
|
|
}
|
|
}
|
|
}
|
|
|
|
void iterate_surfaces_envbox(Vtx *verts) {
|
|
TerrainData *p = gEnvironmentRegions;
|
|
ColorRGB col = COLOR_RGB_YELLOW;
|
|
s32 i = 0;
|
|
|
|
if (p != NULL) {
|
|
s32 numRegions = *p++;
|
|
for (i = 0; i < numRegions; i++) {
|
|
make_vertex(verts, (gVisualSurfaceCount + 0), p[1], p[5], p[2], 0, 0, col[0], col[1], col[2], 0x80);
|
|
make_vertex(verts, (gVisualSurfaceCount + 1), p[1], p[5], p[4], 0, 0, col[0], col[1], col[2], 0x80);
|
|
make_vertex(verts, (gVisualSurfaceCount + 2), p[3], p[5], p[2], 0, 0, col[0], col[1], col[2], 0x80);
|
|
|
|
make_vertex(verts, (gVisualSurfaceCount + 3), p[3], p[5], p[2], 0, 0, col[0], col[1], col[2], 0x80);
|
|
make_vertex(verts, (gVisualSurfaceCount + 4), p[1], p[5], p[4], 0, 0, col[0], col[1], col[2], 0x80);
|
|
make_vertex(verts, (gVisualSurfaceCount + 5), p[3], p[5], p[4], 0, 0, col[0], col[1], col[2], 0x80);
|
|
|
|
gVisualSurfaceCount += 6;
|
|
gVisualOffset += 6;
|
|
p += 6;
|
|
}
|
|
}
|
|
}
|
|
|
|
// VERTCOUNT = The highest number divisible by 6, which is less than the maximum vertex buffer divided by 2.
|
|
#define VERTCOUNT 30
|
|
|
|
void visual_surface_display(Gfx **gfx, Vtx *verts, s32 iteration) {
|
|
s32 vts = (iteration ? gVisualOffset : gVisualSurfaceCount);
|
|
s32 vtl = 0;
|
|
s32 count = VERTCOUNT;
|
|
s32 ntx = 0;
|
|
|
|
while (vts > 0) {
|
|
if (count == VERTCOUNT) {
|
|
ntx = MIN(VERTCOUNT, vts);
|
|
gSPVertex((*gfx)++, VIRTUAL_TO_PHYSICAL(verts + (gVisualSurfaceCount - vts)), ntx, 0);
|
|
count = 0;
|
|
vtl = VERTCOUNT;
|
|
}
|
|
|
|
if (vtl >= 6) {
|
|
gSP2Triangles((*gfx)++, (count + 0),
|
|
(count + 1),
|
|
(count + 2), 0x0,
|
|
(count + 3),
|
|
(count + 4),
|
|
(count + 5), 0x0);
|
|
vts -= 6;
|
|
vtl -= 6;
|
|
count += 6;
|
|
} else if (vtl >= 3) {
|
|
gSP1Triangle((*gfx)++, (count + 0),
|
|
(count + 1),
|
|
(count + 2), 0x0);
|
|
vts -= 3;
|
|
vtl -= 3;
|
|
count += 3;
|
|
}
|
|
}
|
|
}
|
|
|
|
s32 iterate_surface_count(s32 x, s32 z) {
|
|
struct SurfaceNode *node;
|
|
s32 i = 0;
|
|
s32 j = 0;
|
|
TerrainData *p = gEnvironmentRegions;
|
|
s32 numRegions;
|
|
|
|
if (is_outside_level_bounds(x, z)) return 0;
|
|
|
|
s32 cellX = GET_CELL_COORD(x);
|
|
s32 cellZ = GET_CELL_COORD(z);
|
|
|
|
for (i = 0; i < (2 * NUM_SPATIAL_PARTITIONS); i++) {
|
|
switch (i) {
|
|
case 0: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next; break;
|
|
case 1: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next; break;
|
|
case 2: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; break;
|
|
case 3: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; break;
|
|
case 4: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next; break;
|
|
case 5: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next; break;
|
|
case 6: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next; break;
|
|
case 7: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next; break;
|
|
}
|
|
|
|
while (node != NULL) {
|
|
node = node->next;
|
|
j++;
|
|
}
|
|
}
|
|
if (p != NULL) {
|
|
numRegions = *p++;
|
|
j += (numRegions * 6);
|
|
}
|
|
|
|
return j;
|
|
}
|
|
|
|
void visual_surface_loop(Gfx **gfx) {
|
|
if (!gSurfaceNodesAllocated
|
|
|| !gSurfacesAllocated
|
|
|| !gMarioState->marioObj) {
|
|
return;
|
|
}
|
|
Vtx *verts = alloc_display_list((iterate_surface_count(gMarioState->pos[0], gMarioState->pos[2]) * 3) * sizeof(Vtx));
|
|
|
|
gVisualSurfaceCount = 0;
|
|
gVisualOffset = 0;
|
|
|
|
if (verts == NULL) {
|
|
return;
|
|
}
|
|
|
|
gSPDisplayList((*gfx)++, dl_visual_surface);
|
|
|
|
iterate_surfaces_visual(gMarioState->pos[0], gMarioState->pos[2], verts);
|
|
|
|
visual_surface_display(gfx, verts, 0);
|
|
|
|
gDPPipeSync((*gfx)++);
|
|
iterate_surfaces_envbox(verts);
|
|
|
|
gDPSetRenderMode((*gfx)++, G_RM_ZB_XLU_SURF, G_RM_NOOP2);
|
|
|
|
visual_surface_display(gfx, verts, 1);
|
|
|
|
gSPDisplayList((*gfx)++, dl_debug_box_end);
|
|
}
|
|
|
|
/**
|
|
* Adds a box to the list to be rendered this frame.
|
|
*
|
|
* If there are already MAX_DEBUG_BOXES boxes, does nothing.
|
|
*/
|
|
static void append_debug_box(Vec3f center, Vec3f bounds, s16 yaw, s32 type) {
|
|
if (hitboxView) {
|
|
if (sNumBoxes >= MAX_DEBUG_BOXES) return;
|
|
|
|
vec3f_to_vec3s(sBoxes[sNumBoxes].center, center);
|
|
vec3f_to_vec3s(sBoxes[sNumBoxes].bounds, bounds);
|
|
|
|
sBoxes[sNumBoxes].yaw = yaw;
|
|
sBoxes[sNumBoxes].color = sCurBoxColor;
|
|
sBoxes[sNumBoxes].type = type;
|
|
++sNumBoxes;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw new boxes with the given color.
|
|
* Color format is 32-bit RGBA.
|
|
* If the alpha component is zero, DBG_BOX_ALPHA (0x7f) will be used instead.
|
|
* Ex: 0xFF000000 becomes 0xFF00007F
|
|
*/
|
|
void debug_box_color(u32 color) {
|
|
if ((color & 0xFF) == 0) color |= (DBG_BOX_ALPHA);
|
|
sCurBoxColor = color;
|
|
}
|
|
|
|
/**
|
|
* Draws a debug box from (center - bounds) to (center + bounds)
|
|
* To draw a rotated box, use debug_box_rot()
|
|
*
|
|
* @see debug_box_rot()
|
|
*/
|
|
void debug_box(Vec3f center, Vec3f bounds, s32 type) {
|
|
append_debug_box(center, bounds, 0, type);
|
|
}
|
|
|
|
/**
|
|
* Draws a debug box from (center - bounds) to (center + bounds), rotating it by `yaw`
|
|
*/
|
|
void debug_box_rot(Vec3f center, Vec3f bounds, s16 yaw, s32 type) {
|
|
append_debug_box(center, bounds, yaw, type);
|
|
}
|
|
|
|
/**
|
|
* Draws a debug box from pMin to pMax
|
|
* To draw a rotated box this way, use debug_box_pos_rot()
|
|
*
|
|
* @see debug_box_pos_rot()
|
|
*/
|
|
void debug_box_pos(Vec3f pMin, Vec3f pMax, s32 type) {
|
|
debug_box_pos_rot(pMin, pMax, 0x0, type);
|
|
}
|
|
|
|
/**
|
|
* Draws a debug box from pMin to pMax, rotating it in the xz-plane by `yaw`
|
|
*/
|
|
void debug_box_pos_rot(Vec3f pMin, Vec3f pMax, s16 yaw, s32 type) {
|
|
Vec3f center, bounds;
|
|
|
|
bounds[0] = ((pMax[0] - pMin[0]) / 2.0f);
|
|
bounds[1] = ((pMax[1] - pMin[1]) / 2.0f);
|
|
bounds[2] = ((pMax[2] - pMin[2]) / 2.0f);
|
|
|
|
vec3f_sum(center, pMin, bounds);
|
|
|
|
append_debug_box(center, bounds, yaw, type);
|
|
}
|
|
|
|
static void render_box(Gfx **gfx, int index) {
|
|
struct DebugBox *box = &sBoxes[index];
|
|
s32 color = box->color;
|
|
Mat4 mtxFloat;
|
|
|
|
// Allocate the transformation matrix for this box
|
|
Mtx *mtx = alloc_display_list(sizeof(Mtx));
|
|
|
|
if (mtx == NULL) return;
|
|
|
|
// Calculate rotation matrix
|
|
guRotateF(mtxFloat, ((box->yaw / (f32)0x10000) * 360.0f), 0, 1.0f, 0);
|
|
|
|
// Apply scale to column vectors of matrix
|
|
for (int i = 0; i < 3; i++) {
|
|
for (int j = 0; j < 3; j++) {
|
|
mtxFloat[i][j] *= box->bounds[j] * 0.01f;
|
|
}
|
|
}
|
|
|
|
// Copy translation into matrix
|
|
for (int i = 0; i < 3; i++) {
|
|
mtxFloat[3][i] = box->center[i];
|
|
}
|
|
|
|
// Convert the matrix from floating-point to fixed-point
|
|
mtxf_to_mtx(mtx, mtxFloat);
|
|
|
|
// Load the calculated matrix
|
|
gSPMatrix((*gfx)++, mtx, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
|
|
|
|
// Set env color to the color of this box
|
|
gDPSetColor((*gfx)++, G_SETENVCOLOR, color);
|
|
|
|
if (box->type & DEBUG_SHAPE_BOX) {
|
|
gSPDisplayList((*gfx)++, dl_debug_box_verts);
|
|
}
|
|
if (box->type & DEBUG_SHAPE_CYLINDER) {
|
|
gSPDisplayList((*gfx)++, dl_debug_cylinder_verts);
|
|
}
|
|
}
|
|
|
|
void render_debug_boxes(Gfx **gfx) {
|
|
s32 i;
|
|
|
|
debug_box_color(DBG_BOX_DEF_COLOR);
|
|
|
|
if (sNumBoxes == 0) return;
|
|
if (gAreaUpdateCounter < 3) return;
|
|
|
|
gSPDisplayList((*gfx)++, dl_debug_box_begin);
|
|
|
|
for (i = 0; i < sNumBoxes; ++i) {
|
|
render_box(gfx, i);
|
|
}
|
|
|
|
sNumBoxes = 0;
|
|
gSPDisplayList((*gfx)++, dl_debug_box_end);
|
|
}
|
|
|
|
#endif
|