diff --git a/lib/rt64 b/lib/rt64 index 7e2479d..bdd9ee8 160000 --- a/lib/rt64 +++ b/lib/rt64 @@ -1 +1 @@ -Subproject commit 7e2479d6b63ab4447635fadbb16ce3cf416afb00 +Subproject commit bdd9ee86c0b058f8313493b25193ea610f481b90 diff --git a/patches/actor_transform_tagging.c b/patches/actor_transform_tagging.c index 7bc50eb..81b42d4 100644 --- a/patches/actor_transform_tagging.c +++ b/patches/actor_transform_tagging.c @@ -84,7 +84,7 @@ Gfx* push_limb_matrix_group(Gfx* dlist, Actor* actor, u32 limb_index) { if (actor != NULL) { u32 cur_transform_id = actor_transform_id(actor); if (actor_get_interpolation_skipped(actor)) { - gEXMatrixGroupDecomposedSkip(dlist++, cur_transform_id + limb_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(dlist++, cur_transform_id + limb_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { gEXMatrixGroupDecomposedNormal(dlist++, cur_transform_id + limb_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); } @@ -97,7 +97,7 @@ Gfx* push_post_limb_matrix_group(Gfx* dlist, Actor* actor, u32 limb_index) { if (actor != NULL) { u32 cur_transform_id = actor_transform_id(actor); if (actor_get_interpolation_skipped(actor)) { - gEXMatrixGroupDecomposedSkip(dlist++, cur_transform_id + limb_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(dlist++, cur_transform_id + limb_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { gEXMatrixGroupDecomposedNormal(dlist++, cur_transform_id + limb_index + ACTOR_TRANSFORM_LIMB_COUNT, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); } @@ -110,7 +110,7 @@ Gfx* push_skin_limb_matrix_group(Gfx* dlist, Actor* actor, u32 limb_index) { if (actor != NULL) { u32 cur_transform_id = actor_transform_id(actor); if (actor_get_interpolation_skipped(actor)) { - gEXMatrixGroupDecomposedSkip(dlist++, cur_transform_id + limb_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(dlist++, cur_transform_id + limb_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { gEXMatrixGroupDecomposedVerts(dlist++, cur_transform_id + limb_index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); } diff --git a/patches/billboard_tagging.c b/patches/billboard_tagging.c new file mode 100644 index 0000000..1958e68 --- /dev/null +++ b/patches/billboard_tagging.c @@ -0,0 +1,1024 @@ +#include "patches.h" +#include "transform_ids.h" +#include "play_patches.h" + +// Needs to copy billboard state +// Matrix_Push + +// Needs to restore billboard state +// Matrix_Pop + +// Can set or reset billboard state +// Matrix_Put +// Matrix_ReplaceRotation +// Matrix_MtxFCopy +// Matrix_Mult + +// Can only reset billboard state +// Matrix_Translate in NEW +// Matrix_Scale in NEW +// Matrix_RotateXS in NEW +// Matrix_RotateXF in NEW +// Matrix_RotateXFNew +// Matrix_RotateYS in NEW +// Matrix_RotateYF in NEW +// Matrix_RotateZS in NEW +// Matrix_RotateZF in NEW +// Matrix_RotateZYX in NEW +// Matrix_TranslateRotateZYX in NEW +// Matrix_SetTranslateRotateYXZ +// Matrix_RotateAxisF in NEW +// Matrix_RotateAxisS in NEW + +#define MATRIX_STACK_SIZE 20 + +MtxF* play_billboard_matrix; +u8 matrix_stack_billboard_states[MATRIX_STACK_SIZE] = {0}; +u8* current_billboard_state; + +#define MAX_TRACKED_BILLBOARDS 2048 +Mtx* tracked_billboard_matrices[MAX_TRACKED_BILLBOARDS] = {0}; +u32 tracked_billboard_matrix_count = 0; + +void edit_billboard_groups(PlayState* play) { + OPEN_DISPS(play->state.gfxCtx); + + if (camera_was_skipped()) { + // Skip rotation for the main billboard matrix. + gEXEditGroupByAddress(POLY_XLU_DISP++, play->billboardMtx, G_EX_INTERPOLATE_DECOMPOSE, G_MTX_PUSH, G_MTX_MODELVIEW, + G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, + G_EX_ORDER_LINEAR); + // Skip rotation for any additional tracked billboard matrices. + for (u32 i = 0; i < tracked_billboard_matrix_count; i++) { + gEXEditGroupByAddress(POLY_XLU_DISP++, tracked_billboard_matrices[i], G_EX_INTERPOLATE_DECOMPOSE, G_MTX_PUSH, G_MTX_MODELVIEW, + G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, + G_EX_ORDER_LINEAR); + recomp_printf("Skipped matrix %08X\n", (u32)tracked_billboard_matrices[i]); + } + } + + tracked_billboard_matrix_count = 0; + + CLOSE_DISPS(play->state.gfxCtx); +} + +Mtx* Matrix_NewMtx(GraphicsContext* gfxCtx) { + Mtx* ret = Matrix_ToMtx(GRAPH_ALLOC(gfxCtx, sizeof(Mtx))); + + if (*current_billboard_state) { + if (tracked_billboard_matrix_count >= MAX_TRACKED_BILLBOARDS) { + recomp_printf("Ran out of billboard matrix tracking space!\n"); + } + else { + tracked_billboard_matrices[tracked_billboard_matrix_count] = ret; + tracked_billboard_matrix_count++; + } + } + + return ret; +} + +void Matrix_Init(GameState* gameState) { + sMatrixStack = THA_AllocTailAlign16(&gameState->tha, MATRIX_STACK_SIZE * sizeof(MtxF)); + sCurrentMatrix = sMatrixStack; + + // @recomp Reset the matrix stack billboard states. + Lib_MemSet(matrix_stack_billboard_states, 0, sizeof(matrix_stack_billboard_states)); + current_billboard_state = matrix_stack_billboard_states; + + // @recomp Reset the state's billboard matrix pointer. + play_billboard_matrix = NULL; + tracked_billboard_matrix_count = 0; +} + +void matrix_play_update(PlayState* play) { + play_billboard_matrix = &play->billboardMtxF; +} + +void Matrix_Push(void) { + MtxF* prev = sCurrentMatrix; + + sCurrentMatrix++; + Matrix_MtxFCopy(sCurrentMatrix, prev); + + // @recomp Push a new matrix stack billboard state and copy the previous. + u8* prev_billboard = current_billboard_state; + current_billboard_state++; + *current_billboard_state = *prev_billboard; +} + +void Matrix_Pop(void) { + sCurrentMatrix--; + // @recomp Pop the matrix stack billboard state. + current_billboard_state--; +} + +void Matrix_Put(MtxF* src) { + Matrix_MtxFCopy(sCurrentMatrix, src); + + // @recomp Update the current billboard state. + *current_billboard_state = (src == play_billboard_matrix); +} + +void Matrix_ReplaceRotation(MtxF* mf) { + MtxF* cmf = sCurrentMatrix; + f32 acc; + f32 component; + f32 curColNorm; + + // compute the Euclidean norm of the first column of the current matrix + acc = cmf->xx; + acc *= acc; + component = cmf->yx; + acc += SQ(component); + component = cmf->zx; + acc += SQ(component); + curColNorm = sqrtf(acc); + + cmf->xx = mf->xx * curColNorm; + cmf->yx = mf->yx * curColNorm; + cmf->zx = mf->zx * curColNorm; + + // second column + acc = cmf->xy; + acc *= acc; + component = cmf->yy; + acc += SQ(component); + component = cmf->zy; + acc += SQ(component); + curColNorm = sqrtf(acc); + + cmf->xy = mf->xy * curColNorm; + cmf->yy = mf->yy * curColNorm; + cmf->zy = mf->zy * curColNorm; + + // third column + acc = cmf->xz; + acc *= acc; + component = cmf->yz; + acc += SQ(component); + component = cmf->zz; + acc += SQ(component); + curColNorm = sqrtf(acc); + + cmf->xz = mf->xz * curColNorm; + cmf->yz = mf->yz * curColNorm; + cmf->zz = mf->zz * curColNorm; + + // @recomp Update the current billboard state. + *current_billboard_state = (mf == play_billboard_matrix); +} + +void Matrix_Mult(MtxF* mf, MatrixMode mode) { + MtxF* cmf = Matrix_GetCurrent(); + + if (mode == MTXMODE_APPLY) { + SkinMatrix_MtxFMtxFMult(cmf, mf, cmf); + + // @recomp Update the current billboard state. Use or because multiplying another matrix won't remove the current billboarded status of the stack. + *current_billboard_state = *current_billboard_state || (mf == play_billboard_matrix); + } else { + Matrix_MtxFCopy(sCurrentMatrix, mf); + // @recomp Update the current billboard state. + *current_billboard_state = (mf == play_billboard_matrix); + } +} + +void Matrix_Translate(f32 x, f32 y, f32 z, MatrixMode mode) { + MtxF* cmf = sCurrentMatrix; + f32 tempX; + f32 tempY; + + if (mode == MTXMODE_APPLY) { + tempX = cmf->xx; + tempY = cmf->xy; + cmf->xw += tempX * x + tempY * y + cmf->xz * z; + tempX = cmf->yx; + tempY = cmf->yy; + cmf->yw += tempX * x + tempY * y + cmf->yz * z; + tempX = cmf->zx; + tempY = cmf->zy; + cmf->zw += tempX * x + tempY * y + cmf->zz * z; + tempX = cmf->wx; + tempY = cmf->wy; + cmf->ww += tempX * x + tempY * y + cmf->wz * z; + } else { + SkinMatrix_SetTranslate(cmf, x, y, z); + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_Scale(f32 x, f32 y, f32 z, MatrixMode mode) { + MtxF* cmf = sCurrentMatrix; + + if (mode == MTXMODE_APPLY) { + cmf->xx *= x; + cmf->yx *= x; + cmf->zx *= x; + cmf->xy *= y; + cmf->yy *= y; + cmf->zy *= y; + cmf->xz *= z; + cmf->yz *= z; + cmf->zz *= z; + cmf->wx *= x; + cmf->wy *= y; + cmf->wz *= z; + } else { + SkinMatrix_SetScale(cmf, x, y, z); + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_RotateXS(s16 x, MatrixMode mode) { + MtxF* cmf; + f32 sin; + f32 cos; + f32 tempY; + f32 tempZ; + + if (mode == MTXMODE_APPLY) { + if (x != 0) { + cmf = sCurrentMatrix; + + sin = Math_SinS(x); + cos = Math_CosS(x); + + tempY = cmf->xy; + tempZ = cmf->xz; + cmf->xy = tempY * cos + tempZ * sin; + cmf->xz = tempZ * cos - tempY * sin; + + tempY = cmf->yy; + tempZ = cmf->yz; + cmf->yy = tempY * cos + tempZ * sin; + cmf->yz = tempZ * cos - tempY * sin; + + tempY = cmf->zy; + tempZ = cmf->zz; + cmf->zy = tempY * cos + tempZ * sin; + cmf->zz = tempZ * cos - tempY * sin; + + tempY = cmf->wy; + tempZ = cmf->wz; + cmf->wy = tempY * cos + tempZ * sin; + cmf->wz = tempZ * cos - tempY * sin; + } + } else { + cmf = sCurrentMatrix; + + if (x != 0) { + sin = Math_SinS(x); + cos = Math_CosS(x); + } else { + sin = 0.0f; + cos = 1.0f; + } + + cmf->yx = 0.0f; + cmf->zx = 0.0f; + cmf->wx = 0.0f; + cmf->xy = 0.0f; + cmf->wy = 0.0f; + cmf->xz = 0.0f; + cmf->wz = 0.0f; + cmf->xw = 0.0f; + cmf->yw = 0.0f; + cmf->zw = 0.0f; + cmf->xx = 1.0f; + cmf->ww = 1.0f; + cmf->yy = cos; + cmf->zz = cos; + cmf->zy = sin; + cmf->yz = -sin; + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_RotateXF(f32 x, MatrixMode mode) { + MtxF* cmf; + f32 sin; + f32 cos; + f32 tempY; + f32 tempZ; + f32 zero = 0.0; + f32 one = 1.0; + + if (mode == MTXMODE_APPLY) { + if (x != 0) { + cmf = sCurrentMatrix; + + sin = sinf(x); + cos = cosf(x); + + tempY = cmf->xy; + tempZ = cmf->xz; + cmf->xy = tempY * cos + tempZ * sin; + cmf->xz = tempZ * cos - tempY * sin; + + tempY = cmf->yy; + tempZ = cmf->yz; + cmf->yy = tempY * cos + tempZ * sin; + cmf->yz = tempZ * cos - tempY * sin; + + tempY = cmf->zy; + tempZ = cmf->zz; + cmf->zy = tempY * cos + tempZ * sin; + cmf->zz = tempZ * cos - tempY * sin; + + tempY = cmf->wy; + tempZ = cmf->wz; + cmf->wy = tempY * cos + tempZ * sin; + cmf->wz = tempZ * cos - tempY * sin; + } + } else { + cmf = sCurrentMatrix; + + if (x != 0) { + sin = sinf(x); + cos = cosf(x); + } else { + sin = zero; + cos = one; + } + + cmf->xx = one; + cmf->yx = zero; + cmf->zx = zero; + cmf->wx = zero; + cmf->xy = zero; + cmf->yy = cos; + cmf->zy = sin; + cmf->wy = zero; + cmf->xz = zero; + cmf->yz = -sin; + cmf->zz = cos; + cmf->wz = zero; + cmf->xw = zero; + cmf->yw = zero; + cmf->zw = zero; + cmf->ww = one; + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_RotateXFNew(f32 x) { + MtxF* cmf = sCurrentMatrix; + s32 pad[2]; + f32 sin; + f32 cos; + + cmf->xx = 1.0f; + cmf->yx = 0.0f; + cmf->zx = 0.0f; + cmf->wx = 0.0f; + cmf->xy = 0.0f; + cmf->wy = 0.0f; + cmf->xz = 0.0f; + cmf->wz = 0.0f; + cmf->xw = 0.0f; + cmf->yw = 0.0f; + cmf->zw = 0.0f; + cmf->ww = 1.0f; + + if (x != 0.0f) { + sin = sinf(x); + cos = cosf(x); + + cmf->yy = cos; + cmf->zz = cos; + cmf->yz = -sin; + cmf->zy = sin; + } else { + cmf->yy = 1.0f; + cmf->zy = 0.0f; + cmf->yz = 0.0f; + cmf->zz = 1.0f; + } + + // @recomp Clear the current billboard state. + *current_billboard_state = false; +} +void Matrix_RotateYS(s16 y, MatrixMode mode) { + MtxF* cmf; + f32 sin; + f32 cos; + f32 tempX; + f32 tempZ; + + if (mode == MTXMODE_APPLY) { + if (y != 0) { + cmf = sCurrentMatrix; + + sin = Math_SinS(y); + cos = Math_CosS(y); + + tempX = cmf->xx; + tempZ = cmf->xz; + cmf->xx = tempX * cos - tempZ * sin; + cmf->xz = tempX * sin + tempZ * cos; + + tempX = cmf->yx; + tempZ = cmf->yz; + cmf->yx = tempX * cos - tempZ * sin; + cmf->yz = tempX * sin + tempZ * cos; + + tempX = cmf->zx; + tempZ = cmf->zz; + cmf->zx = tempX * cos - tempZ * sin; + cmf->zz = tempX * sin + tempZ * cos; + + tempX = cmf->wx; + tempZ = cmf->wz; + cmf->wx = tempX * cos - tempZ * sin; + cmf->wz = tempX * sin + tempZ * cos; + } + } else { + cmf = sCurrentMatrix; + + if (y != 0) { + sin = Math_SinS(y); + cos = Math_CosS(y); + } else { + sin = 0.0f; + cos = 1.0f; + } + + cmf->yx = 0.0f; + cmf->wx = 0.0f; + cmf->xy = 0.0f; + cmf->zy = 0.0f; + cmf->wy = 0.0f; + cmf->yz = 0.0f; + cmf->wz = 0.0f; + cmf->xw = 0.0f; + cmf->yw = 0.0f; + cmf->zw = 0.0f; + cmf->yy = 1.0f; + cmf->ww = 1.0f; + cmf->xx = cos; + cmf->zz = cos; + cmf->zx = -sin; + cmf->xz = sin; + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_RotateYF(f32 y, MatrixMode mode) { + MtxF* cmf; + f32 sin; + f32 cos; + f32 tempX; + f32 tempZ; + f32 zero = 0.0; + f32 one = 1.0; + + if (mode == MTXMODE_APPLY) { + if (y != 0.0f) { + cmf = sCurrentMatrix; + + sin = sinf(y); + cos = cosf(y); + + tempX = cmf->xx; + tempZ = cmf->xz; + cmf->xx = tempX * cos - tempZ * sin; + cmf->xz = tempX * sin + tempZ * cos; + + tempX = cmf->yx; + tempZ = cmf->yz; + cmf->yx = tempX * cos - tempZ * sin; + cmf->yz = tempX * sin + tempZ * cos; + + tempX = cmf->zx; + tempZ = cmf->zz; + cmf->zx = tempX * cos - tempZ * sin; + cmf->zz = tempX * sin + tempZ * cos; + + tempX = cmf->wx; + tempZ = cmf->wz; + cmf->wx = tempX * cos - tempZ * sin; + cmf->wz = tempX * sin + tempZ * cos; + } + } else { + cmf = sCurrentMatrix; + + if (y != 0.0f) { + sin = sinf(y); + cos = cosf(y); + } else { + cos = one; + sin = zero; + } + + cmf->yx = zero; + cmf->wx = zero; + cmf->xy = zero; + cmf->zy = zero; + cmf->wy = zero; + cmf->yz = zero; + cmf->wz = zero; + cmf->xw = zero; + cmf->yw = zero; + cmf->zw = zero; + cmf->yy = one; + cmf->ww = one; + cmf->xx = cos; + cmf->zz = cos; + cmf->zx = -sin; + cmf->xz = sin; + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_RotateZS(s16 z, MatrixMode mode) { + MtxF* cmf; + f32 sin; + f32 cos; + f32 tempX; + f32 tempY; + f32 zero = 0.0; + f32 one = 1.0; + + if (mode == MTXMODE_APPLY) { + if (z != 0) { + cmf = sCurrentMatrix; + + sin = Math_SinS(z); + cos = Math_CosS(z); + + tempX = cmf->xx; + tempY = cmf->xy; + cmf->xx = tempX * cos + tempY * sin; + cmf->xy = tempY * cos - tempX * sin; + + tempX = cmf->yx; + tempY = cmf->yy; + cmf->yx = tempX * cos + tempY * sin; + cmf->yy = tempY * cos - tempX * sin; + + tempX = cmf->zx; + tempY = cmf->zy; + cmf->zx = tempX * cos + tempY * sin; + cmf->zy = tempY * cos - tempX * sin; + + tempX = cmf->wx; + tempY = cmf->wy; + cmf->wx = tempX * cos + tempY * sin; + cmf->wy = tempY * cos - tempX * sin; + } + } else { + cmf = sCurrentMatrix; + + if (z != 0) { + sin = Math_SinS(z); + cos = Math_CosS(z); + } else { + sin = zero; + cos = one; + } + + cmf->zx = zero; + cmf->wx = zero; + cmf->zy = zero; + cmf->wy = zero; + cmf->xz = zero; + cmf->yz = zero; + cmf->wz = zero; + cmf->xw = zero; + cmf->yw = zero; + cmf->zw = zero; + cmf->zz = one; + cmf->ww = one; + cmf->xx = cos; + cmf->yy = cos; + cmf->yx = sin; + cmf->xy = -sin; + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_RotateZF(f32 z, MatrixMode mode) { + MtxF* cmf; + f32 sin; + f32 cos; + f32 tempX; + f32 tempY; + + if (mode == MTXMODE_APPLY) { + if (z != 0) { + cmf = sCurrentMatrix; + + sin = sinf(z); + cos = cosf(z); + + tempX = cmf->xx; + tempY = cmf->xy; + cmf->xx = tempX * cos + tempY * sin; + cmf->xy = tempY * cos - tempX * sin; + + tempX = cmf->yx; + tempY = cmf->yy; + cmf->yx = tempX * cos + tempY * sin; + cmf->yy = tempY * cos - tempX * sin; + + tempX = cmf->zx; + tempY = cmf->zy; + cmf->zx = tempX * cos + tempY * sin; + cmf->zy = tempY * cos - tempX * sin; + + tempX = cmf->wx; + tempY = cmf->wy; + cmf->wx = tempX * cos + tempY * sin; + cmf->wy = tempY * cos - tempX * sin; + } + } else { + cmf = sCurrentMatrix; + + if (z != 0) { + sin = sinf(z); + cos = cosf(z); + } else { + sin = 0.0f; + cos = 1.0f; + } + + cmf->zx = 0.0f; + cmf->wx = 0.0f; + cmf->zy = 0.0f; + cmf->wy = 0.0f; + cmf->xz = 0.0f; + cmf->yz = 0.0f; + cmf->wz = 0.0f; + cmf->xw = 0.0f; + cmf->yw = 0.0f; + cmf->zw = 0.0f; + cmf->zz = 1.0f; + cmf->ww = 1.0f; + cmf->xx = cos; + cmf->yy = cos; + cmf->yx = sin; + cmf->xy = -sin; + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_RotateZYX(s16 x, s16 y, s16 z, MatrixMode mode) { + MtxF* cmf = sCurrentMatrix; + f32 temp1; + f32 temp2; + f32 sin; + f32 cos; + + if (mode == MTXMODE_APPLY) { + if (z != 0) { // Added in MM, OoT always follows the nonzero path + sin = Math_SinS(z); + cos = Math_CosS(z); + + temp1 = cmf->xx; + temp2 = cmf->xy; + cmf->xx = temp1 * cos + temp2 * sin; + cmf->xy = temp2 * cos - temp1 * sin; + + temp1 = cmf->yx; + temp2 = cmf->yy; + cmf->yx = temp1 * cos + temp2 * sin; + cmf->yy = temp2 * cos - temp1 * sin; + + temp1 = cmf->zx; + temp2 = cmf->zy; + cmf->zx = temp1 * cos + temp2 * sin; + cmf->zy = temp2 * cos - temp1 * sin; + + temp1 = cmf->wx; + temp2 = cmf->wy; + cmf->wx = temp1 * cos + temp2 * sin; + cmf->wy = temp2 * cos - temp1 * sin; + } + + if (y != 0) { + sin = Math_SinS(y); + cos = Math_CosS(y); + + temp1 = cmf->xx; + temp2 = cmf->xz; + cmf->xx = temp1 * cos - temp2 * sin; + cmf->xz = temp1 * sin + temp2 * cos; + + temp1 = cmf->yx; + temp2 = cmf->yz; + cmf->yx = temp1 * cos - temp2 * sin; + cmf->yz = temp1 * sin + temp2 * cos; + + temp1 = cmf->zx; + temp2 = cmf->zz; + cmf->zx = temp1 * cos - temp2 * sin; + cmf->zz = temp1 * sin + temp2 * cos; + + temp1 = cmf->wx; + temp2 = cmf->wz; + cmf->wx = temp1 * cos - temp2 * sin; + cmf->wz = temp1 * sin + temp2 * cos; + } + + if (x != 0) { + sin = Math_SinS(x); + cos = Math_CosS(x); + + temp1 = cmf->xy; + temp2 = cmf->xz; + cmf->xy = temp1 * cos + temp2 * sin; + cmf->xz = temp2 * cos - temp1 * sin; + + temp1 = cmf->yy; + temp2 = cmf->yz; + cmf->yy = temp1 * cos + temp2 * sin; + cmf->yz = temp2 * cos - temp1 * sin; + + temp1 = cmf->zy; + temp2 = cmf->zz; + cmf->zy = temp1 * cos + temp2 * sin; + cmf->zz = temp2 * cos - temp1 * sin; + + temp1 = cmf->wy; + temp2 = cmf->wz; + cmf->wy = temp1 * cos + temp2 * sin; + cmf->wz = temp2 * cos - temp1 * sin; + } + } else { + SkinMatrix_SetRotateRPY(cmf, x, y, z); + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_SetTranslateRotateYXZ(f32 x, f32 y, f32 z, Vec3s* rot) { + MtxF* cmf = sCurrentMatrix; + f32 sinY = Math_SinS(rot->y); + f32 cosY = Math_CosS(rot->y); + f32 cosTemp; + f32 sinTemp; + + cmf->xx = cosY; + cmf->zx = -sinY; + cmf->xw = x; + cmf->yw = y; + cmf->zw = z; + cmf->wx = 0.0f; + cmf->wy = 0.0f; + cmf->wz = 0.0f; + cmf->ww = 1.0f; + + if (rot->x != 0) { + sinTemp = Math_SinS(rot->x); + cosTemp = Math_CosS(rot->x); + + cmf->zz = cosY * cosTemp; + cmf->zy = cosY * sinTemp; + cmf->xz = sinY * cosTemp; + cmf->xy = sinY * sinTemp; + cmf->yz = -sinTemp; + cmf->yy = cosTemp; + } else { + cmf->zz = cosY; + cmf->xz = sinY; + cmf->yz = 0.0f; + cmf->zy = 0.0f; + cmf->xy = 0.0f; + cmf->yy = 1.0f; + } + + if (rot->z != 0) { + sinTemp = Math_SinS(rot->z); + cosTemp = Math_CosS(rot->z); + + sinY = cmf->xx; + cosY = cmf->xy; + cmf->xx = sinY * cosTemp + cosY * sinTemp; + cmf->xy = cosY * cosTemp - sinY * sinTemp; + + sinY = cmf->zx; + cosY = cmf->zy; + cmf->zx = sinY * cosTemp + cosY * sinTemp; + cmf->zy = cosY * cosTemp - sinY * sinTemp; + + cosY = cmf->yy; + cmf->yx = cosY * sinTemp; + cmf->yy = cosY * cosTemp; + } else { + cmf->yx = 0.0f; + } + + // @recomp Clear the current billboard state. + *current_billboard_state = false; +} + +void Matrix_RotateAxisF(f32 angle, Vec3f* axis, MatrixMode mode) { + MtxF* cmf; + f32 sin; + f32 cos; + f32 versin; + f32 temp1; + f32 temp2; + f32 temp3; + f32 temp4; + f32 temp5; + + if (mode == MTXMODE_APPLY) { + if (angle != 0) { + cmf = sCurrentMatrix; + + sin = sinf(angle); + cos = cosf(angle); + + temp1 = cmf->xx; + temp2 = cmf->xy; + temp3 = cmf->xz; + temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos); + cmf->xx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y); + cmf->xy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z); + cmf->xz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x); + + temp1 = cmf->yx; + temp2 = cmf->yy; + temp3 = cmf->yz; + temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos); + cmf->yx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y); + cmf->yy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z); + cmf->yz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x); + + temp1 = cmf->zx; + temp2 = cmf->zy; + temp3 = cmf->zz; + temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos); + cmf->zx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y); + cmf->zy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z); + cmf->zz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x); + } + } else { + cmf = sCurrentMatrix; + + if (angle != 0) { + sin = sinf(angle); + cos = cosf(angle); + versin = 1.0f - cos; + + cmf->xx = axis->x * axis->x * versin + cos; + cmf->yy = axis->y * axis->y * versin + cos; + cmf->zz = axis->z * axis->z * versin + cos; + + if (0) {} + + temp2 = axis->x * versin * axis->y; + temp3 = axis->z * sin; + cmf->yx = temp2 + temp3; + cmf->xy = temp2 - temp3; + + temp2 = axis->x * versin * axis->z; + temp3 = axis->y * sin; + cmf->zx = temp2 - temp3; + cmf->xz = temp2 + temp3; + + temp2 = axis->y * versin * axis->z; + temp3 = axis->x * sin; + cmf->zy = temp2 + temp3; + cmf->yz = temp2 - temp3; + + cmf->wx = cmf->wy = cmf->wz = cmf->xw = cmf->yw = cmf->zw = 0.0f; + cmf->ww = 1.0f; + } else { + cmf->xx = 1.0f; + cmf->yx = 0.0f; + cmf->zx = 0.0f; + cmf->wx = 0.0f; + cmf->xy = 0.0f; + cmf->yy = 1.0f; + cmf->zy = 0.0f; + cmf->wy = 0.0f; + cmf->xz = 0.0f; + cmf->yz = 0.0f; + cmf->zz = 1.0f; + cmf->wz = 0.0f; + cmf->xw = 0.0f; + cmf->yw = 0.0f; + cmf->zw = 0.0f; + cmf->ww = 1.0f; + } + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} + +void Matrix_RotateAxisS(s16 angle, Vec3f* axis, MatrixMode mode) { + MtxF* cmf; + f32 cos; + f32 sin; + f32 versin; + f32 temp1; + f32 temp2; + f32 temp3; + f32 temp4; + + if (mode == MTXMODE_APPLY) { + if (angle != 0) { + cmf = sCurrentMatrix; + + sin = Math_SinS(angle); + cos = Math_CosS(angle); + + temp1 = cmf->xx; + temp2 = cmf->xy; + temp3 = cmf->xz; + temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos); + cmf->xx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y); + cmf->xy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z); + cmf->xz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x); + + temp1 = cmf->yx; + temp2 = cmf->yy; + temp3 = cmf->yz; + temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos); + cmf->yx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y); + cmf->yy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z); + cmf->yz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x); + + temp1 = cmf->zx; + temp2 = cmf->zy; + temp3 = cmf->zz; + temp4 = (axis->x * temp1 + axis->y * temp2 + axis->z * temp3) * (1.0f - cos); + cmf->zx = temp1 * cos + axis->x * temp4 + sin * (temp2 * axis->z - temp3 * axis->y); + cmf->zy = temp2 * cos + axis->y * temp4 + sin * (temp3 * axis->x - temp1 * axis->z); + cmf->zz = temp3 * cos + axis->z * temp4 + sin * (temp1 * axis->y - temp2 * axis->x); + } + } else { + cmf = sCurrentMatrix; + + if (angle != 0) { + sin = Math_SinS(angle); + cos = Math_CosS(angle); + versin = 1.0f - cos; + + cmf->xx = axis->x * axis->x * versin + cos; + cmf->yy = axis->y * axis->y * versin + cos; + cmf->zz = axis->z * axis->z * versin + cos; + + if (0) {} + + temp2 = axis->x * versin * axis->y; + temp3 = axis->z * sin; + cmf->yx = temp2 + temp3; + cmf->xy = temp2 - temp3; + + temp2 = axis->x * versin * axis->z; + temp3 = axis->y * sin; + cmf->zx = temp2 - temp3; + cmf->xz = temp2 + temp3; + + temp2 = axis->y * versin * axis->z; + temp3 = axis->x * sin; + cmf->zy = temp2 + temp3; + cmf->yz = temp2 - temp3; + + cmf->wx = cmf->wy = cmf->wz = cmf->xw = cmf->yw = cmf->zw = 0.0f; + cmf->ww = 1.0f; + } else { + cmf->xx = 1.0f; + cmf->yx = 0.0f; + cmf->zx = 0.0f; + cmf->wx = 0.0f; + cmf->xy = 0.0f; + cmf->yy = 1.0f; + cmf->zy = 0.0f; + cmf->wy = 0.0f; + cmf->xz = 0.0f; + cmf->yz = 0.0f; + cmf->zz = 1.0f; + cmf->wz = 0.0f; + cmf->xw = 0.0f; + cmf->yw = 0.0f; + cmf->zw = 0.0f; + cmf->ww = 1.0f; + } + + // @recomp Clear the current billboard state. + *current_billboard_state = false; + } +} diff --git a/patches/effect_transform_tagging.c b/patches/effect_transform_tagging.c index 3fc8b84..e9e1f03 100644 --- a/patches/effect_transform_tagging.c +++ b/patches/effect_transform_tagging.c @@ -2,6 +2,7 @@ #include "transform_ids.h" #include "overlays/actors/ovl_En_Test7/z_en_test7.h" #include "overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h" +#include "overlays/actors/ovl_Eff_Stk/z_eff_stk.h" #include "z64effect.h" // Decomp renames, TODO update decomp and remove these @@ -304,7 +305,7 @@ void func_808DD3C8(Actor* thisx, PlayState* play2) { // @recomp Check if the particle's interpolation should be skipped this frame. if (particle_skipped(this->unk_14C[i])) { // @recomp Tag the particle's transform to skip interpolation. - gEXMatrixGroupDecomposedSkip(POLY_XLU_DISP++, actor_transform_id(thisx) + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipPosRot(POLY_XLU_DISP++, actor_transform_id(thisx) + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { // @recomp Tag the particle's matrix to interpolate normally. @@ -458,3 +459,49 @@ void Effect_DrawAll(GraphicsContext* gfxCtx) { pop_effect_tag(gfxCtx); } } + +extern Gfx object_stk2_DL_008920[]; +extern Gfx object_stk2_DL_008A38[]; +extern AnimatedMaterial object_stk2_Matanimheader_009F60[]; + +void EffStk_Draw(Actor* thisx, PlayState* play) { + EffStk* this = (EffStk*)thisx; + s32 pad; + Camera* activeCam = GET_ACTIVE_CAM(play); + Vec3f eye = activeCam->eye; + Vec3f quakeOffset; + + quakeOffset = Camera_GetQuakeOffset(activeCam); + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + Matrix_Translate(eye.x + quakeOffset.x, eye.y + quakeOffset.y, eye.z + quakeOffset.z, MTXMODE_NEW); + Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_Translate(0.0f, 0.0f, this->unk148, MTXMODE_APPLY); + + Mtx* mtx = Matrix_NewMtx(play->state.gfxCtx); + recomp_printf("EffStk_Draw matrix: %08X\n", (u32)mtx); + + // @recomp Tag the transform. Do not allow edits as this will get edited by the billboard detection and we'll want to skip position during a camera cut too. + if (camera_was_skipped()) { + gEXMatrixGroupDecomposedSkipPosRot(POLY_XLU_DISP++, actor_transform_id(thisx), G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + recomp_printf(" Skipped EffStk_Draw matrix\n"); + } + else { + gEXMatrixGroupDecomposedNormal(POLY_XLU_DISP++, actor_transform_id(thisx), G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + } + + gSPMatrix(POLY_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + AnimatedMat_DrawAlphaStep(play, Lib_SegmentedToVirtual(object_stk2_Matanimheader_009F60), 1.0f, this->unk144); + gDPSetColorDither(POLY_XLU_DISP++, G_CD_NOISE); + gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_NOISE); + gSPDisplayList(POLY_XLU_DISP++, object_stk2_DL_008920); + gSPDisplayList(POLY_XLU_DISP++, object_stk2_DL_008A38); + + // @recomp Tag the transform. + gEXPopMatrixGroup(POLY_XLU_DISP++, G_MTX_MODELVIEW); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/patches/particle_transform_tagging.c b/patches/particle_transform_tagging.c index b2483a5..99bcbf0 100644 --- a/patches/particle_transform_tagging.c +++ b/patches/particle_transform_tagging.c @@ -71,8 +71,8 @@ void EffectSS_DrawParticle(PlayState* play, s32 index) { // @recomp If this particle was just reset then skip interpolation. if (particle_reset_list[index]) { - gEXMatrixGroupDecomposedSkip(POLY_OPA_DISP++, PARTICLE_TRANSFORM_ID_START + index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); - gEXMatrixGroupDecomposedSkip(POLY_XLU_DISP++, PARTICLE_TRANSFORM_ID_START + index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(POLY_OPA_DISP++, PARTICLE_TRANSFORM_ID_START + index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(POLY_XLU_DISP++, PARTICLE_TRANSFORM_ID_START + index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { gEXMatrixGroupDecomposedNormal(POLY_OPA_DISP++, PARTICLE_TRANSFORM_ID_START + index, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); @@ -138,7 +138,7 @@ void func_80B22FA8_patched(Actor* thisx, EnHanabiStruct* arg0, PlayState* play2) // @recomp Tag the matrix. gEXMatrixGroupDecomposedNormal(POLY_XLU_DISP++, actor_transform_id(thisx) + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); - + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); if (sp53 != arg0->unk_02) { diff --git a/patches/patches.h b/patches/patches.h index 2c05139..014cf9a 100644 --- a/patches/patches.h +++ b/patches/patches.h @@ -17,7 +17,10 @@ #define gEXMatrixGroupDecomposedNormal(cmd, id, push, proj, edit) \ gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit) -#define gEXMatrixGroupDecomposedSkip(cmd, id, push, proj, edit) \ +#define gEXMatrixGroupDecomposedSkipPosRot(cmd, id, push, proj, edit) \ + gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit) + +#define gEXMatrixGroupDecomposedSkipAll(cmd, id, push, proj, edit) \ gEXMatrixGroupDecomposed(cmd, id, push, proj, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, edit) #define gEXMatrixGroupDecomposedVerts(cmd, id, push, proj, edit) \ @@ -59,6 +62,7 @@ void View_ApplyInterpolate(View* view, s32 mask, bool reset_interpolation_state) void set_camera_skipped(bool skipped); void clear_camera_skipped(); +void edit_billboard_groups(PlayState* play); bool camera_was_skipped(); void room_load_hook(PlayState* play, Room* room); diff --git a/patches/play_patches.c b/patches/play_patches.c index 8db002a..3a59d96 100644 --- a/patches/play_patches.c +++ b/patches/play_patches.c @@ -16,6 +16,7 @@ void Play_Main(GameState* thisx) { // @recomp debug_play_update(this); controls_play_update(this); + matrix_play_update(this); // @recomp avoid unused variable warning (void)prevInput; diff --git a/patches/play_patches.h b/patches/play_patches.h index 3af7df4..d6b7a58 100644 --- a/patches/play_patches.h +++ b/patches/play_patches.h @@ -6,5 +6,6 @@ void debug_play_update(PlayState* play); void camera_pre_play_update(PlayState* play); void camera_post_play_update(PlayState* play); +void matrix_play_update(PlayState* play); #endif diff --git a/patches/sky_transform_tagging.c b/patches/sky_transform_tagging.c index 0a9c889..9503a62 100644 --- a/patches/sky_transform_tagging.c +++ b/patches/sky_transform_tagging.c @@ -32,7 +32,7 @@ void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId // @recomp Tag the skybox's matrix, skipping interpolation if the camera's interpolation was also skipped. if (camera_was_skipped()) { - gEXMatrixGroupDecomposedSkip(POLY_OPA_DISP++, SKYBOX_TRANSFORM_ID_START, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(POLY_OPA_DISP++, SKYBOX_TRANSFORM_ID_START, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { gEXMatrixGroupDecomposedNormal(POLY_OPA_DISP++, SKYBOX_TRANSFORM_ID_START, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); @@ -247,9 +247,16 @@ void Environment_DrawSkyboxStarsImpl(PlayState* play, Gfx** gfxP) { viewProjectionMtxF = play->viewProjectionMtxF.mf; if (imgWidth >= 2) { + // @recomp Tag the star. - gEXMatrixGroupSimple(gfx++, STAR_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, - G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, G_EX_EDIT_NONE); + if (camera_was_skipped()) { + gEXMatrixGroupSimple(gfx++, STAR_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_ORDER_LINEAR, G_EX_EDIT_NONE); + } + else { + gEXMatrixGroupSimple(gfx++, STAR_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, + G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR, G_EX_EDIT_NONE); + } // @recomp Draw the star in 3D with a billboarded matrix. Environment_DrawSkyboxStarBillboard(play->state.gfxCtx, &billboard_mtx, &gfx, pos.x, pos.y, pos.z, imgWidth, imgWidth); diff --git a/patches/specific_actor_transform_tagging.c b/patches/specific_actor_transform_tagging.c index 8bb3607..0a7392e 100644 --- a/patches/specific_actor_transform_tagging.c +++ b/patches/specific_actor_transform_tagging.c @@ -291,7 +291,7 @@ void Boss03_DrawEffects(PlayState* play) { // @recomp Tag this effect and clear its reset state. if (special_effect_reset_states[i]) { - gEXMatrixGroupDecomposedSkip(POLY_OPA_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(POLY_OPA_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { gEXMatrixGroupDecomposedNormal(POLY_OPA_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); @@ -340,7 +340,7 @@ void Boss03_DrawEffects(PlayState* play) { // @recomp Tag this effect and clear its reset state. if (special_effect_reset_states[i]) { - gEXMatrixGroupDecomposedSkip(POLY_XLU_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(POLY_XLU_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { gEXMatrixGroupDecomposedNormal(POLY_XLU_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); @@ -381,7 +381,7 @@ void Boss03_DrawEffects(PlayState* play) { // @recomp Tag this effect and clear its reset state. if (special_effect_reset_states[i]) { - gEXMatrixGroupDecomposedSkip(POLY_XLU_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); + gEXMatrixGroupDecomposedSkipAll(POLY_XLU_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } else { gEXMatrixGroupDecomposedNormal(POLY_XLU_DISP++, SPECIAL_EFFECTS_TRANSFORM_ID_START + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); diff --git a/patches/ui_patches.c b/patches/ui_patches.c index f4f37b8..2c193b2 100644 --- a/patches/ui_patches.c +++ b/patches/ui_patches.c @@ -97,6 +97,12 @@ void Graph_ExecuteAndDraw(GraphicsContext* gfxCtx, GameState* gameState) { // @recomp Send the current framerate to RT64, including any extra VI interrupt periods. gEXSetRefreshRate(POLY_OPA_DISP++, 60 / (gameState->framerateDivisor + extra_vis)); + // @recomp Edit billboard groups to skip interpolation if the camera also skipped. + if (gameState->destroy == Play_Destroy) { + PlayState* play = (PlayState*)gameState; + edit_billboard_groups(play); + } + // @recomp Clear the camera skip state. clear_camera_skipped();