WIP: uncapped framerate

This commit is contained in:
MysterD 2022-04-26 20:00:18 -07:00
parent c0969c7833
commit da0d4b3733
7 changed files with 201 additions and 114 deletions

View File

@ -124,9 +124,9 @@ struct GraphNodePerspective
struct DisplayListNode struct DisplayListNode
{ {
Mtx *transform; Mtx *transform;
void *transformInterpolated; void *transformPrev;
void *displayList; void *displayList;
void *displayListInterpolated; void *displayListPrev;
struct DisplayListNode *next; struct DisplayListNode *next;
}; };

View File

@ -12,6 +12,7 @@
#include "sm64.h" #include "sm64.h"
#include "game/level_update.h" #include "game/level_update.h"
#include "pc/lua/smlua_hooks.h" #include "pc/lua/smlua_hooks.h"
#include "pc/utils/misc.h"
/** /**
* This file contains the code that processes the scene graph for rendering. * This file contains the code that processes the scene graph for rendering.
@ -42,9 +43,9 @@
s16 gMatStackIndex; s16 gMatStackIndex;
Mat4 gMatStack[MATRIX_STACK_SIZE] = {}; Mat4 gMatStack[MATRIX_STACK_SIZE] = {};
Mat4 gMatStackInterpolated[MATRIX_STACK_SIZE] = {}; Mat4 gMatStackPrev[MATRIX_STACK_SIZE] = {};
Mtx *gMatStackFixed[MATRIX_STACK_SIZE] = { 0 }; Mtx *gMatStackFixed[MATRIX_STACK_SIZE] = { 0 };
Mtx *gMatStackInterpolatedFixed[MATRIX_STACK_SIZE] = { 0 }; Mtx *gMatStackPrevFixed[MATRIX_STACK_SIZE] = { 0 };
/** /**
* Animation nodes have state in global variables, so this struct captures * Animation nodes have state in global variables, so this struct captures
@ -137,45 +138,73 @@ u16 gAreaUpdateCounter = 0;
LookAt lookAt; LookAt lookAt;
#endif #endif
static Gfx *sPerspectivePos = NULL; static struct GraphNodePerspective *sPerspectiveNode = NULL;
static Mtx *sPerspectiveMtx = NULL; static Gfx* sPerspectivePos = NULL;
static Mtx* sPerspectiveMtx = NULL;
static f32 sPerspectiveAspect = 0;
static Vp* sViewport = NULL;
static Gfx* sViewportPos = NULL;
static Gfx* sViewportClipPos = NULL;
static Vp sViewportPrev = { 0 };
static Vp sViewportInterp = { 0 };
struct { struct {
Gfx *pos; Gfx *pos;
void *mtx; void *mtx;
void *displayList; void *displayList;
void *mtxPrev;
Mtx interp;
} gMtxTbl[6400]; } gMtxTbl[6400];
s32 gMtxTblSize; s32 gMtxTblSize;
static Gfx *sViewportPos = NULL;
static Vp sPrevViewport;
struct Object* gCurGraphNodeProcessingObject = NULL; struct Object* gCurGraphNodeProcessingObject = NULL;
struct MarioState* gCurGraphNodeMarioState = NULL; struct MarioState* gCurGraphNodeMarioState = NULL;
void mtx_patch_interpolated(void) { void mtx_patch_interpolated(f32 delta) {
if (sPerspectivePos != NULL) { if (sPerspectiveNode != NULL) {
gSPMatrix(sPerspectivePos, VIRTUAL_TO_PHYSICAL(sPerspectiveMtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); u16 perspNorm;
f32 fovInterpolated = delta_interpolate_f32(sPerspectiveNode->prevFov, sPerspectiveNode->fov, delta);
guPerspective(sPerspectiveMtx, &perspNorm, fovInterpolated, sPerspectiveAspect, sPerspectiveNode->near, sPerspectiveNode->far, 1.0f);
gSPMatrix(sPerspectivePos, VIRTUAL_TO_PHYSICAL(sPerspectiveNode), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
}
if (sViewportClipPos != NULL) {
delta_interpolate_vectors_s16(sViewportInterp.vp.vtrans, sViewportPrev.vp.vtrans, sViewport->vp.vtrans, delta);
delta_interpolate_vectors_s16(sViewportInterp.vp.vscale, sViewportPrev.vp.vscale, sViewport->vp.vscale, delta);
Gfx *saved = gDisplayListHead;
gDisplayListHead = sViewportClipPos;
make_viewport_clip_rect(&sViewportInterp);
gSPViewport(gDisplayListHead, VIRTUAL_TO_PHYSICAL(&sViewportInterp));
gDisplayListHead = saved;
} }
for (s32 i = 0; i < gMtxTblSize; i++) { for (s32 i = 0; i < gMtxTblSize; i++) {
Gfx *pos = gMtxTbl[i].pos; Gfx *pos = gMtxTbl[i].pos;
gSPMatrix(pos++, VIRTUAL_TO_PHYSICAL(gMtxTbl[i].mtx), delta_interpolate_mtx(&gMtxTbl[i].interp, (Mtx*) gMtxTbl[i].mtxPrev, (Mtx*) gMtxTbl[i].mtx, delta);
gSPMatrix(pos++, VIRTUAL_TO_PHYSICAL(&gMtxTbl[i].interp),
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gSPDisplayList(pos++, gMtxTbl[i].displayList); gSPDisplayList(pos++, gMtxTbl[i].displayList);
} }
}
if (sViewportPos != NULL) { void mtx_patch_before(void) {
Gfx *saved = gDisplayListHead; gMtxTblSize = 0;
gDisplayListHead = sViewportPos;
make_viewport_clip_rect(&sPrevViewport); if (sPerspectiveNode != NULL) {
gSPViewport(gDisplayListHead, VIRTUAL_TO_PHYSICAL(&sPrevViewport)); sPerspectiveNode->prevFov = sPerspectiveNode->fov;
gDisplayListHead = saved; sPerspectiveNode = NULL;
} }
gMtxTblSize = 0; if (sViewport != NULL) {
sPerspectivePos = NULL; sViewportPrev = *sViewport;
sViewportPos = NULL; sViewport = NULL;
sViewportPos = NULL;
sViewportClipPos = NULL;
}
} }
/** /**
@ -183,14 +212,14 @@ void mtx_patch_interpolated(void) {
*/ */
static u8 increment_mat_stack() { static u8 increment_mat_stack() {
Mtx *mtx = alloc_display_list(sizeof(*mtx)); Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated)); Mtx *mtxPrev = alloc_display_list(sizeof(*mtxPrev));
if (mtx == NULL || mtxInterpolated == NULL) { return FALSE; } if (mtx == NULL || mtxPrev == NULL) { return FALSE; }
gMatStackIndex++; gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]); mtxf_to_mtx(mtxPrev, gMatStackPrev[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx; gMatStackFixed[gMatStackIndex] = mtx;
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated; gMatStackPrevFixed[gMatStackIndex] = mtxPrev;
return TRUE; return TRUE;
} }
@ -223,11 +252,12 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) {
if ((u32) gMtxTblSize < sizeof(gMtxTbl) / sizeof(gMtxTbl[0])) { if ((u32) gMtxTblSize < sizeof(gMtxTbl) / sizeof(gMtxTbl[0])) {
gMtxTbl[gMtxTblSize].pos = gDisplayListHead; gMtxTbl[gMtxTblSize].pos = gDisplayListHead;
gMtxTbl[gMtxTblSize].mtx = currList->transform; gMtxTbl[gMtxTblSize].mtx = currList->transform;
gMtxTbl[gMtxTblSize].mtxPrev = currList->transformPrev;
gMtxTbl[gMtxTblSize++].displayList = currList->displayList; gMtxTbl[gMtxTblSize++].displayList = currList->displayList;
} }
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(currList->transformInterpolated), gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(currList->transformPrev),
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gSPDisplayList(gDisplayListHead++, currList->displayListInterpolated); gSPDisplayList(gDisplayListHead++, currList->displayListPrev);
currList = currList->next; currList = currList->next;
} }
} }
@ -243,7 +273,7 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) {
* parameter. Look at the RenderModeContainer struct to see the corresponding * parameter. Look at the RenderModeContainer struct to see the corresponding
* render modes of layers. * render modes of layers.
*/ */
static void geo_append_display_list2(void *displayList, void *displayListInterpolated, s16 layer) { static void geo_append_display_list2(void *displayList, void *displayListPrev, s16 layer) {
#ifdef F3DEX_GBI_2 #ifdef F3DEX_GBI_2
gSPLookAt(gDisplayListHead++, &lookAt); gSPLookAt(gDisplayListHead++, &lookAt);
@ -253,9 +283,9 @@ static void geo_append_display_list2(void *displayList, void *displayListInterpo
alloc_only_pool_alloc(gDisplayListHeap, sizeof(struct DisplayListNode)); alloc_only_pool_alloc(gDisplayListHeap, sizeof(struct DisplayListNode));
listNode->transform = gMatStackFixed[gMatStackIndex]; listNode->transform = gMatStackFixed[gMatStackIndex];
listNode->transformInterpolated = gMatStackInterpolatedFixed[gMatStackIndex]; listNode->transformPrev = gMatStackPrevFixed[gMatStackIndex];
listNode->displayList = displayList; listNode->displayList = displayList;
listNode->displayListInterpolated = displayListInterpolated; listNode->displayListPrev = displayListPrev;
listNode->next = 0; listNode->next = 0;
if (gCurGraphNodeMasterList->listHeads[layer] == 0) { if (gCurGraphNodeMasterList->listHeads[layer] == 0) {
gCurGraphNodeMasterList->listHeads[layer] = listNode; gCurGraphNodeMasterList->listHeads[layer] = listNode;
@ -312,42 +342,31 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
if (node->fnNode.func != NULL) { if (node->fnNode.func != NULL) {
node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, gMatStack[gMatStackIndex]); node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, gMatStack[gMatStackIndex]);
} }
if (node->fnNode.node.children != NULL) { if (node->fnNode.node.children == NULL) { return; }
u16 perspNorm;
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated)); u16 perspNorm;
Mtx *mtx = alloc_display_list(sizeof(*mtx)); Mtx *mtx = alloc_display_list(sizeof(*mtx));
if (mtx == NULL || mtxInterpolated == NULL) { return; } if (mtx == NULL) { return; }
f32 fovInterpolated;
#ifdef VERSION_EU #ifdef VERSION_EU
f32 aspect = ((f32) gCurGraphNodeRoot->width / (f32) gCurGraphNodeRoot->height) * 1.1f; f32 aspect = ((f32) gCurGraphNodeRoot->width / (f32) gCurGraphNodeRoot->height) * 1.1f;
#else #else
f32 aspect = (f32) gCurGraphNodeRoot->width / (f32) gCurGraphNodeRoot->height; f32 aspect = (f32) gCurGraphNodeRoot->width / (f32) gCurGraphNodeRoot->height;
#endif #endif
guPerspective(mtx, &perspNorm, node->fov, aspect, node->near, node->far, 1.0f); guPerspective(mtx, &perspNorm, node->prevFov, aspect, node->near, node->far, 1.0f);
if (gGlobalTimer == node->prevTimestamp + 1 && gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) { sPerspectiveNode = node;
sPerspectiveMtx = mtx;
sPerspectivePos = gDisplayListHead;
sPerspectiveAspect = aspect;
fovInterpolated = (node->prevFov + node->fov) / 2.0f; gSPPerspNormalize(gDisplayListHead++, perspNorm);
guPerspective(mtxInterpolated, &perspNorm, fovInterpolated, aspect, node->near, node->far, 1.0f); gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
sPerspectivePos = gDisplayListHead; gCurGraphNodeCamFrustum = node;
sPerspectiveMtx = mtx; geo_process_node_and_siblings(node->fnNode.node.children);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtxInterpolated), gCurGraphNodeCamFrustum = NULL;
G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
} else {
gSPPerspNormalize(gDisplayListHead++, perspNorm);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
}
node->prevFov = node->fov;
node->prevTimestamp = gGlobalTimer;
gCurGraphNodeCamFrustum = node;
geo_process_node_and_siblings(node->fnNode.node.children);
gCurGraphNodeCamFrustum = NULL;
}
} }
/** /**
@ -427,7 +446,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
Vec3f posInterpolated; Vec3f posInterpolated;
Vec3f focusInterpolated; Vec3f focusInterpolated;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
Mtx *rollMtx = alloc_display_list(sizeof(*rollMtx)); Mtx *rollMtx = alloc_display_list(sizeof(*rollMtx));
@ -465,7 +484,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
vec3f_copy(node->prevFocus, node->focus); vec3f_copy(node->prevFocus, node->focus);
node->prevTimestamp = gGlobalTimer; node->prevTimestamp = gGlobalTimer;
mtxf_lookat(cameraTransform, posInterpolated, focusInterpolated, node->roll); mtxf_lookat(cameraTransform, posInterpolated, focusInterpolated, node->roll);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], cameraTransform, gMatStackInterpolated[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], cameraTransform, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
@ -473,7 +492,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
if (node->fnNode.node.children != 0) { if (node->fnNode.node.children != 0) {
gCurGraphNodeCamera = node; gCurGraphNodeCamera = node;
node->matrixPtr = &gMatStack[gMatStackIndex]; node->matrixPtr = &gMatStack[gMatStackIndex];
node->matrixPtrInterpolated = &gMatStackInterpolated[gMatStackIndex]; node->matrixPtrInterpolated = &gMatStackPrev[gMatStackIndex];
geo_process_node_and_siblings(node->fnNode.node.children); geo_process_node_and_siblings(node->fnNode.node.children);
gCurGraphNodeCamera = NULL; gCurGraphNodeCamera = NULL;
} }
@ -496,7 +515,7 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation
vec3s_to_vec3f(translation, node->translation); vec3s_to_vec3f(translation, node->translation);
mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation); mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
@ -525,7 +544,7 @@ static void geo_process_translation(struct GraphNodeTranslation *node) {
vec3s_to_vec3f(translation, node->translation); vec3s_to_vec3f(translation, node->translation);
mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero); mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
@ -559,7 +578,7 @@ static void geo_process_rotation(struct GraphNodeRotation *node) {
} }
vec3s_copy(node->prevRotation, node->rotation); vec3s_copy(node->prevRotation, node->rotation);
node->prevTimestamp = gGlobalTimer; node->prevTimestamp = gGlobalTimer;
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
@ -586,7 +605,7 @@ static void geo_process_scale(struct GraphNodeScale *node) {
vec3f_set(scaleVec, node->scale, node->scale, node->scale); vec3f_set(scaleVec, node->scale, node->scale, node->scale);
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], scaleVec); mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], scaleVec);
mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex], scaleVec); mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex], scaleVec);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
@ -617,17 +636,17 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) {
vec3s_to_vec3f(translation, node->translation); vec3s_to_vec3f(translation, node->translation);
mtxf_billboard(gMatStack[nextMatStackIndex], gMatStack[gMatStackIndex], translation, mtxf_billboard(gMatStack[nextMatStackIndex], gMatStack[gMatStackIndex], translation,
gCurGraphNodeCamera->roll); gCurGraphNodeCamera->roll);
mtxf_billboard(gMatStackInterpolated[nextMatStackIndex], gMatStackInterpolated[gMatStackIndex], translation, mtxf_billboard(gMatStackPrev[nextMatStackIndex], gMatStackPrev[gMatStackIndex], translation,
gCurGraphNodeCamera->roll); gCurGraphNodeCamera->roll);
if (gCurGraphNodeHeldObject != NULL) { if (gCurGraphNodeHeldObject != NULL) {
mtxf_scale_vec3f(gMatStack[nextMatStackIndex], gMatStack[nextMatStackIndex], mtxf_scale_vec3f(gMatStack[nextMatStackIndex], gMatStack[nextMatStackIndex],
gCurGraphNodeHeldObject->objNode->header.gfx.scale); gCurGraphNodeHeldObject->objNode->header.gfx.scale);
mtxf_scale_vec3f(gMatStackInterpolated[nextMatStackIndex], gMatStackInterpolated[nextMatStackIndex], mtxf_scale_vec3f(gMatStackPrev[nextMatStackIndex], gMatStackPrev[nextMatStackIndex],
gCurGraphNodeHeldObject->objNode->header.gfx.scale); gCurGraphNodeHeldObject->objNode->header.gfx.scale);
} else if (gCurGraphNodeObject != NULL) { } else if (gCurGraphNodeObject != NULL) {
mtxf_scale_vec3f(gMatStack[nextMatStackIndex], gMatStack[nextMatStackIndex], mtxf_scale_vec3f(gMatStack[nextMatStackIndex], gMatStack[nextMatStackIndex],
gCurGraphNodeObject->scale); gCurGraphNodeObject->scale);
mtxf_scale_vec3f(gMatStackInterpolated[nextMatStackIndex], gMatStackInterpolated[nextMatStackIndex], mtxf_scale_vec3f(gMatStackPrev[nextMatStackIndex], gMatStackPrev[nextMatStackIndex],
gCurGraphNodeObject->scale); gCurGraphNodeObject->scale);
} }
@ -810,7 +829,7 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
mtxf_rotate_xyz_and_translate(matrix, translation, rotation); mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]); mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
mtxf_rotate_xyz_and_translate(matrix, translationInterpolated, rotationInterpolated); mtxf_rotate_xyz_and_translate(matrix, translationInterpolated, rotationInterpolated);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], matrix, gMatStackInterpolated[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
@ -957,7 +976,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
mtxf_translate(mtxf, shadowPos); mtxf_translate(mtxf, shadowPos);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtr); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtr);
mtxf_translate(mtxf, shadowPosInterpolated); mtxf_translate(mtxf, shadowPosInterpolated);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtrInterpolated); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtrInterpolated);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
@ -1105,11 +1124,11 @@ static void geo_process_object(struct Object *node) {
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp && gGlobalTimer != node->header.gfx.skipInterpolationTimestamp &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) { gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_matrix(mtxf, *node->header.gfx.throwMatrix, node->header.gfx.prevThrowMatrix); interpolate_matrix(mtxf, *node->header.gfx.throwMatrix, node->header.gfx.prevThrowMatrix);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf,
gMatStackInterpolated[gMatStackIndex]); gMatStackPrev[gMatStackIndex]);
} else { } else {
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], (void *) node->header.gfx.throwMatrix, mtxf_mul(gMatStackPrev[gMatStackIndex + 1], (void *) node->header.gfx.throwMatrix,
gMatStackInterpolated[gMatStackIndex]); gMatStackPrev[gMatStackIndex]);
} }
mtxf_copy(node->header.gfx.prevThrowMatrix, *node->header.gfx.throwMatrix); mtxf_copy(node->header.gfx.prevThrowMatrix, *node->header.gfx.throwMatrix);
node->header.gfx.prevThrowMatrixTimestamp = gGlobalTimer; node->header.gfx.prevThrowMatrixTimestamp = gGlobalTimer;
@ -1126,7 +1145,7 @@ static void geo_process_object(struct Object *node) {
node->header.gfx.prevTimestamp = gGlobalTimer; node->header.gfx.prevTimestamp = gGlobalTimer;
mtxf_cylboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], mtxf_cylboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
node->header.gfx.pos, gCurGraphNodeCamera->roll); node->header.gfx.pos, gCurGraphNodeCamera->roll);
mtxf_cylboard(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex], mtxf_cylboard(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex],
posInterpolated, gCurGraphNodeCamera->roll); posInterpolated, gCurGraphNodeCamera->roll);
} else if ((node->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) && !(node->header.gfx.sharedChild && node->header.gfx.sharedChild->extraFlags & GRAPH_EXTRA_FORCE_3D)) { } else if ((node->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) && !(node->header.gfx.sharedChild && node->header.gfx.sharedChild->extraFlags & GRAPH_EXTRA_FORCE_3D)) {
Vec3f posInterpolated; Vec3f posInterpolated;
@ -1141,7 +1160,7 @@ static void geo_process_object(struct Object *node) {
node->header.gfx.prevTimestamp = gGlobalTimer; node->header.gfx.prevTimestamp = gGlobalTimer;
mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
node->header.gfx.pos, gCurGraphNodeCamera->roll); node->header.gfx.pos, gCurGraphNodeCamera->roll);
mtxf_billboard(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex], mtxf_billboard(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex],
posInterpolated, gCurGraphNodeCamera->roll); posInterpolated, gCurGraphNodeCamera->roll);
} else { } else {
Vec3f posInterpolated; Vec3f posInterpolated;
@ -1161,7 +1180,7 @@ static void geo_process_object(struct Object *node) {
mtxf_rotate_zxy_and_translate(mtxf, node->header.gfx.pos, node->header.gfx.angle); mtxf_rotate_zxy_and_translate(mtxf, node->header.gfx.pos, node->header.gfx.angle);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_rotate_zxy_and_translate(mtxf, posInterpolated, angleInterpolated); mtxf_rotate_zxy_and_translate(mtxf, posInterpolated, angleInterpolated);
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mtxf, gMatStackInterpolated[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
} }
if (gGlobalTimer == node->header.gfx.prevScaleTimestamp + 1 && if (gGlobalTimer == node->header.gfx.prevScaleTimestamp + 1 &&
@ -1176,10 +1195,10 @@ static void geo_process_object(struct Object *node) {
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1], mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1],
node->header.gfx.scale); node->header.gfx.scale);
mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex + 1], mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex + 1],
scaleInterpolated); scaleInterpolated);
node->header.gfx.throwMatrix = &gMatStack[++gMatStackIndex]; node->header.gfx.throwMatrix = &gMatStack[++gMatStackIndex];
node->header.gfx.throwMatrixInterpolated = &gMatStackInterpolated[gMatStackIndex]; node->header.gfx.throwMatrixInterpolated = &gMatStackPrev[gMatStackIndex];
node->header.gfx.cameraToObject[0] = gMatStack[gMatStackIndex][3][0]; node->header.gfx.cameraToObject[0] = gMatStack[gMatStackIndex][3][0];
node->header.gfx.cameraToObject[1] = gMatStack[gMatStackIndex][3][1]; node->header.gfx.cameraToObject[1] = gMatStack[gMatStackIndex][3][1];
node->header.gfx.cameraToObject[2] = gMatStack[gMatStackIndex][3][2]; node->header.gfx.cameraToObject[2] = gMatStack[gMatStackIndex][3][2];
@ -1197,8 +1216,8 @@ static void geo_process_object(struct Object *node) {
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx; gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]); mtxf_to_mtx(mtxInterpolated, gMatStackPrev[gMatStackIndex]);
gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated; gMatStackPrevFixed[gMatStackIndex] = mtxInterpolated;
if (node->header.gfx.sharedChild != NULL) { if (node->header.gfx.sharedChild != NULL) {
gCurGraphNodeObject = (struct GraphNodeObject *) node; gCurGraphNodeObject = (struct GraphNodeObject *) node;
node->header.gfx.sharedChild->parent = &node->header.gfx.node; node->header.gfx.sharedChild->parent = &node->header.gfx.node;
@ -1280,12 +1299,12 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
gMatStack[gMatStackIndex + 1][3][2] = gMatStack[gMatStackIndex][3][2]; gMatStack[gMatStackIndex + 1][3][2] = gMatStack[gMatStackIndex][3][2];
mtxf_mul(gMatStack[gMatStackIndex + 1], mat, gMatStack[gMatStackIndex + 1]); mtxf_mul(gMatStack[gMatStackIndex + 1], mat, gMatStack[gMatStackIndex + 1]);
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1], node->objNode->header.gfx.scale); mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1], node->objNode->header.gfx.scale);
mtxf_copy(gMatStackInterpolated[gMatStackIndex + 1], (void *) gCurGraphNodeObject->throwMatrixInterpolated); mtxf_copy(gMatStackPrev[gMatStackIndex + 1], (void *) gCurGraphNodeObject->throwMatrixInterpolated);
gMatStackInterpolated[gMatStackIndex + 1][3][0] = gMatStackInterpolated[gMatStackIndex][3][0]; gMatStackPrev[gMatStackIndex + 1][3][0] = gMatStackPrev[gMatStackIndex][3][0];
gMatStackInterpolated[gMatStackIndex + 1][3][1] = gMatStackInterpolated[gMatStackIndex][3][1]; gMatStackPrev[gMatStackIndex + 1][3][1] = gMatStackPrev[gMatStackIndex][3][1];
gMatStackInterpolated[gMatStackIndex + 1][3][2] = gMatStackInterpolated[gMatStackIndex][3][2]; gMatStackPrev[gMatStackIndex + 1][3][2] = gMatStackPrev[gMatStackIndex][3][2];
mtxf_mul(gMatStackInterpolated[gMatStackIndex + 1], mat, gMatStackInterpolated[gMatStackIndex + 1]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mat, gMatStackPrev[gMatStackIndex + 1]);
mtxf_scale_vec3f(gMatStackInterpolated[gMatStackIndex + 1], gMatStackInterpolated[gMatStackIndex + 1], mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex + 1],
scaleInterpolated); scaleInterpolated);
if (node->fnNode.func != NULL) { if (node->fnNode.func != NULL) {
node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node, (struct AllocOnlyPool *) gMatStack[gMatStackIndex + 1]); node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node, (struct AllocOnlyPool *) gMatStack[gMatStackIndex + 1]);
@ -1442,7 +1461,6 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
if (node->node.flags & GRAPH_RENDER_ACTIVE) { if (node->node.flags & GRAPH_RENDER_ACTIVE) {
Vp *viewport = alloc_display_list(sizeof(*viewport)); Vp *viewport = alloc_display_list(sizeof(*viewport));
if (viewport == NULL) { return; } if (viewport == NULL) { return; }
Vp *viewportInterpolated = viewport;
gDisplayListHeap = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool), MEMORY_POOL_LEFT); gDisplayListHeap = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool), MEMORY_POOL_LEFT);
@ -1456,29 +1474,29 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
if (b != NULL) { if (b != NULL) {
clear_frame_buffer(clearColor); clear_frame_buffer(clearColor);
viewportInterpolated = alloc_display_list(sizeof(*viewportInterpolated));
if (viewportInterpolated == NULL) { return; }
interpolate_vectors_s16(viewportInterpolated->vp.vtrans, sPrevViewport.vp.vtrans, b->vp.vtrans);
interpolate_vectors_s16(viewportInterpolated->vp.vscale, sPrevViewport.vp.vscale, b->vp.vscale);
sViewportPos = gDisplayListHead; sViewportClipPos = gDisplayListHead;
make_viewport_clip_rect(viewportInterpolated); make_viewport_clip_rect(&sViewportPrev);
*viewport = *b; *viewport = *b;
} else if (c != NULL) { } else if (c != NULL) {
clear_frame_buffer(clearColor); clear_frame_buffer(clearColor);
make_viewport_clip_rect(c); make_viewport_clip_rect(c);
} }
sPrevViewport = *viewport;
mtxf_identity(gMatStack[gMatStackIndex]); mtxf_identity(gMatStack[gMatStackIndex]);
mtxf_to_mtx(initialMatrix, gMatStack[gMatStackIndex]); mtxf_to_mtx(initialMatrix, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = initialMatrix; gMatStackFixed[gMatStackIndex] = initialMatrix;
mtxf_identity(gMatStackInterpolated[gMatStackIndex]); sViewport = viewport;
gMatStackInterpolatedFixed[gMatStackIndex] = initialMatrix; sViewportPos = gDisplayListHead;
gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(viewportInterpolated)); // vvv 60 FPS PATCH vvv
mtxf_identity(gMatStackPrev[gMatStackIndex]);
gMatStackPrevFixed[gMatStackIndex] = initialMatrix;
// ^^^ ^^^
gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&sViewportPrev));
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(gMatStackFixed[gMatStackIndex]), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(gMatStackFixed[gMatStackIndex]), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gCurGraphNodeRoot = node; gCurGraphNodeRoot = node;

View File

@ -39,18 +39,24 @@ extern bool dynos_warp_to_level(s32 aLevel, s32 aArea, s32 aAct);
static void debug_warp_level1() { static void debug_warp_level1() {
// warp to credits // warp to credits
//set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0); set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0);
//return; return;
dynos_warp_to_level(LEVEL_BOB, 1, 1); dynos_warp_to_level(LEVEL_BOB, 1, 1);
} }
static void debug_warp_level2() { static void debug_warp_level2() {
dynos_warp_to_level(gCurrLevelNum, gCurrAreaIndex^3, 1); extern f32 gGameSpeed;
gGameSpeed = MAX(gGameSpeed - 0.1f, 0.1f);
printf("GAME SPEED: %f\n", gGameSpeed);
//dynos_warp_to_level(gCurrLevelNum, gCurrAreaIndex^3, 1);
} }
static void debug_warp_level3() { static void debug_warp_level3() {
dynos_warp_to_level(LEVEL_CASTLE_GROUNDS, 1, 1); extern f32 gGameSpeed;
gGameSpeed = MIN(gGameSpeed + 0.1f, 10.0f);
printf("GAME SPEED: %f\n", gGameSpeed);
//dynos_warp_to_level(LEVEL_CASTLE_GROUNDS, 1, 1);
} }
static void debug_grand_star(void) { static void debug_grand_star(void) {

View File

@ -247,6 +247,7 @@ static void gfx_sdl_set_keyboard_callbacks(kb_callback_t on_key_down, kb_callbac
} }
static bool gfx_sdl_start_frame(void) { static bool gfx_sdl_start_frame(void) {
return true;
f64 curTime = clock_elapsed_f64(); f64 curTime = clock_elapsed_f64();
f64 frameTime = config60Fps ? (sFrameTime / 2.0) : sFrameTime; f64 frameTime = config60Fps ? (sFrameTime / 2.0) : sFrameTime;
if (curTime > sFrameTargetTime) { if (curTime > sFrameTargetTime) {
@ -260,6 +261,7 @@ static bool gfx_sdl_start_frame(void) {
} }
static inline void sync_framerate_with_timer(void) { static inline void sync_framerate_with_timer(void) {
return;
f64 curTime = clock_elapsed_f64(); f64 curTime = clock_elapsed_f64();
if (curTime < sFrameTargetTime) { if (curTime < sFrameTargetTime) {
u32 delayMs = (sFrameTargetTime - curTime) * 1000.0; u32 delayMs = (sFrameTargetTime - curTime) * 1000.0;

View File

@ -48,6 +48,7 @@
#include "pc/network/version.h" #include "pc/network/version.h"
#include "pc/network/network_player.h" #include "pc/network/network_player.h"
#include "pc/djui/djui.h" #include "pc/djui/djui.h"
#include "pc/utils/misc.h"
#include "pc/mods/mods.h" #include "pc/mods/mods.h"
@ -63,6 +64,8 @@ s8 gShowDebugText;
s32 gRumblePakPfs; s32 gRumblePakPfs;
u32 gNumVblanks = 0; u32 gNumVblanks = 0;
f32 gGameSpeed = 1.0f; // DO NOT COMMIT
static struct AudioAPI *audio_api; static struct AudioAPI *audio_api;
struct GfxWindowManagerAPI *wm_api; struct GfxWindowManagerAPI *wm_api;
static struct GfxRenderingAPI *rendering_api; static struct GfxRenderingAPI *rendering_api;
@ -94,8 +97,13 @@ void send_display_list(struct SPTask *spTask) {
#define SAMPLES_LOW 528 #define SAMPLES_LOW 528
#endif #endif
static inline void patch_interpolations(void) { static void patch_interpolations_before(void) {
extern void mtx_patch_interpolated(void); extern void mtx_patch_before(void);
mtx_patch_before();
}
static inline void patch_interpolations(f32 delta) {
extern void mtx_patch_interpolated(f32 delta);
extern void patch_screen_transition_interpolated(void); extern void patch_screen_transition_interpolated(void);
extern void patch_title_screen_scales(void); extern void patch_title_screen_scales(void);
extern void patch_interpolated_dialog(void); extern void patch_interpolated_dialog(void);
@ -104,19 +112,44 @@ static inline void patch_interpolations(void) {
extern void patch_interpolated_bubble_particles(void); extern void patch_interpolated_bubble_particles(void);
extern void patch_interpolated_snow_particles(void); extern void patch_interpolated_snow_particles(void);
extern void djui_render_patch(void); extern void djui_render_patch(void);
mtx_patch_interpolated(); mtx_patch_interpolated(delta);
patch_screen_transition_interpolated(); /*patch_screen_transition_interpolated();
patch_title_screen_scales(); patch_title_screen_scales();
patch_interpolated_dialog(); patch_interpolated_dialog();
patch_interpolated_hud(); patch_interpolated_hud();
patch_interpolated_paintings(); patch_interpolated_paintings();
patch_interpolated_bubble_particles(); patch_interpolated_bubble_particles();
patch_interpolated_snow_particles(); patch_interpolated_snow_particles();
djui_render_patch(); djui_render_patch();*/
}
void produce_uncapped_frames(void) {
#define FRAMERATE 30
static const f64 sFrameTime = (1.0 / ((double)FRAMERATE));
static f64 sFrameTargetTime = 0;
f64 startTime = clock_elapsed_f64();
f64 curTime = startTime;
u64 frames = 0;
while ((curTime = clock_elapsed_f64()) < sFrameTargetTime) {
gfx_start_frame();
f32 delta = (curTime - startTime) / (sFrameTargetTime - startTime);
patch_interpolations(delta);
send_display_list(gGfxSPTask);
gfx_end_frame();
frames++;
}
printf(">> frames %llu | %f\n", frames, gGameSpeed);
fflush(stdout);
sFrameTargetTime += sFrameTime * gGameSpeed;
} }
void produce_one_frame(void) { void produce_one_frame(void) {
network_update(); network_update();
patch_interpolations_before();
gfx_start_frame(); gfx_start_frame();
const f32 master_mod = (f32)configMasterVolume / 127.0f; const f32 master_mod = (f32)configMasterVolume / 127.0f;
@ -145,11 +178,9 @@ void produce_one_frame(void) {
gfx_end_frame(); gfx_end_frame();
// uncapped
if (config60Fps) { if (config60Fps) {
gfx_start_frame(); produce_uncapped_frames();
patch_interpolations();
send_display_list(gGfxSPTask);
gfx_end_frame();
} }
} }

View File

@ -113,3 +113,25 @@ next_get:
*buffer = '\0'; *buffer = '\0';
} }
/////////////////
f32 delta_interpolate_f32(f32 start, f32 end, f32 delta) {
return start * (1.0f - delta) + end * delta;
}
void delta_interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b, f32 delta) {
f32 antiDelta = 1.0f - delta;
res[0] = ((a[0] * antiDelta) + (b[0] * delta));
res[1] = ((a[1] * antiDelta) + (b[1] * delta));
res[2] = ((a[2] * antiDelta) + (b[2] * delta));
}
void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta) {
f32 antiDelta = 1.0f - delta;
for (s32 i = 0; i < 4; i++) {
for (s32 j = 0; j < 4; j++) {
out->m[i][j] = (a->m[i][j] * antiDelta) + (b->m[i][j] * delta);
}
}
}

View File

@ -2,12 +2,20 @@
#define UTILS_MISC_H #define UTILS_MISC_H
#include <stdio.h> #include <stdio.h>
#include "types.h"
#include "PR/gbi.h"
float smoothstep(float edge0, float edge1, float x); float smoothstep(float edge0, float edge1, float x);
void update_all_mario_stars(void); void update_all_mario_stars(void);
f32 clock_elapsed(void); f32 clock_elapsed(void);
f64 clock_elapsed_f64(void); f64 clock_elapsed_f64(void);
u32 clock_elapsed_ticks(void); u32 clock_elapsed_ticks(void);
void file_get_line(char* buffer, size_t maxLength, FILE* fp); void file_get_line(char* buffer, size_t maxLength, FILE* fp);
f32 delta_interpolate_f32(f32 start, f32 end, f32 delta);
void delta_interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b, f32 delta);
void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta);
#endif #endif