diff --git a/src/actors/mario_sign/render.inc.c b/src/actors/mario_sign/render.inc.c index 1c72c8394..7914a283f 100644 --- a/src/actors/mario_sign/render.inc.c +++ b/src/actors/mario_sign/render.inc.c @@ -14,7 +14,7 @@ void render_actor_mario_sign(Camera* arg0, UNUSED Mat4 arg1, struct Actor* arg2) Mat4 sp40; f32 unk; s16 temp = arg2->flags; - + FrameInterpolation_RecordOpenChild(arg2, 0); if (temp & 0x800) { return; } @@ -31,4 +31,7 @@ void render_actor_mario_sign(Camera* arg0, UNUSED Mat4 arg1, struct Actor* arg2) gSPDisplayList(gDisplayListHead++, d_course_mario_raceway_dl_sign); } } + + FrameInterpolation_RecordCloseChild(); + } diff --git a/src/actors/mario_sign/update.inc.c b/src/actors/mario_sign/update.inc.c index 6a061eddd..7a85e8ac5 100644 --- a/src/actors/mario_sign/update.inc.c +++ b/src/actors/mario_sign/update.inc.c @@ -11,10 +11,10 @@ void update_actor_mario_sign(struct Actor* arg0) { arg0->pos[1] += 4.0f; if (arg0->pos[1] > 800.0f) { arg0->flags |= 0x800; - arg0->rot[1] += 1820; + arg0->rot[1] += 4; } } else { - arg0->rot[1] += 182; + arg0->rot[1] += 4; } } } diff --git a/src/engine/Matrix.cpp b/src/engine/Matrix.cpp index 1f2301258..44e5f081d 100644 --- a/src/engine/Matrix.cpp +++ b/src/engine/Matrix.cpp @@ -1,6 +1,7 @@ #include #include #include "engine/World.h" +#include "src/port/interpolation/FrameInterpolation.h" extern "C" { #include "common_structs.h" @@ -16,6 +17,7 @@ void AddMatrix(std::vector& stack, Mat4 mtx, s32 flags) { stack.emplace_back(); // Convert to a fixed-point matrix + FrameInterpolation_RecordMatrixMtxFToMtx((MtxF*)mtx, &stack.back()); guMtxF2L(mtx, &stack.back()); // Load the matrix diff --git a/src/enhancements/collision_viewer.c b/src/enhancements/collision_viewer.c index fd7c542e0..f45a9872f 100644 --- a/src/enhancements/collision_viewer.c +++ b/src/enhancements/collision_viewer.c @@ -4,6 +4,8 @@ #include "code_800029B0.h" #include "mk64.h" #include "main.h" +#include +#include #include "collision_viewer.h" #include "math_util.h" diff --git a/src/gbiMacro.c b/src/gbiMacro.c index 5fa0ab171..007d7d281 100644 --- a/src/gbiMacro.c +++ b/src/gbiMacro.c @@ -18,5 +18,5 @@ UNUSED void gfx_func_80040D00(void) { guOrtho(&gGfxPool->mtxScreen, 0.0f, SCREEN_WIDTH, 0.0f, SCREEN_HEIGHT, -1.0f, 1.0f, 1.0f); gSPPerspNormalize(gDisplayListHead++, 0xFFFF); gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(gGfxPool), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); - gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gIdentityMatrix), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + //gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gIdentityMatrix), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); } diff --git a/src/port/interpolation/FrameInterpolation.cpp b/src/port/interpolation/FrameInterpolation.cpp index 12b57f4a9..9064cdb04 100644 --- a/src/port/interpolation/FrameInterpolation.cpp +++ b/src/port/interpolation/FrameInterpolation.cpp @@ -8,6 +8,7 @@ #include #include #include "FrameInterpolation.h" +#include "matrix.h" /* Frame interpolation. @@ -59,6 +60,8 @@ enum class Op { MatrixTranslate, MatrixScale, MatrixRotate1Coord, + MatrixMult4x4, + MatrixPosRotXYZ, MatrixMultVec3fNoTranslate, MatrixMultVec3f, MatrixMtxFToMtx, @@ -90,14 +93,13 @@ union Data { struct { Mat4* matrix; - Vec3f b; + Vec3fInterp b; } matrix_translate, matrix_scale; struct { Mat4* matrix; u32 coord; - f32 value; - u8 mode; + s16 value; } matrix_rotate_1_coord; struct { @@ -112,6 +114,17 @@ union Data { Vec3f dest; } matrix_vec_no_translate; + struct { + Mat4* dest; + Mat4 mtx1; + Mat4 mtx2; + } matrix_mult_4x4; + + struct { + Vec3fInterp pos; + Vec3sInterp orientation; + } matrix_pos_rot_xyz; + struct { Mat4* matrix; Vec3f translation; @@ -215,6 +228,10 @@ struct InterpolateCtx { return w * o + step * n; } + s16 lerp_s16(s16 o, s16 n) { + return w * o + step * n; + } + void lerp_vec3f(Vec3f* res, Vec3f* o, Vec3f* n) { *res[0] = lerp(*o[0], *n[0]); *res[1] = lerp(*o[1], *n[1]); @@ -332,20 +349,29 @@ struct InterpolateCtx { break; case Op::MatrixTranslate: - // Matrix_Translate(gInterpolationMatrix, lerp(old_op.matrix_translate.x, - // new_op.matrix_translate.x), - // lerp(old_op.matrix_translate.y, new_op.matrix_translate.y), - // lerp(old_op.matrix_translate.z, new_op.matrix_translate.z), - // new_op.matrix_translate.mode); Vec3f temp; - temp[0] = lerp(old_op.matrix_translate.b[0], new_op.matrix_translate.b[0]); - temp[1] = lerp(old_op.matrix_translate.b[1], new_op.matrix_translate.b[1]); - temp[2] = lerp(old_op.matrix_translate.b[2], new_op.matrix_translate.b[2]); + temp[0] = lerp(old_op.matrix_translate.b.x, new_op.matrix_translate.b.x); + temp[1] = lerp(old_op.matrix_translate.b.y, new_op.matrix_translate.b.y); + temp[2] = lerp(old_op.matrix_translate.b.z, new_op.matrix_translate.b.z); mtxf_translate(*gInterpolationMatrix, temp); break; + case Op::MatrixPosRotXYZ: + Vec3f tempF; + Vec3s tempS; + + tempF[0] = lerp(old_op.matrix_pos_rot_xyz.pos.x, new_op.matrix_pos_rot_xyz.pos.x); + tempF[1] = lerp(old_op.matrix_pos_rot_xyz.pos.y, new_op.matrix_pos_rot_xyz.pos.y); + tempF[2] = lerp(old_op.matrix_pos_rot_xyz.pos.z, new_op.matrix_pos_rot_xyz.pos.z); + + tempS[0] = lerp(old_op.matrix_pos_rot_xyz.orientation.x, new_op.matrix_pos_rot_xyz.orientation.x); + tempS[1] = lerp(old_op.matrix_pos_rot_xyz.orientation.y, new_op.matrix_pos_rot_xyz.orientation.y); + tempS[2] = lerp(old_op.matrix_pos_rot_xyz.orientation.z, new_op.matrix_pos_rot_xyz.orientation.z); + + mtxf_pos_rotation_xyz(*gInterpolationMatrix, tempF, tempS); + break; case Op::MatrixScale: // Matrix_Scale(gInterpolationMatrix, lerp(old_op.matrix_scale.x, new_op.matrix_scale.x), @@ -355,20 +381,19 @@ struct InterpolateCtx { break; case Op::MatrixRotate1Coord: { - float v = interpolate_angle(old_op.matrix_rotate_1_coord.value, + s16 v = interpolate_angle(old_op.matrix_rotate_1_coord.value, new_op.matrix_rotate_1_coord.value); - u8 mode = new_op.matrix_rotate_1_coord.mode; switch (new_op.matrix_rotate_1_coord.coord) { case 0: - // Matrix_RotateX(gInterpolationMatrix, v, mode); + mtxf_rotate_x(*gInterpolationMatrix, v); break; case 1: - // Matrix_RotateY(gInterpolationMatrix, v, mode); + mtxf_rotate_y(*gInterpolationMatrix, v); break; case 2: - // Matrix_RotateZ(gInterpolationMatrix, v, mode); + mtxf_s16_rotate_z(*gInterpolationMatrix, v); break; } break; @@ -445,12 +470,12 @@ void FrameInterpolation_StartRecord(void) { current_recording = {}; current_path.clear(); current_path.push_back(¤t_recording.root_path); - if (!camera_interpolation) { - // default to interpolating - camera_interpolation = true; - is_recording = false; - return; - } + // if (!camera_interpolation) { + // // default to interpolating + // camera_interpolation = true; + // is_recording = false; + // return; + // } if (GameEngine::GetInterpolationFPS() != 20) { is_recording = true; } @@ -530,7 +555,7 @@ void FrameInterpolation_RecordMatrixTranslate(Mat4* matrix, Vec3f b) { if (!is_recording) return; - append(Op::MatrixTranslate).matrix_translate = { matrix, b[0] }; + append(Op::MatrixTranslate).matrix_translate = { matrix, *((Vec3fInterp*) &b) }; } void FrameInterpolation_RecordMatrixScale(Mat4* matrix, f32 x, f32 y, f32 z, u8 mode) { @@ -542,7 +567,16 @@ void FrameInterpolation_RecordMatrixScale(Mat4* matrix, f32 x, f32 y, f32 z, u8 void FrameInterpolation_RecordMatrixMultVec3fNoTranslate(Mat4* matrix, Vec3f src, Vec3f dest) { if (!is_recording) return; - // append(Op::MatrixMultVec3fNoTranslate).matrix_vec_no_translate = { matrix, src, dest }; + //append(Op::MatrixMultVec3fNoTranslate).matrix_vec_no_translate = { matrix, src, dest }; +} + +// Make a template for deref + + +void FrameInterpolation_RecordMatrixPosRotXYZ(Mat4 out, Vec3f pos, Vec3s orientation) { + if (!is_recording) + return; + append(Op::MatrixPosRotXYZ).matrix_pos_rot_xyz = { *((Vec3fInterp*) &pos), *((Vec3sInterp*) &orientation) }; } void FrameInterpolation_RecordMatrixMultVec3f(Mat4* matrix, Vec3f src, Vec3f dest) { @@ -551,10 +585,10 @@ void FrameInterpolation_RecordMatrixMultVec3f(Mat4* matrix, Vec3f src, Vec3f des // append(Op::MatrixMultVec3f).matrix_vec_translate = { matrix, src, dest }; } -void FrameInterpolation_RecordMatrixRotate1Coord(Mat4* matrix, u32 coord, f32 value, u8 mode) { +void FrameInterpolation_RecordMatrixRotate1Coord(Mat4* matrix, u32 coord, s16 value) { if (!is_recording) return; - append(Op::MatrixRotate1Coord).matrix_rotate_1_coord = { matrix, coord, value, mode }; + append(Op::MatrixRotate1Coord).matrix_rotate_1_coord = { matrix, coord, value }; } void FrameInterpolation_RecordMatrixMtxFToMtx(MtxF* src, Mtx* dest) { diff --git a/src/port/interpolation/FrameInterpolation.h b/src/port/interpolation/FrameInterpolation.h index 72a1c9146..7d2df76a8 100644 --- a/src/port/interpolation/FrameInterpolation.h +++ b/src/port/interpolation/FrameInterpolation.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef __FRAME_INTERPOLATION_H +#define __FRAME_INTERPOLATION_H // #include "sf64math.h" #include @@ -12,11 +13,8 @@ std::unordered_map FrameInterpolation_Interpolate(float step); extern "C" { - #endif - - void FrameInterpolation_ShouldInterpolateFrame(bool shouldInterpolate); void FrameInterpolation_StartRecord(void); @@ -35,6 +33,8 @@ int FrameInterpolation_GetCameraEpoch(void); void FrameInterpolation_RecordActorPosRotMatrix(void); +void FrameInterpolation_RecordMatrixPosRotXYZ(Mat4 out, Vec3f pos, Vec3s orientation); + //void FrameInterpolation_RecordMatrixPush(Matrix** mtx); //void FrameInterpolation_RecordMatrixPop(Matrix** mtx); @@ -45,7 +45,7 @@ void FrameInterpolation_RecordMatrixTranslate(Mat4* matrix, Vec3f b); //void FrameInterpolation_RecordMatrixScale(Matrix* matrix, f32 x, f32 y, f32 z, u8 mode); -//void FrameInterpolation_RecordMatrixRotate1Coord(Matrix* matrix, u32 coord, f32 value, u8 mode); +void FrameInterpolation_RecordMatrixRotate1Coord(Mat4* matrix, u32 coord, s16 value); void FrameInterpolation_RecordMatrixMtxFToMtx(MtxF* src, Mtx* dest); @@ -63,4 +63,6 @@ void FrameInterpolation_RecordSkinMatrixMtxFToMtx(MtxF* src, Mtx* dest); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif + +#endif // __FRAME_INTERPOLATION_H \ No newline at end of file diff --git a/src/port/interpolation/matrix.c b/src/port/interpolation/matrix.c new file mode 100644 index 000000000..4f8a7839b --- /dev/null +++ b/src/port/interpolation/matrix.c @@ -0,0 +1,450 @@ +#include +#include +#include "matrix.h" +#include "common_structs.h" + +Mtx gIdentityMtx = gdSPDefMtx(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); +Matrix gIdentityMatrix = { { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, +} }; + +Matrix* gGfxMatrix; +Matrix sGfxMatrixStack[0x20]; +Matrix* gCalcMatrix; +Matrix sCalcMatrixStack[0x20]; + +Mtx gMainMatrixStack[0x480]; +Mtx* gGfxMtx; + +void Matrix_InitPerspective(Gfx** dList) { + u16 norm; + float near = 10.0f; + float far = 12800.0f; + float fov = 45.0f; + + guPerspective(gGfxMtx, &norm, fov, 320.0f / 240.0f, near, far, 1.0f); + gSPPerspNormalize((*dList)++, norm); + gSPMatrix((*dList)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + guLookAt(gGfxMtx, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -12800.0f, 0.0f, 1.0f, 0.0f); + gSPMatrix((*dList)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + Matrix_Copy(gGfxMatrix, &gIdentityMatrix); +} + +void Matrix_InitOrtho(Gfx** dList) { + FrameInterpolation_RecordOpenChild("ortho", 0); + FrameInterpolation_RecordMarker(__FILE__, __LINE__); + guOrtho(gGfxMtx, -320.0f / 2, 320.0f / 2, -240.0f / 2, 240.0f / 2, 0.0f, 5.0f, 1.0f); + gSPMatrix((*dList)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); + guLookAt(gGfxMtx, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -12800.0f, 0.0f, 1.0f, 0.0f); + gSPMatrix((*dList)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); + Matrix_Copy(gGfxMatrix, &gIdentityMatrix); + FrameInterpolation_RecordCloseChild(); +} + + +// Copies src Matrix into dst +void Matrix_Copy(Matrix* dst, Matrix* src) { + int32_t i; + + for (i = 0; i < 4; i++) { + dst->mf[i][0] = src->mf[i][0]; + dst->mf[i][1] = src->mf[i][1]; + dst->mf[i][2] = src->mf[i][2]; + dst->mf[i][3] = src->mf[i][3]; + } +} + +// Makes a copy of the stack's current matrix and puts it on the top of the stack +void Matrix_Push(Matrix** mtxStack) { + Matrix_Copy(*mtxStack + 1, *mtxStack); + (*mtxStack)++; +} + +// Removes the top matrix of the stack +void Matrix_Pop(Matrix** mtxStack) { + (*mtxStack)--; +} + +// Copies tf into mtx (MTXF_NEW) or applies it to mtx (MTXF_APPLY) +void Matrix_Mult(Matrix* mtx, Matrix* tf, u8 mode) { + f32 rx; + f32 ry; + f32 rz; + f32 rw; + s32 i0; + s32 i1; + s32 i2; + s32 i3; + + if (mode == 1) { + rx = mtx->mf[0][0]; + ry = mtx->mf[1][0]; + rz = mtx->mf[2][0]; + rw = mtx->mf[3][0]; + + for (i0 = 0; i0 < 4; i0++) { + mtx->mf[i0][0] = (rx * tf->mf[i0][0]) + (ry * tf->mf[i0][1]) + (rz * tf->mf[i0][2]) + (rw * tf->mf[i0][3]); + } + + rx = mtx->mf[0][1]; + ry = mtx->mf[1][1]; + rz = mtx->mf[2][1]; + rw = mtx->mf[3][1]; + + for (i1 = 0; i1 < 4; i1++) { + mtx->mf[i1][1] = (rx * tf->mf[i1][0]) + (ry * tf->mf[i1][1]) + (rz * tf->mf[i1][2]) + (rw * tf->mf[i1][3]); + } + + rx = mtx->mf[0][2]; + ry = mtx->mf[1][2]; + rz = mtx->mf[2][2]; + rw = mtx->mf[3][2]; + + for (i2 = 0; i2 < 4; i2++) { + mtx->mf[i2][2] = (rx * tf->mf[i2][0]) + (ry * tf->mf[i2][1]) + (rz * tf->mf[i2][2]) + (rw * tf->mf[i2][3]); + } + + rx = mtx->mf[0][3]; + ry = mtx->mf[1][3]; + rz = mtx->mf[2][3]; + rw = mtx->mf[3][3]; + + for (i3 = 0; i3 < 4; i3++) { + mtx->mf[i3][3] = (rx * tf->mf[i3][0]) + (ry * tf->mf[i3][1]) + (rz * tf->mf[i3][2]) + (rw * tf->mf[i3][3]); + } + } else { + Matrix_Copy(mtx, tf); + } +} + +// Creates a translation matrix in mtx (MTXF_NEW) or applies one to mtx (MTXF_APPLY) +void Matrix_Translate(Matrix* mtx, f32 x, f32 y, f32 z, u8 mode) { + f32 rx; + f32 ry; + s32 i; + + if (mode == 1) { + for (i = 0; i < 4; i++) { + rx = mtx->mf[0][i]; + ry = mtx->mf[1][i]; + + mtx->mf[3][i] += (rx * x) + (ry * y) + (mtx->mf[2][i] * z); + } + } else { + mtx->mf[3][0] = x; + mtx->mf[3][1] = y; + mtx->mf[3][2] = z; + mtx->mf[0][1] = mtx->mf[0][2] = mtx->mf[0][3] = mtx->mf[1][0] = mtx->mf[1][2] = mtx->mf[1][3] = mtx->mf[2][0] = + mtx->mf[2][1] = mtx->mf[2][3] = 0.0f; + mtx->mf[0][0] = mtx->mf[1][1] = mtx->mf[2][2] = mtx->mf[3][3] = 1.0f; + } +} + +// Creates a scale matrix in mtx (MTXF_NEW) or applies one to mtx (MTXF_APPLY) +void Matrix_Scale(Matrix* mtx, f32 xScale, f32 yScale, f32 zScale, u8 mode) { + f32 rx; + f32 ry; + s32 i; + + if (mode == 1) { + for (i = 0; i < 4; i++) { + rx = mtx->mf[0][i]; + ry = mtx->mf[1][i]; + + mtx->mf[0][i] = rx * xScale; + mtx->mf[1][i] = ry * yScale; + mtx->mf[2][i] *= zScale; + } + } else { + mtx->mf[0][0] = xScale; + mtx->mf[1][1] = yScale; + mtx->mf[2][2] = zScale; + mtx->mf[0][1] = mtx->mf[0][2] = mtx->mf[0][3] = mtx->mf[1][0] = mtx->mf[1][2] = mtx->mf[1][3] = mtx->mf[2][0] = + mtx->mf[2][1] = mtx->mf[2][3] = mtx->mf[3][0] = mtx->mf[3][1] = mtx->mf[3][2] = 0.0f; + mtx->mf[3][3] = 1.0f; + } +} + +// Creates rotation matrix about the X axis in mtx (MTXF_NEW) or applies one to mtx (MTXF_APPLY) +void Matrix_RotateX(Matrix* mtx, f32 angle, u8 mode) { + f32 cs; + f32 sn; + f32 ry; + f32 rz; + s32 i; + + sn = sinf(angle); + cs = cosf(angle); + if (mode == 1) { + for (i = 0; i < 4; i++) { + ry = mtx->mf[1][i]; + rz = mtx->mf[2][i]; + + mtx->mf[1][i] = (ry * cs) + (rz * sn); + mtx->mf[2][i] = (rz * cs) - (ry * sn); + } + } else { + mtx->mf[1][1] = mtx->mf[2][2] = cs; + mtx->mf[1][2] = sn; + mtx->mf[2][1] = -sn; + mtx->mf[0][0] = mtx->mf[3][3] = 1.0f; + mtx->mf[0][1] = mtx->mf[0][2] = mtx->mf[0][3] = mtx->mf[1][0] = mtx->mf[1][3] = mtx->mf[2][0] = mtx->mf[2][3] = + mtx->mf[3][0] = mtx->mf[3][1] = mtx->mf[3][2] = 0.0f; + } +} + +// Creates rotation matrix about the Y axis in mtx (MTXF_NEW) or applies one to mtx (MTXF_APPLY) +void Matrix_RotateY(Matrix* mtx, f32 angle, u8 mode) { + f32 cs; + f32 sn; + f32 rx; + f32 rz; + s32 i; + + sn = sinf(angle); + cs = cosf(angle); + if (mode == 1) { + for (i = 0; i < 4; i++) { + rx = mtx->mf[0][i]; + rz = mtx->mf[2][i]; + + mtx->mf[0][i] = (rx * cs) - (rz * sn); + mtx->mf[2][i] = (rx * sn) + (rz * cs); + } + } else { + mtx->mf[0][0] = mtx->mf[2][2] = cs; + mtx->mf[0][2] = -sn; + mtx->mf[2][0] = sn; + mtx->mf[1][1] = mtx->mf[3][3] = 1.0f; + mtx->mf[0][1] = mtx->mf[0][3] = mtx->mf[1][0] = mtx->mf[1][2] = mtx->mf[1][3] = mtx->mf[2][1] = mtx->mf[2][3] = + mtx->mf[3][0] = mtx->mf[3][1] = mtx->mf[3][2] = 0.0f; + } +} + +// Creates rotation matrix about the Z axis in mtx (MTXF_NEW) or applies one to mtx (MTXF_APPLY) +void Matrix_RotateZ(Matrix* mtx, f32 angle, u8 mode) { + f32 cs; + f32 sn; + f32 rx; + f32 ry; + s32 i; + + sn = sinf(angle); + cs = cosf(angle); + if (mode == 1) { + for (i = 0; i < 4; i++) { + rx = mtx->mf[0][i]; + ry = mtx->mf[1][i]; + + mtx->mf[0][i] = (rx * cs) + (ry * sn); + mtx->mf[1][i] = (ry * cs) - (rx * sn); + } + } else { + mtx->mf[0][0] = mtx->mf[1][1] = cs; + mtx->mf[0][1] = sn; + mtx->mf[1][0] = -sn; + mtx->mf[2][2] = mtx->mf[3][3] = 1.0f; + mtx->mf[0][2] = mtx->mf[0][3] = mtx->mf[1][2] = mtx->mf[1][3] = mtx->mf[2][0] = mtx->mf[2][1] = mtx->mf[2][3] = + mtx->mf[3][0] = mtx->mf[3][1] = mtx->mf[3][2] = 0.0f; + } +} + +// Creates rotation matrix about a given vector axis in mtx (MTXF_NEW) or applies one to mtx (MTXF_APPLY). +// The vector specifying the axis does not need to be a unit vector. +void Matrix_RotateAxis(Matrix* mtx, f32 angle, f32 axisX, f32 axisY, f32 axisZ, u8 mode) { + f32 rx; + f32 ry; + f32 rz; + f32 norm; + f32 cxx; + f32 cyx; + f32 czx; + f32 cxy; + f32 cyy; + f32 czy; + f32 cxz; + f32 cyz; + f32 czz; + f32 xx; + f32 yy; + f32 zz; + f32 xy; + f32 yz; + f32 xz; + f32 sinA; + f32 cosA; + + norm = sqrtf((axisX * axisX) + (axisY * axisY) + (axisZ * axisZ)); + if (norm != 0.0) { + axisX /= norm; + axisY /= norm; + axisZ /= norm; + sinA = sinf(angle); + cosA = cosf(angle); + xx = axisX * axisX; + yy = axisY * axisY; + zz = axisZ * axisZ; + xy = axisX * axisY; + yz = axisY * axisZ; + xz = axisX * axisZ; + + if (mode == 1) { + cxx = (1.0f - xx) * cosA + xx; + cyx = (1.0f - cosA) * xy + axisZ * sinA; + czx = (1.0f - cosA) * xz - axisY * sinA; + + cxy = (1.0f - cosA) * xy - axisZ * sinA; + cyy = (1.0f - yy) * cosA + yy; + czy = (1.0f - cosA) * yz + axisX * sinA; + + cxz = (1.0f - cosA) * xz + axisY * sinA; + cyz = (1.0f - cosA) * yz - axisX * sinA; + czz = (1.0f - zz) * cosA + zz; + + // loop doesn't seem to work here. + rx = mtx->mf[0][0]; + ry = mtx->mf[0][1]; + rz = mtx->mf[0][2]; + mtx->mf[0][0] = (rx * cxx) + (ry * cxy) + (rz * cxz); + mtx->mf[0][1] = (rx * cyx) + (ry * cyy) + (rz * cyz); + mtx->mf[0][2] = (rx * czx) + (ry * czy) + (rz * czz); + + rx = mtx->mf[1][0]; + ry = mtx->mf[1][1]; + rz = mtx->mf[1][2]; + mtx->mf[1][0] = (rx * cxx) + (ry * cxy) + (rz * cxz); + mtx->mf[1][1] = (rx * cyx) + (ry * cyy) + (rz * cyz); + mtx->mf[1][2] = (rx * czx) + (ry * czy) + (rz * czz); + + rx = mtx->mf[2][0]; + ry = mtx->mf[2][1]; + rz = mtx->mf[2][2]; + mtx->mf[2][0] = (rx * cxx) + (ry * cxy) + (rz * cxz); + mtx->mf[2][1] = (rx * cyx) + (ry * cyy) + (rz * cyz); + mtx->mf[2][2] = (rx * czx) + (ry * czy) + (rz * czz); + } else { + mtx->mf[0][0] = (1.0f - xx) * cosA + xx; + mtx->mf[0][1] = (1.0f - cosA) * xy + axisZ * sinA; + mtx->mf[0][2] = (1.0f - cosA) * xz - axisY * sinA; + mtx->mf[0][3] = 0.0f; + + mtx->mf[1][0] = (1.0f - cosA) * xy - axisZ * sinA; + mtx->mf[1][1] = (1.0f - yy) * cosA + yy; + mtx->mf[1][2] = (1.0f - cosA) * yz + axisX * sinA; + mtx->mf[1][3] = 0.0f; + + mtx->mf[2][0] = (1.0f - cosA) * xz + axisY * sinA; + mtx->mf[2][1] = (1.0f - cosA) * yz - axisX * sinA; + mtx->mf[2][2] = (1.0f - zz) * cosA + zz; + mtx->mf[2][3] = 0.0f; + + mtx->mf[3][0] = mtx->mf[3][1] = mtx->mf[3][2] = 0.0f; + mtx->mf[3][3] = 1.0f; + } + } +} + +// Converts the current Gfx matrix to a Mtx +void Matrix_ToMtx(Mtx* dest) { + // LTODO: We need to validate this + guMtxF2L(gGfxMatrix->mf, dest); +} + +// Converts the Mtx src to a Matrix, putting the result in dest +void Matrix_FromMtx(Mtx* src, Matrix* dest) { + guMtxF2L(src->m, dest->mf); +} + +// Applies the transform matrix mtx to the vector src, putting the result in dest +void Matrix_MultVec3f(Matrix* mtx, Vec3f* src, Vec3f* dest) { + *dest[0] = (mtx->mf[0][0] * *src[0]) + (mtx->mf[1][0] * *src[1]) + (mtx->mf[2][0] * *src[2]) + mtx->mf[3][0]; + *dest[1] = (mtx->mf[0][1] * *src[0]) + (mtx->mf[1][1] * *src[1]) + (mtx->mf[2][1] * *src[2]) + mtx->mf[3][1]; + *dest[2] = (mtx->mf[0][2] * *src[0]) + (mtx->mf[1][2] * *src[1]) + (mtx->mf[2][2] * *src[2]) + mtx->mf[3][2]; +} + +// Applies the linear part of the transformation matrix mtx to the vector src, ignoring any translation that mtx might +// have. Puts the result in dest. +void Matrix_MultVec3fNoTranslate(Matrix* mtx, Vec3f* src, Vec3f* dest) { + *dest[0] = (mtx->mf[0][0] * *src[0]) + (mtx->mf[1][0] * *src[1]) + (mtx->mf[2][0] * *src[2]); + *dest[1] = (mtx->mf[0][1] * *src[0]) + (mtx->mf[1][1] * *src[1]) + (mtx->mf[2][1] * *src[2]); + *dest[2] = (mtx->mf[0][2] * *src[0]) + (mtx->mf[1][2] * *src[1]) + (mtx->mf[2][2] * *src[2]); +} + +// Expresses the rotational part of the transform mtx as Tait-Bryan angles, in the yaw-pitch-roll (intrinsic YXZ) +// convention used in worldspace calculations +void Matrix_GetYRPAngles(Matrix* mtx, Vec3f* rot) { + Matrix invYP; + Vec3f origin = { 0.0f, 0.0f, 0.0f }; + Vec3f originP; + Vec3f zHat = { 0.0f, 0.0f, 1.0f }; + Vec3f zHatP; + Vec3f xHat = { 1.0f, 0.0f, 0.0f }; + Vec3f xHatP; + + Matrix_MultVec3fNoTranslate(mtx, &origin, &originP); + Matrix_MultVec3fNoTranslate(mtx, &zHat, &zHatP); + Matrix_MultVec3fNoTranslate(mtx, &xHat, &xHatP); + zHatP[0] -= originP[0]; + zHatP[1] -= originP[1]; + zHatP[2] -= originP[2]; + xHatP[0] -= originP[0]; + xHatP[1] -= originP[1]; + xHatP[2] -= originP[2]; + *rot[1] = atan2f(zHatP[0], zHatP[2]); + *rot[0] = -atan2f(zHatP[1], sqrtf(SQ(zHatP[0]) + SQ(zHatP[2]))); + Matrix_RotateX(&invYP, -*rot[0], MTXF_NEW); + Matrix_RotateY(&invYP, -*rot[1], MTXF_APPLY); + Matrix_MultVec3fNoTranslate(&invYP, &xHatP, &xHat); + *rot[0] *= M_RTOD; + *rot[1] *= M_RTOD; + *rot[2] = atan2f(xHat[1], xHat[0]) * M_RTOD; +} + +// Expresses the rotational part of the transform mtx as Tait-Bryan angles, in the extrinsic XYZ convention used in +// modelspace calculations +void Matrix_GetXYZAngles(Matrix* mtx, Vec3f* rot) { + Matrix invYZ; + Vec3f origin = { 0.0f, 0.0f, 0.0f }; + Vec3f originP; + Vec3f xHat = { 1.0f, 0.0f, 0.0f }; + Vec3f xHatP; + Vec3f yHat = { 0.0f, 1.0f, 0.0f }; + Vec3f yHatP; + + Matrix_MultVec3fNoTranslate(mtx, &origin, &originP); + Matrix_MultVec3fNoTranslate(mtx, &xHat, &xHatP); + Matrix_MultVec3fNoTranslate(mtx, &yHat, &yHatP); + xHatP[0] -= originP[0]; + xHatP[1] -= originP[1]; + xHatP[2] -= originP[2]; + yHatP[0] -= originP[0]; + yHatP[1] -= originP[1]; + yHatP[2] -= originP[2]; + *rot[2] = atan2f(xHatP[1], xHatP[0]); + *rot[1] = -atan2f(xHatP[2], sqrtf(SQ(xHatP[0]) + SQ(xHatP[1]))); + Matrix_RotateY(&invYZ, -*rot[1], MTXF_NEW); + Matrix_RotateZ(&invYZ, -*rot[2], MTXF_APPLY); + Matrix_MultVec3fNoTranslate(&invYZ, &yHatP, &yHat); + *rot[0] = atan2f(yHat[2], yHat[1]) * M_RTOD; + *rot[1] *= M_RTOD; + *rot[2] *= M_RTOD; +} + +// Creates a look-at matrix from Eye, At, and Up in mtx (MTXF_NEW) or applies one to mtx (MTXF_APPLY). +// A look-at matrix is a rotation-translation matrix that maps y to Up, z to (At - Eye), and translates to Eye +void Matrix_LookAt(Matrix* mtx, f32 xEye, f32 yEye, f32 zEye, f32 xAt, f32 yAt, f32 zAt, f32 xUp, f32 yUp, f32 zUp, + u8 mode) { + Matrix lookAt; + + guLookAtF(lookAt.mf, xEye, yEye, zEye, xAt, yAt, zAt, xUp, yUp, zUp); + Matrix_Mult(mtx, &lookAt, mode); +} + +// Converts the current Gfx matrix to a Mtx and sets it to the display list +void Matrix_SetGfxMtx(Gfx** gfx) { + Matrix_ToMtx(gGfxMtx); + gSPMatrix((*gfx)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); +} \ No newline at end of file diff --git a/src/port/interpolation/matrix.h b/src/port/interpolation/matrix.h new file mode 100644 index 000000000..f71ef6ab0 --- /dev/null +++ b/src/port/interpolation/matrix.h @@ -0,0 +1,94 @@ +#pragma once + +#define MTXF_NEW 0 +#define MTXF_APPLY 1 +#include "common_structs.h" + +typedef struct { + float r; + float g; + float b; +} Color; + +typedef struct { + float x; + float y; + float z; +} Vec3fInterp; + +typedef struct { + s16 x; + s16 y; + s16 z; +} Vec3sInterp; + +typedef struct { + f32 m1; f32 m2; f32 m3; f32 m4; + f32 m5; f32 m6; f32 m7; f32 m8; +} Mat4Interp; + +#define M_PI 3.14159265358979323846f +#define M_RTOD (180.0f / M_PI) +#define SQ(val) ((val) * (val)) + +#define qs1616(e) ((s32) ((e) *0x00010000)) + +#define IPART(x) ((qs1616(x) >> 16) & 0xFFFF) +#define FPART(x) (qs1616(x) & 0xFFFF) + +#define gdSPDefMtx(xx, yx, zx, wx, xy, yy, zy, wy, xz, yz, zz, wz, xw, yw, zw, ww) \ + { \ + { \ + (IPART(xx) << 0x10) | IPART(xy), (IPART(xz) << 0x10) | IPART(xw), (IPART(yx) << 0x10) | IPART(yy), \ + (IPART(yz) << 0x10) | IPART(yw), (IPART(zx) << 0x10) | IPART(zy), (IPART(zz) << 0x10) | IPART(zw), \ + (IPART(wx) << 0x10) | IPART(wy), (IPART(wz) << 0x10) | IPART(ww), (FPART(xx) << 0x10) | FPART(xy), \ + (FPART(xz) << 0x10) | FPART(xw), (FPART(yx) << 0x10) | FPART(yy), (FPART(yz) << 0x10) | FPART(yw), \ + (FPART(zx) << 0x10) | FPART(zy), (FPART(zz) << 0x10) | FPART(zw), (FPART(wx) << 0x10) | FPART(wy), \ + (FPART(wz) << 0x10) | FPART(ww), \ + } \ + } + + +typedef MtxF Matrix; + +#ifdef __cplusplus +extern "C" { +#endif + +extern Mtx gIdentityMtx; +extern Matrix gIdentityMatrix; + +extern Matrix* gGfxMatrix; +extern Matrix sGfxMatrixStack[]; +extern Matrix* gCalcMatrix; +extern Matrix sCalcMatrixStack[]; + +extern Mtx gMainMatrixStack[]; +extern Mtx* gGfxMtx; + +void Matrix_InitPerspective(Gfx** dList); +void Matrix_InitOrtho(Gfx** dList); +void Matrix_Copy(Matrix* dst, Matrix* src); +void Matrix_Push(Matrix** mtxStack); +void Matrix_Pop(Matrix** mtxStack); +void Matrix_Mult(Matrix* mtx, Matrix* tf, u8 mode); +void Matrix_Translate(Matrix* mtx, f32 x, f32 y, f32 z, u8 mode); +void Matrix_Scale(Matrix* mtx, f32 xScale, f32 yScale, f32 zScale, u8 mode); +void Matrix_RotateX(Matrix* mtx, f32 angle, u8 mode); +void Matrix_RotateY(Matrix* mtx, f32 angle, u8 mode); +void Matrix_RotateZ(Matrix* mtx, f32 angle, u8 mode); +void Matrix_RotateAxis(Matrix* mtx, f32 angle, f32 axisX, f32 axisY, f32 axisZ, u8 mode); +void Matrix_ToMtx(Mtx* dest); +void Matrix_FromMtx(Mtx* src, Matrix* dest); +void Matrix_MultVec3f(Matrix* mtx, Vec3f* src, Vec3f* dest); +void Matrix_MultVec3fNoTranslate(Matrix* mtx, Vec3f* src, Vec3f* dest); +void Matrix_GetYRPAngles(Matrix* mtx, Vec3f* rot); +void Matrix_GetXYZAngles(Matrix* mtx, Vec3f* rot); +void Matrix_LookAt(Matrix* mtx, f32 xEye, f32 yEye, f32 zEye, f32 xAt, f32 yAt, f32 zAt, f32 xUp, f32 yUp, f32 zUp, + u8 mode); +void Matrix_SetGfxMtx(Gfx** gfx); +void Lights_SetOneLight(Gfx** dList, s32 dirX, s32 dirY, s32 dirZ, s32 colR, s32 colG, s32 colB, s32 ambR, s32 ambG, s32 ambB); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/racing/framebuffer_effects.c b/src/racing/framebuffer_effects.c index 9a166b448..a89df5b40 100644 --- a/src/racing/framebuffer_effects.c +++ b/src/racing/framebuffer_effects.c @@ -37,7 +37,7 @@ void FB_CreateFramebuffers(void) { void FB_CopyToFramebuffer(Gfx** gfxP, s32 fb_src, s32 fb_dest, u8 oncePerFrame, u8* hasCopied) { Gfx* gfx = *gfxP; - gSPMatrix(gfx++, &gIdentityMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + // gSPMatrix(gfx++, &gIdentityMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gDPSetOtherMode(gfx++, G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | @@ -110,7 +110,7 @@ void FB_WriteFramebufferSliceToCPU(Gfx** gfxP, void* buffer, u8 byteSwap) { void FB_DrawFromFramebuffer(Gfx** gfxP, s32 fb, u8 alpha) { Gfx* gfx = *gfxP; - gSPMatrix(gfx++, &gIdentityMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + //gSPMatrix(gfx++, &gIdentityMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gDPSetEnvColor(gfx++, 255, 255, 255, alpha); diff --git a/src/racing/math_util.c b/src/racing/math_util.c index 934865b08..f1dd6bf5d 100644 --- a/src/racing/math_util.c +++ b/src/racing/math_util.c @@ -9,15 +9,17 @@ #include "memory.h" #include "engine/Matrix.h" #include "port/Game.h" +#include +#include #pragma intrinsic(sqrtf, fabs) s32 D_802B91C0[2] = { 13, 13 }; Vec3f D_802B91C8 = { 0.0f, 0.0f, 0.0f }; -Mtx gIdentityMatrix = { - toFixedPointMatrix(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0), -}; +// Mtx gIdentityMatrix = { +// toFixedPointMatrix(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0), +// }; // This functions looks similar to a segment of code from func_802A4A0C in skybox_and_splitscreen.c UNUSED s32 func_802B4F60(UNUSED s32 arg0, Vec3f arg1, UNUSED s32 arg2, UNUSED f32 arg3, UNUSED f32 arg4) { @@ -349,6 +351,7 @@ void mtxf_rotate_x(Mat4 mat, s16 angle) { // create a rotation matrix around the y axis void mtxf_rotate_y(Mat4 mat, s16 angle) { + FrameInterpolation_RecordMatrixRotate1Coord(&mat, 1, angle); f32 sin_theta = sins(angle); f32 cos_theta = coss(angle); @@ -368,6 +371,7 @@ void mtxf_rotate_y(Mat4 mat, s16 angle) { // create a rotation matrix around the z axis void mtxf_s16_rotate_z(Mat4 mat, s16 angle) { + FrameInterpolation_RecordMatrixRotate1Coord(&mat, 2, angle); f32 sin_theta = sins(angle); f32 cos_theta = coss(angle); @@ -480,6 +484,7 @@ void mtxf_pos_rotation_xyz(Mat4 out, Vec3f pos, Vec3s orientation) { f32 cosine2; f32 sine3; f32 cosine3; + FrameInterpolation_RecordMatrixPosRotXYZ(out, pos, orientation); sine1 = sins(orientation[0]); cosine1 = coss(orientation[0]); diff --git a/src/racing/math_util.h b/src/racing/math_util.h index b767e9068..ec6c2f3c9 100644 --- a/src/racing/math_util.h +++ b/src/racing/math_util.h @@ -10,6 +10,10 @@ // #define min(a, b) ((a) <= (b) ? (a) : (b)) // #define max(a, b) ((a) > (b) ? (a) : (b)) +#ifdef __cplusplus +extern "C" { +#endif + #define sqr(x) ((x) * (x)) // Here to appease the pragma gods @@ -70,6 +74,10 @@ f32 is_within_render_distance(Vec3f, Vec3f, u16, f32, f32, f32); extern s32 D_802B91C0[]; extern Vec3f D_802B91C8; -extern Mtx gIdentityMatrix; +//extern Mtx gIdentityMatrix; + +#ifdef __cplusplus +} +#endif #endif // MATH_UTIL_H diff --git a/src/racing/skybox_and_splitscreen.c b/src/racing/skybox_and_splitscreen.c index 77b1c03ff..be56d22f1 100644 --- a/src/racing/skybox_and_splitscreen.c +++ b/src/racing/skybox_and_splitscreen.c @@ -397,6 +397,10 @@ void func_802A450C(Vtx* skybox) { skybox[7].v.cn[2] = prop->FloorTopLeft.b; } +Mtx gIdentityMatrix2 = { + toFixedPointMatrix(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0), +}; + void func_802A487C(Vtx* arg0, UNUSED struct UnkStruct_800DC5EC* arg1, UNUSED s32 arg2, UNUSED s32 arg3, UNUSED f32* arg4) { @@ -409,7 +413,7 @@ void func_802A487C(Vtx* arg0, UNUSED struct UnkStruct_800DC5EC* arg1, UNUSED s32 gSPPerspNormalize(gDisplayListHead++, 0xFFFF); gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxScreen), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); - gSPMatrix(gDisplayListHead++, &gIdentityMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPMatrix(gDisplayListHead++, &gIdentityMatrix2, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPVertex(gDisplayListHead++, &arg0[4], 4, 0); gSP2Triangles(gDisplayListHead++, 0, 3, 1, 0, 1, 3, 2, 0); } @@ -476,7 +480,7 @@ void func_802A4A0C(Vtx* vtx, struct UnkStruct_800DC5EC* arg1, UNUSED s32 arg2, U gSPPerspNormalize(gDisplayListHead++, 0xFFFF); gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxScreen), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); - gSPMatrix(gDisplayListHead++, &gIdentityMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPMatrix(gDisplayListHead++, &gIdentityMatrix2, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPVertex(gDisplayListHead++, &vtx[0], 4, 0); gSP2Triangles(gDisplayListHead++, 0, 3, 1, 0, 1, 3, 2, 0); if (GetCourse() == GetRainbowRoad()) { @@ -760,6 +764,8 @@ void render_screens(s32 mode, s32 cameraId, s32 playerId) { s32 screenId = 0; s32 screenMode = SCREEN_MODE_1P; + FrameInterpolation_StartRecord(); + switch (mode) { case RENDER_SCREEN_MODE_1P_PLAYER_ONE: func_802A53A4(); @@ -902,6 +908,8 @@ void render_screens(s32 mode, s32 cameraId, s32 playerId) { if (mode != RENDER_SCREEN_MODE_1P_PLAYER_ONE) { gNumScreens += 1; } + + FrameInterpolation_StopRecord(); } void func_802A74BC(void) {