From 9fe391a2a4617cdb6ce3b2ab743183756f2ca9bd Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sun, 15 Jun 2025 22:17:24 -0600 Subject: [PATCH] Fix More Interpolation (#220) * Fix SetTextMatrix Interpolation (flashing text) * Interpolate pause menu item box * Interp mtxf_translation_x_y_rotate_z_scale_x_y * Fix billboarding for freecam * Fix menus battle mode back to grand prix bug * Fix snow interp * interp star clouds --- src/engine/Matrix.cpp | 26 +++++--- src/engine/Matrix.h | 3 +- src/engine/courses/FrappeSnowland.cpp | 2 +- src/math_util_2.c | 1 + src/menu_items.c | 43 +++++++----- src/menus.c | 1 + src/os/guMtxCatL.c | 2 + src/port/interpolation/FrameInterpolation.cpp | 65 +++++++++++++++++-- src/port/interpolation/FrameInterpolation.h | 8 ++- src/racing/actors.c | 13 +++- src/render_objects.c | 4 ++ 11 files changed, 135 insertions(+), 33 deletions(-) diff --git a/src/engine/Matrix.cpp b/src/engine/Matrix.cpp index 671489413..b55a9b89f 100644 --- a/src/engine/Matrix.cpp +++ b/src/engine/Matrix.cpp @@ -35,8 +35,8 @@ void AddMatrixFixed(std::vector& stack, s32 flags) { } // Used in func_80095BD0 -Mtx* SetTextMatrix(f32 arg1, f32 arg2, f32 arg3, f32 arg4) { - Mat4 mf; +void SetTextMatrix(Mat4 mf, f32 x, f32 y, f32 arg3, f32 arg4) { + FrameInterpolation_Record_SetTextMatrix((Mat4*)&mf, x, y, arg3, arg4); mf[0][0] = arg3; mf[0][1] = 0.0f; mf[0][2] = 0.0f; @@ -49,15 +49,25 @@ Mtx* SetTextMatrix(f32 arg1, f32 arg2, f32 arg3, f32 arg4) { mf[2][1] = 0.0f; mf[2][2] = 1.0f; mf[2][3] = 0.0f; - mf[3][0] = arg1; - mf[3][1] = arg2; + mf[3][0] = x; + mf[3][1] = y; mf[3][2] = 0.0f; mf[3][3] = 1.0f; - Mtx* mtx = GetMatrix(gWorldInstance.Mtx.Effects); - FrameInterpolation_RecordMatrixMtxFToMtx((MtxF*)mf, mtx); - guMtxF2L(mf, mtx); +} - return mtx; +// AddMatrix but with custom gfx ptr arg and flags are predefined +Gfx* AddTextMatrix(Gfx* displayListHead, Mat4 mtx) { + // Push a new matrix to the stack + gWorldInstance.Mtx.Effects.emplace_back(); + + // Convert to a fixed-point matrix + FrameInterpolation_RecordMatrixMtxFToMtx((MtxF*)mtx, &gWorldInstance.Mtx.Effects.back()); + guMtxF2L(mtx, &gWorldInstance.Mtx.Effects.back()); + + // Load the matrix + gSPMatrix(displayListHead++, &gWorldInstance.Mtx.Effects.back(), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + return displayListHead; } void ApplyMatrixTransformations(Mat4 mtx, FVector pos, IRotator rot, FVector scale) { diff --git a/src/engine/Matrix.h b/src/engine/Matrix.h index 180ebfb16..a1e943a40 100644 --- a/src/engine/Matrix.h +++ b/src/engine/Matrix.h @@ -17,7 +17,8 @@ void AddObjectMatrix(Mat4 mtx, s32 flags); void AddEffectMatrix(Mat4 mtx, s32 flags); void AddEffectMatrixOrtho(void); void AddEffectMatrixFixed(s32 flags); -Mtx* SetTextMatrix(f32 arg1, f32 arg2, f32 arg3, f32 arg4); +void SetTextMatrix(Mat4 mf, f32 arg1, f32 arg2, f32 arg3, f32 arg4); +Gfx* AddTextMatrix(Gfx* displayListHead, Mat4 mtx); Mtx* GetEffectMatrix(void); void ClearHudMatrixPool(void); void ClearEffectsMatrixPool(void); diff --git a/src/engine/courses/FrappeSnowland.cpp b/src/engine/courses/FrappeSnowland.cpp index 16b9b7380..66a1f9b1a 100644 --- a/src/engine/courses/FrappeSnowland.cpp +++ b/src/engine/courses/FrappeSnowland.cpp @@ -178,7 +178,6 @@ void FrappeSnowland::BeginPlay() { void FrappeSnowland::InitClouds() { s32 var_s0; s32 var_s4; - if (gPlayerCount == 1) { var_s4 = 0x32; } else { @@ -189,6 +188,7 @@ void FrappeSnowland::InitClouds() { } D_8018D1F8 += var_s0; D_8018D1F0 = var_s0; + D_8018D230 = 0; // This must be turned off or mayhem ensues } void FrappeSnowland::UpdateClouds(s32 sp1C, Camera* camera) { diff --git a/src/math_util_2.c b/src/math_util_2.c index b113c6a5d..1431d8ada 100644 --- a/src/math_util_2.c +++ b/src/math_util_2.c @@ -579,6 +579,7 @@ UNUSED void mtxf_rotate_z_scale_x_y(Mat4 dest, u16 angle, f32 scale) { void mtxf_translation_x_y_rotate_z_scale_x_y(Mat4 dest, s32 x, s32 y, u16 angle, f32 scale) { f32 sin_theta = sins(angle); f32 cos_theta = coss(angle) * scale; + FrameInterpolation_RecordMatrixPosRotScaleXY(dest, x, y, angle, scale); dest[2][0] = 0.0f; dest[0][0] = cos_theta; diff --git a/src/menu_items.c b/src/menu_items.c index d65e4b2a4..6be566b08 100644 --- a/src/menu_items.c +++ b/src/menu_items.c @@ -47,6 +47,7 @@ #include "engine/courses/Course.h" #include "engine/Matrix.h" #include "src/engine/HM_Intro.h" +#include "src/port/interpolation/FrameInterpolation.h" const char* GetCupName(void); @@ -2716,9 +2717,13 @@ Gfx* func_80095BD0(Gfx* displayListHead, u8* arg1, f32 arg2, f32 arg3, u32 arg4, if (gMatrixEffectCount < 0) { rmonPrintf("effectcount < 0 !!!!!!(kawano)\n"); } + FrameInterpolation_RecordOpenChild("flashing_text", TAG_LETTER((uintptr_t)&arg1 << 8) + (arg4 + arg5)); + Mat4 mf; + SetTextMatrix(mf, arg2, arg3, arg6, arg7); // func_80095AE0(&gGfxPool->mtxEffect[gMatrixEffectCount], arg2, arg3, arg6, arg7); - Mtx* mtx = SetTextMatrix(arg2, arg3, arg6, arg7); - gSPMatrix(displayListHead++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + displayListHead = AddTextMatrix(displayListHead, mf); + //gSPMatrix(displayListHead++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gMKLoadTextureTile_4b(displayListHead++, arg1, G_IM_FMT_I, arg4, 0, 0, 0, arg4, arg5, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); switch (arg4) { @@ -2735,28 +2740,32 @@ Gfx* func_80095BD0(Gfx* displayListHead, u8* arg1, f32 arg2, f32 arg3, u32 arg4, var_a1 = D_02007DF8; break; } - - return func_800959F8(displayListHead, var_a1); + displayListHead = func_800959F8(displayListHead, var_a1); + FrameInterpolation_RecordCloseChild(); + return displayListHead; } +// Time trials text box Gfx* func_80095BD0_wide_right(Gfx* displayListHead, u8* arg1, f32 arg2, f32 arg3, u32 arg4, u32 arg5, f32 arg6, f32 arg7) { Vtx* var_a1; // A match is a match, but why are goto's required here? if (gMatrixEffectCount >= 0x2F7) { - goto func_80095BD0_label1; + rmonPrintf("func_80095BD0_wide_right: MAX effectcount(760) over!!!!(kawano)\n"); + return displayListHead; } if (gMatrixEffectCount < 0) { - rmonPrintf("effectcount < 0 !!!!!!(kawano)\n"); + rmonPrintf("func_80095BD0_wide_right: effectcount < 0 !!!!!!(kawano)\n"); } - goto func_80095BD0_label2; -func_80095BD0_label1: - rmonPrintf("MAX effectcount(760) over!!!!(kawano)\n"); - return displayListHead; -func_80095BD0_label2: - func_80095AE0(&gGfxPool->mtxEffect[gMatrixEffectCount], OTRGetDimensionFromRightEdge(arg2), arg3, arg6, arg7); - gSPMatrix(displayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxEffect[gMatrixEffectCount++]), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + FrameInterpolation_RecordOpenChild("flashing_text_wide_right", TAG_LETTER((uintptr_t)&arg1 << 8) + (arg4 + arg5)); + Mat4 mf; + SetTextMatrix(mf, OTRGetDimensionFromRightEdge(arg2), arg3, arg6, arg7); + //func_80095AE0(&gGfxPool->mtxEffect[gMatrixEffectCount], OTRGetDimensionFromRightEdge(arg2), arg3, arg6, arg7); + + displayListHead = AddTextMatrix(displayListHead, mf); + // gSPMatrix(displayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxEffect[gMatrixEffectCount++]), + // G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gMKLoadTextureTile_4b(displayListHead++, arg1, G_IM_FMT_I, arg4, 0, 0, 0, arg4, arg5, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); switch (arg4) { @@ -2774,7 +2783,9 @@ func_80095BD0_label2: break; } - return func_800959F8(displayListHead, var_a1); + displayListHead = func_800959F8(displayListHead, var_a1); + FrameInterpolation_RecordCloseChild(); + return displayListHead; } // Player select menu character border @@ -8333,6 +8344,7 @@ void pause_menu_item_box_cursor(MenuItem* arg0, Unk_D_800E70A0* arg1) { static float x2, y2, z2; static float x1, y1, z1; + FrameInterpolation_RecordOpenChild("pause_menu_item_box", TAG_OBJECT(arg0)); mtx = GetEffectMatrix(); mtx2 = GetEffectMatrix(); if (arg0->paramf > 1.5) { @@ -8370,6 +8382,7 @@ void pause_menu_item_box_cursor(MenuItem* arg0, Unk_D_800E70A0* arg1) { gDPNoOp(gDisplayListHead++); gDPSetRenderMode(gDisplayListHead++, G_RM_CLD_SURF, G_RM_CLD_SURF2); gSPDisplayList(gDisplayListHead++, D_0D003090); + FrameInterpolation_RecordCloseChild(); } void func_800A69C8(UNUSED MenuItem* arg0) { diff --git a/src/menus.c b/src/menus.c index ce9f0a643..edc56494f 100644 --- a/src/menus.c +++ b/src/menus.c @@ -2010,6 +2010,7 @@ void load_menu_states(s32 menuSelection) { } else { if (GetCup() == GetBattleCup()) { CM_SetCup(GetMushroomCup()); + CM_SetCupIndex(MUSHROOM_CUP); // gCupSelection = MUSHROOM_CUP; } gSubMenuSelection = SUB_MENU_MAP_SELECT_CUP; diff --git a/src/os/guMtxCatL.c b/src/os/guMtxCatL.c index cef956954..1ca1b5a28 100644 --- a/src/os/guMtxCatL.c +++ b/src/os/guMtxCatL.c @@ -31,6 +31,7 @@ */ #include +#include "port/interpolation/FrameInterpolation.h" // void guMtxXFMF(Mtx*, float, float, float, float*, float*, float*); void guMtxCatF(float mf[4][4], float nf[4][4], float res[4][4]); @@ -43,6 +44,7 @@ void guMtxCatL(Mtx* m, Mtx* n, Mtx* res) { guMtxCatF(mf, nf, resf); + FrameInterpolation_RecordMatrixMtxFToMtx((MtxF*)resf, res); guMtxF2L(resf, res); } diff --git a/src/port/interpolation/FrameInterpolation.cpp b/src/port/interpolation/FrameInterpolation.cpp index 836e6c70c..438c10c0a 100644 --- a/src/port/interpolation/FrameInterpolation.cpp +++ b/src/port/interpolation/FrameInterpolation.cpp @@ -7,6 +7,7 @@ #include "port/Engine.h" #include "FrameInterpolation.h" #include "matrix.h" +#include "engine/Matrix.h" extern "C" { #include "math_util.h" @@ -81,7 +82,9 @@ enum class Op { SkinMatrixMtxFToMtx, SetTransformMatrix, SetMatrixTransformation, - SetTranslateRotate + SetTranslateRotate, + SetTextMatrix, + SetMatrixPosRotScaleXY, }; typedef pair label; @@ -140,10 +143,19 @@ union Data { } matrix_mult_4x4; struct { + Mat4* matrix; Vec3fInterp pos; Vec3sInterp orientation; } matrix_pos_rot_xyz; + struct { + Mat4* matrix; + s32 x; + s32 y; + u16 angle; + f32 scale; + } matrix_pos_rot_scale_xy; + struct { Mat4* matrix; Vec3f translation; @@ -208,6 +220,14 @@ union Data { s16 rot; } set_orientation_matrix_data; + struct { + Mat4* matrix; + f32 x; + f32 y; + f32 arg3; + f32 arg4; + } matrix_text; + struct { label key; size_t idx; @@ -254,6 +274,7 @@ struct InterpolateCtx { Mat3 tmp_mat3; Vec3f tmp_vec3f, tmp_vec3f2; Vec3s tmp_vec3s; + int32_t tmp32[2]; MtxF actor_mtx; MtxF* new_replacement(Mtx* addr) { @@ -276,6 +297,10 @@ struct InterpolateCtx { return w * o + step * n; } + s32 lerp_s32(s32 o, s32 n) { + return w * o + step * n; + } + void lerp_vec3s(Vec3s* res, Vec3s o, Vec3s n) { *res[0] = lerp_s16(o[0], n[0]); *res[1] = lerp_s16(o[1], n[1]); @@ -400,7 +425,6 @@ struct InterpolateCtx { break; case Op::MatrixTranslate: - Vec3f temp; temp[0] = lerp(old_op.matrix_translate.b.x, new_op.matrix_translate.b.x); @@ -533,6 +557,27 @@ struct InterpolateCtx { mtxf_translate_rotate(*gInterpolationMatrix, tmp_vec3f, tmp_vec3s); break; } + case Op::SetTextMatrix: { + + tmp_vec3f[0] = lerp(old_op.matrix_text.x, new_op.matrix_text.x); + tmp_vec3f[1] = lerp(old_op.matrix_text.y, new_op.matrix_text.y); + tmp_vec3f[2] = lerp(old_op.matrix_text.arg3, new_op.matrix_text.arg3); + tmp_vec3f2[0] = lerp(old_op.matrix_text.arg4, new_op.matrix_text.arg4); + + SetTextMatrix(*gInterpolationMatrix, tmp_vec3f[0], tmp_vec3f[1], tmp_vec3f[2], tmp_vec3f2[0]); + break; + } + case Op::SetMatrixPosRotScaleXY: { + tmp32[0] = lerp_s32(old_op.matrix_pos_rot_scale_xy.x, new_op.matrix_pos_rot_scale_xy.x); + tmp32[1] = lerp_s32(old_op.matrix_pos_rot_scale_xy.y, new_op.matrix_pos_rot_scale_xy.y); + + tmp_vec3s[0] = lerp_s16(old_op.matrix_pos_rot_scale_xy.angle, new_op.matrix_pos_rot_scale_xy.angle); + + tmp_vec3f[0] = lerp(old_op.matrix_pos_rot_scale_xy.scale, new_op.matrix_pos_rot_scale_xy.scale); + + mtxf_translation_x_y_rotate_z_scale_x_y(*gInterpolationMatrix, tmp32[0], tmp32[1], tmp_vec3s[0], tmp_vec3f[0]); + break; + } } } } @@ -605,6 +650,12 @@ int FrameInterpolation_GetCameraEpoch(void) { return (int) camera_epoch; } +void FrameInterpolation_Record_SetTextMatrix(Mat4* matrix, f32 x, f32 y, f32 arg3, f32 arg4) { + if (!is_recording) + return; + append(Op::SetTextMatrix).matrix_text = {matrix, x, y, arg3, arg4}; +} + void FrameInterpolation_RecordActorPosRotMatrix(void) { if (!is_recording) return; @@ -689,10 +740,16 @@ void FrameInterpolation_RecordCalculateOrientationMatrix(Mat3* dest, f32 x, f32 // Make a template for deref -void FrameInterpolation_RecordMatrixPosRotXYZ(Mat4 out, Vec3f pos, Vec3s orientation) { +void FrameInterpolation_RecordMatrixPosRotXYZ(Mat4* out, Vec3f pos, Vec3s orientation) { if (!is_recording) return; - append(Op::MatrixPosRotXYZ).matrix_pos_rot_xyz = { *((Vec3fInterp*) &pos), *((Vec3sInterp*) &orientation) }; + append(Op::MatrixPosRotXYZ).matrix_pos_rot_xyz = { out, *((Vec3fInterp*) &pos), *((Vec3sInterp*) &orientation) }; +} + +void FrameInterpolation_RecordMatrixPosRotScaleXY(Mat4* matrix, s32 x, s32 y, u16 angle, f32 scale) { + if (!is_recording) + return; + append(Op::SetMatrixPosRotScaleXY).matrix_pos_rot_scale_xy = { matrix, x, y, angle, scale }; } void FrameInterpolation_RecordMatrixMultVec3f(Mat4* matrix, Vec3f src, Vec3f dest) { diff --git a/src/port/interpolation/FrameInterpolation.h b/src/port/interpolation/FrameInterpolation.h index c59743681..30187c808 100644 --- a/src/port/interpolation/FrameInterpolation.h +++ b/src/port/interpolation/FrameInterpolation.h @@ -18,7 +18,7 @@ extern "C" { #define TAG_ITEM_ADDR(x) ((u32) 0x10000000 | (u32)x) #define TAG_SMOKE_DUST(x) ((u32) 0x20000000 | (u32) (x)) -#define TAG_LETTER(x) ((u32)0x30000000 | (u32) (x)) +#define TAG_LETTER(x) ((u32)0x30000000 | (u32) (uintptr_t) (x)) #define TAG_OBJECT(x) ((u32)0x40000000 | (u32) (uintptr_t) (x)) void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate); @@ -39,7 +39,11 @@ int FrameInterpolation_GetCameraEpoch(void); void FrameInterpolation_RecordActorPosRotMatrix(void); -void FrameInterpolation_RecordMatrixPosRotXYZ(Mat4 out, Vec3f pos, Vec3s orientation); +void FrameInterpolation_RecordMatrixPosRotXYZ(Mat4* out, Vec3f pos, Vec3s orientation); + +void FrameInterpolation_RecordMatrixPosRotScaleXY(Mat4* matrix, s32 x, s32 y, u16 angle, f32 scale); + +void FrameInterpolation_Record_SetTextMatrix(Mat4* matrix, f32 x, f32 y, f32 arg3, f32 arg4); void FrameInterpolation_RecordMatrixPush(Mat4* matrix); diff --git a/src/racing/actors.c b/src/racing/actors.c index 137e3556e..0d6bd0ee4 100644 --- a/src/racing/actors.c +++ b/src/racing/actors.c @@ -2429,8 +2429,17 @@ void render_course_actors(struct UnkStruct_800DC5EC* arg0) { struct Actor* actor; UNUSED Vec3f sp4C = { 0.0f, 5.0f, 10.0f }; - f32 sp48 = sins(camera->rot[1] - 0x8000); // unk26; - f32 temp_f0 = coss(camera->rot[1] - 0x8000); + + // Freecam rotY is reversed in the engine for whatever reason + f32 sp48 = 0; + f32 temp_f0 = 0; + if (CVarGetInteger("gFreecam", 0) == true) { + sp48 = sins(-camera->rot[1] - 0x8000); + temp_f0 = coss(-camera->rot[1] - 0x8000); + } else { + sp48 = sins(camera->rot[1] - 0x8000); + temp_f0 = coss(camera->rot[1] - 0x8000); + } sBillBoardMtx[0][0] = temp_f0; sBillBoardMtx[0][2] = -sp48; diff --git a/src/render_objects.c b/src/render_objects.c index 7aa06dcaf..e0097750e 100644 --- a/src/render_objects.c +++ b/src/render_objects.c @@ -3527,7 +3527,11 @@ void func_80051ABC(s16 arg0, s32 arg1) { for (var_s0 = 0; var_s0 < D_8018D1F0; var_s0++) { objectIndex = D_8018CC80[arg1 + var_s0]; object = &gObjectList[objectIndex]; + FrameInterpolation_RecordOpenChild("stars_cloud", TAG_OBJECT(object)); + func_800519D4(objectIndex, object->unk_09C, arg0 - object->unk_09E); + FrameInterpolation_RecordCloseChild(); + } } else { func_8004B6C4(255, 255, 255);