From 88f1f328b92a09982581966c8d6abb0de4fb1143 Mon Sep 17 00:00:00 2001 From: Angel Tomkins Date: Wed, 28 Feb 2024 20:48:26 -0500 Subject: [PATCH 1/5] Added vertex batching --- src/nds/nds_renderer.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/nds/nds_renderer.c b/src/nds/nds_renderer.c index 9851e3ae4f..0a229bd41f 100644 --- a/src/nds/nds_renderer.c +++ b/src/nds/nds_renderer.c @@ -81,6 +81,10 @@ static uint16_t fog_max; static int no_texture; static int frame_count; +static Vtx_t* vertex_batch[32 * 3]; +static uint8_t num_verts_batched = 0; + + struct Sprite sprites[MAX_SPRITES]; struct { @@ -468,26 +472,20 @@ static void g_vtx(Gwords *words) { } static void g_tri1(Gwords *words) { - // Draw a triangle - const Vtx_t *v[] = { - &vertex_buffer[((words->w0 >> 16) & 0xFF) >> 1].v, - &vertex_buffer[((words->w0 >> 8) & 0xFF) >> 1].v, - &vertex_buffer[((words->w0 >> 0) & 0xFF) >> 1].v - }; - draw_vertices(v, 3); + // Batch a triangle to render + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 16) & 0xFF) >> 1].v; + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 8) & 0xFF) >> 1].v; + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 0) & 0xFF) >> 1].v; } static void g_tri2(Gwords *words) { - // Draw two triangles at once - const Vtx_t *v[] = { - &vertex_buffer[((words->w0 >> 16) & 0xFF) >> 1].v, - &vertex_buffer[((words->w0 >> 8) & 0xFF) >> 1].v, - &vertex_buffer[((words->w0 >> 0) & 0xFF) >> 1].v, - &vertex_buffer[((words->w1 >> 16) & 0xFF) >> 1].v, - &vertex_buffer[((words->w1 >> 8) & 0xFF) >> 1].v, - &vertex_buffer[((words->w1 >> 0) & 0xFF) >> 1].v - }; - draw_vertices(v, 6); + // Batch triangles to render + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 16) & 0xFF) >> 1].v; + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 8) & 0xFF) >> 1].v; + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 0) & 0xFF) >> 1].v; + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w1 >> 16) & 0xFF) >> 1].v; + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w1 >> 8) & 0xFF) >> 1].v; + vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w1 >> 0) & 0xFF) >> 1].v; } static void g_texture(Gwords *words) { @@ -939,6 +937,12 @@ static void execute(Gfx* cmd) { while (true) { const uint8_t opcode = cmd->words.w0 >> 24; + // Draw the batched verticies + if ((opcode != G_TRI1 && opcode != G_TRI2 && num_verts_batched > 0) || num_verts_batched >= 90) { + draw_vertices(vertex_batch, num_verts_batched); + num_verts_batched = 0; + } + switch (opcode) { case G_VTX: g_vtx(&cmd->words); break; case G_TRI1: g_tri1(&cmd->words); break; From cfcf475773da4f19658aff4845ef3250b4757132 Mon Sep 17 00:00:00 2001 From: Angel Tomkins Date: Wed, 28 Feb 2024 20:53:23 -0500 Subject: [PATCH 2/5] Revert "Added vertex batching" This reverts commit 88f1f328b92a09982581966c8d6abb0de4fb1143. revert --- src/nds/nds_renderer.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/nds/nds_renderer.c b/src/nds/nds_renderer.c index 0a229bd41f..9851e3ae4f 100644 --- a/src/nds/nds_renderer.c +++ b/src/nds/nds_renderer.c @@ -81,10 +81,6 @@ static uint16_t fog_max; static int no_texture; static int frame_count; -static Vtx_t* vertex_batch[32 * 3]; -static uint8_t num_verts_batched = 0; - - struct Sprite sprites[MAX_SPRITES]; struct { @@ -472,20 +468,26 @@ static void g_vtx(Gwords *words) { } static void g_tri1(Gwords *words) { - // Batch a triangle to render - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 16) & 0xFF) >> 1].v; - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 8) & 0xFF) >> 1].v; - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 0) & 0xFF) >> 1].v; + // Draw a triangle + const Vtx_t *v[] = { + &vertex_buffer[((words->w0 >> 16) & 0xFF) >> 1].v, + &vertex_buffer[((words->w0 >> 8) & 0xFF) >> 1].v, + &vertex_buffer[((words->w0 >> 0) & 0xFF) >> 1].v + }; + draw_vertices(v, 3); } static void g_tri2(Gwords *words) { - // Batch triangles to render - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 16) & 0xFF) >> 1].v; - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 8) & 0xFF) >> 1].v; - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w0 >> 0) & 0xFF) >> 1].v; - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w1 >> 16) & 0xFF) >> 1].v; - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w1 >> 8) & 0xFF) >> 1].v; - vertex_batch[num_verts_batched++] = &vertex_buffer[((words->w1 >> 0) & 0xFF) >> 1].v; + // Draw two triangles at once + const Vtx_t *v[] = { + &vertex_buffer[((words->w0 >> 16) & 0xFF) >> 1].v, + &vertex_buffer[((words->w0 >> 8) & 0xFF) >> 1].v, + &vertex_buffer[((words->w0 >> 0) & 0xFF) >> 1].v, + &vertex_buffer[((words->w1 >> 16) & 0xFF) >> 1].v, + &vertex_buffer[((words->w1 >> 8) & 0xFF) >> 1].v, + &vertex_buffer[((words->w1 >> 0) & 0xFF) >> 1].v + }; + draw_vertices(v, 6); } static void g_texture(Gwords *words) { @@ -937,12 +939,6 @@ static void execute(Gfx* cmd) { while (true) { const uint8_t opcode = cmd->words.w0 >> 24; - // Draw the batched verticies - if ((opcode != G_TRI1 && opcode != G_TRI2 && num_verts_batched > 0) || num_verts_batched >= 90) { - draw_vertices(vertex_batch, num_verts_batched); - num_verts_batched = 0; - } - switch (opcode) { case G_VTX: g_vtx(&cmd->words); break; case G_TRI1: g_tri1(&cmd->words); break; From fa4cd482afa8bed3e8b5b70c04db0bad97522d08 Mon Sep 17 00:00:00 2001 From: Angel Tomkins Date: Mon, 4 Mar 2024 22:47:13 -0500 Subject: [PATCH 3/5] Reimplemented painting vertex displacement to use fixed point numbers --- src/game/paintings.c | 51 +++++++++++++++++++++++++++++--------------- src/game/paintings.h | 10 +++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/game/paintings.c b/src/game/paintings.c index 481db8f37c..e3f74ab49d 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c @@ -1,5 +1,7 @@ #include +#include "../nds/nds_include.h" + #include "sm64.h" #include "area.h" #include "engine/graph_node.h" @@ -189,6 +191,8 @@ struct Painting **sPaintingGroups[] = { s16 gPaintingUpdateCounter = 1; s16 gLastPaintingUpdateCounter = 0; +//struct FixedPainting* fixedPainting; + /** * Stop paintings in paintingGroup from rippling if their id is different from *idptr. */ @@ -615,37 +619,42 @@ void painting_update_ripple_state(struct Painting *painting) { * @return the ripple function at posX, posY * note that posX and posY correspond to a point on the face of the painting, not actual axes */ -s16 calculate_ripple_at_point(struct Painting *painting, f32 posX, f32 posY) { +s16 calculate_ripple_at_point(struct FixedPainting *fixedPainting, f32 posX, f32 posY) { /// Controls the peaks of the ripple. - f32 rippleMag = painting->currRippleMag; + s32 rippleMag = fixedPainting->currRippleMag; /// Controls the ripple's frequency - f32 rippleRate = painting->currRippleRate; + s32 rippleRate = fixedPainting->currRippleRate; /// Controls how fast the ripple spreads - f32 dispersionFactor = painting->dispersionFactor; + s32 dispersionFactor = fixedPainting->dispersionFactor; /// How far the ripple has spread - f32 rippleTimer = painting->rippleTimer; + s32 rippleTimer = fixedPainting->rippleTimer; /// x and y ripple origin - f32 rippleX = painting->rippleX; - f32 rippleY = painting->rippleY; + s32 rippleX = fixedPainting->rippleX; + s32 rippleY = fixedPainting->rippleY; + + s32 distanceToOrigin; + s32 rippleDistance; - f32 distanceToOrigin; - f32 rippleDistance; + s32 sposX = (floattof32(posX) * ((fixedPainting->size) / floattof32(PAINTING_SIZE))); + s32 sposY = (floattof32(posY) * ((fixedPainting->size) / floattof32(PAINTING_SIZE))); + + distanceToOrigin = sqrtf32(mulf32((sposX - rippleX), (sposX - rippleX)) + + mulf32((sposY - rippleY), (sposY - rippleY))); - posX *= painting->size / PAINTING_SIZE; - posY *= painting->size / PAINTING_SIZE; - distanceToOrigin = sqrtf((posX - rippleX) * (posX - rippleX) + (posY - rippleY) * (posY - rippleY)); // A larger dispersionFactor makes the ripple spread slower - rippleDistance = distanceToOrigin / dispersionFactor; + rippleDistance = (distanceToOrigin<<12) / dispersionFactor; if (rippleTimer < rippleDistance) { // if the ripple hasn't reached the point yet, make the point magnitude 0 return 0; } else { // use a cosine wave to make the ripple go up and down, // scaled by the painting's ripple magnitude - f32 rippleZ = rippleMag * cosf(rippleRate * (2 * M_PI) * (rippleTimer - rippleDistance)); + s16 angle = (mulf32(rippleRate, (rippleTimer - rippleDistance))*DEGREES_IN_CIRCLE) >> 12; + s32 value = cosLerp(angle); + f32 rippleZ = mulf32(rippleMag, value); // round it to an int and return it - return round_float(rippleZ); + return f32toint(rippleZ); } } @@ -683,6 +692,14 @@ s16 ripple_if_movable(struct Painting *painting, s16 movable, s16 posX, s16 posY */ void painting_generate_mesh(struct Painting *painting, s16 *mesh, s16 numTris) { s16 i; + struct FixedPainting fixed_painting; + fixed_painting.currRippleMag = floattof32(painting->currRippleMag); + fixed_painting.currRippleRate = floattof32(painting->currRippleRate); + fixed_painting.dispersionFactor = floattof32(painting->dispersionFactor); + fixed_painting.rippleTimer = floattof32(painting->rippleTimer); + fixed_painting.rippleX = floattof32(painting->rippleX); + fixed_painting.rippleY = floattof32(painting->rippleY); + fixed_painting.size = floattof32(painting->size); gPaintingMesh = mem_pool_alloc(gEffectsMemoryPool, numTris * sizeof(struct PaintingMeshVertex)); if (gPaintingMesh == NULL) { @@ -693,7 +710,7 @@ void painting_generate_mesh(struct Painting *painting, s16 *mesh, s16 numTris) { gPaintingMesh[i].pos[1] = mesh[i * 3 + 2]; // The "z coordinate" of each vertex in the mesh is either 1 or 0. Instead of being an // actual coordinate, it just determines whether the vertex moves - gPaintingMesh[i].pos[2] = ripple_if_movable(painting, mesh[i * 3 + 3], + gPaintingMesh[i].pos[2] = ripple_if_movable(&fixed_painting, mesh[i * 3 + 3], gPaintingMesh[i].pos[0], gPaintingMesh[i].pos[1]); } } @@ -1284,4 +1301,4 @@ Gfx *geo_painting_update(s32 callContext, UNUSED struct GraphNode *node, UNUSED gPaintingMarioZPos = gMarioObject->oPosZ; } return NULL; -} +} \ No newline at end of file diff --git a/src/game/paintings.h b/src/game/paintings.h index 8c93033138..dd604ab118 100644 --- a/src/game/paintings.h +++ b/src/game/paintings.h @@ -116,6 +116,16 @@ struct Painting { f32 size; }; +struct FixedPainting { + s32 currRippleMag; + s32 currRippleRate; + s32 dispersionFactor; + s32 rippleTimer; + s32 rippleX; + s32 rippleY; + s32 size; +}; + /** * Contains the position and normal of a vertex in the painting's generated mesh. */ From 8f7d97795b0695699294ff0ed38f4261297e6836 Mon Sep 17 00:00:00 2001 From: Angel Tomkins Date: Mon, 4 Mar 2024 22:51:12 -0500 Subject: [PATCH 4/5] Removed unused pointer added during testing --- src/game/paintings.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/paintings.c b/src/game/paintings.c index e3f74ab49d..baa60e794d 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c @@ -191,8 +191,6 @@ struct Painting **sPaintingGroups[] = { s16 gPaintingUpdateCounter = 1; s16 gLastPaintingUpdateCounter = 0; -//struct FixedPainting* fixedPainting; - /** * Stop paintings in paintingGroup from rippling if their id is different from *idptr. */ From 886dc8d5e824ab17dcf7e34f35d3f720b688d159 Mon Sep 17 00:00:00 2001 From: Angel Tomkins Date: Wed, 6 Mar 2024 16:19:29 -0500 Subject: [PATCH 5/5] Added preprocessor ifdef statements to ensure build works on non TARGET_NDS devices --- src/game/paintings.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ src/game/paintings.h | 2 ++ 2 files changed, 47 insertions(+) diff --git a/src/game/paintings.c b/src/game/paintings.c index baa60e794d..ce01c15f05 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c @@ -1,6 +1,8 @@ #include +#ifdef TARGET_NDS #include "../nds/nds_include.h" +#endif #include "sm64.h" #include "area.h" @@ -617,6 +619,7 @@ void painting_update_ripple_state(struct Painting *painting) { * @return the ripple function at posX, posY * note that posX and posY correspond to a point on the face of the painting, not actual axes */ +#ifdef TARGET_NDS s16 calculate_ripple_at_point(struct FixedPainting *fixedPainting, f32 posX, f32 posY) { /// Controls the peaks of the ripple. s32 rippleMag = fixedPainting->currRippleMag; @@ -655,6 +658,41 @@ s16 calculate_ripple_at_point(struct FixedPainting *fixedPainting, f32 posX, f32 return f32toint(rippleZ); } } +#else +s16 calculate_ripple_at_point(struct Painting *painting, f32 posX, f32 posY) { + /// Controls the peaks of the ripple. + f32 rippleMag = painting->currRippleMag; + /// Controls the ripple's frequency + f32 rippleRate = painting->currRippleRate; + /// Controls how fast the ripple spreads + f32 dispersionFactor = painting->dispersionFactor; + /// How far the ripple has spread + f32 rippleTimer = painting->rippleTimer; + /// x and y ripple origin + f32 rippleX = painting->rippleX; + f32 rippleY = painting->rippleY; + + f32 distanceToOrigin; + f32 rippleDistance; + + posX *= painting->size / PAINTING_SIZE; + posY *= painting->size / PAINTING_SIZE; + distanceToOrigin = sqrtf((posX - rippleX) * (posX - rippleX) + (posY - rippleY) * (posY - rippleY)); + // A larger dispersionFactor makes the ripple spread slower + rippleDistance = distanceToOrigin / dispersionFactor; + if (rippleTimer < rippleDistance) { + // if the ripple hasn't reached the point yet, make the point magnitude 0 + return 0; + } else { + // use a cosine wave to make the ripple go up and down, + // scaled by the painting's ripple magnitude + f32 rippleZ = rippleMag * cosf(rippleRate * (2 * M_PI) * (rippleTimer - rippleDistance)); + + // round it to an int and return it + return round_float(rippleZ); + } +} +#endif /** * If movable, return the ripple function at (posX, posY) @@ -690,6 +728,7 @@ s16 ripple_if_movable(struct Painting *painting, s16 movable, s16 posX, s16 posY */ void painting_generate_mesh(struct Painting *painting, s16 *mesh, s16 numTris) { s16 i; + #ifdef TARGET_NDS struct FixedPainting fixed_painting; fixed_painting.currRippleMag = floattof32(painting->currRippleMag); fixed_painting.currRippleRate = floattof32(painting->currRippleRate); @@ -698,6 +737,7 @@ void painting_generate_mesh(struct Painting *painting, s16 *mesh, s16 numTris) { fixed_painting.rippleX = floattof32(painting->rippleX); fixed_painting.rippleY = floattof32(painting->rippleY); fixed_painting.size = floattof32(painting->size); + #endif gPaintingMesh = mem_pool_alloc(gEffectsMemoryPool, numTris * sizeof(struct PaintingMeshVertex)); if (gPaintingMesh == NULL) { @@ -708,8 +748,13 @@ void painting_generate_mesh(struct Painting *painting, s16 *mesh, s16 numTris) { gPaintingMesh[i].pos[1] = mesh[i * 3 + 2]; // The "z coordinate" of each vertex in the mesh is either 1 or 0. Instead of being an // actual coordinate, it just determines whether the vertex moves + #ifdef TARGET_NDS gPaintingMesh[i].pos[2] = ripple_if_movable(&fixed_painting, mesh[i * 3 + 3], gPaintingMesh[i].pos[0], gPaintingMesh[i].pos[1]); + #else + gPaintingMesh[i].pos[2] = ripple_if_movable(painting, mesh[i * 3 + 3], + gPaintingMesh[i].pos[0], gPaintingMesh[i].pos[1]); + #endif } } diff --git a/src/game/paintings.h b/src/game/paintings.h index dd604ab118..56324a259a 100644 --- a/src/game/paintings.h +++ b/src/game/paintings.h @@ -116,6 +116,7 @@ struct Painting { f32 size; }; +#ifdef TARGET_NDS struct FixedPainting { s32 currRippleMag; s32 currRippleRate; @@ -125,6 +126,7 @@ struct FixedPainting { s32 rippleY; s32 size; }; +#endif /** * Contains the position and normal of a vertex in the painting's generated mesh.