WIP: uncapped framerate 2

This commit is contained in:
MysterD 2022-04-26 22:42:57 -07:00
parent da0d4b3733
commit cca8cdc860
10 changed files with 172 additions and 208 deletions

View file

@ -152,7 +152,7 @@ struct GraphNodeObject
/*0x50*/ Mat4 *throwMatrix; // matrix ptr
Mat4 prevThrowMatrix;
u32 prevThrowMatrixTimestamp;
Mat4 *throwMatrixInterpolated;
Mat4 *throwMatrixPrev;
/*0x54*/ Vec3f cameraToObject;
u32 skipInterpolationTimestamp;
};

View file

@ -290,6 +290,7 @@ struct GraphNodeScale *init_graph_node_scale(struct AllocOnlyPool *pool,
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_SCALE);
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
graphNode->scale = scale;
graphNode->prevScale = scale;
graphNode->displayList = displayList;
}

View file

@ -197,7 +197,7 @@ struct GraphNodeCamera
Vec3f prevFocus;
u32 prevTimestamp;
/*0x34*/ Mat4 *matrixPtr; // pointer to look-at matrix of this camera as a Mat4
Mat4 *matrixPtrInterpolated;
Mat4 *matrixPtrPrev;
/*0x38*/ s16 roll; // roll in look at matrix. Doesn't account for light direction unlike rollScreen.
/*0x3A*/ s16 rollScreen; // rolls screen while keeping the light direction consistent
};
@ -290,6 +290,7 @@ struct GraphNodeScale
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x18*/ f32 scale;
/*????*/ f32 prevScale;
};
/** GraphNode that draws a shadow under an object.

View file

@ -412,8 +412,6 @@ f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometr
return floorHeight;
}
u8 gInterpolatingSurfaces;
/**
* Iterate through the list of floors and find the first floor under a given point.
*/
@ -424,14 +422,12 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
f32 oo;
f32 height;
struct Surface *floor = NULL;
s32 interpolate;
// Iterate through the list of floors until there are no more floors.
while (surfaceNode != NULL) {
surf = surfaceNode->surface;
if (surf == NULL) { break; }
surfaceNode = surfaceNode->next;
interpolate = gInterpolatingSurfaces && surf->modifiedTimestamp == gGlobalTimer;
if (gCheckingSurfaceCollisionsForObject != NULL) {
if (surf->object != gCheckingSurfaceCollisionsForObject) {
@ -443,20 +439,6 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
z1 = surf->vertex1[2];
x2 = surf->vertex2[0];
z2 = surf->vertex2[2];
if (interpolate) {
f32 diff = (surf->prevVertex1[0] - x1) * (surf->prevVertex1[0] - x1);
diff += (surf->prevVertex1[1] - surf->vertex1[1]) * (surf->prevVertex1[1] - surf->vertex1[1]);
diff += (surf->prevVertex1[2] - z1) * (surf->prevVertex1[2] - z1);
//printf("%f\n", sqrtf(diff));
if (diff > 10000) {
interpolate = FALSE;
} else {
x1 = (surf->prevVertex1[0] + x1) / 2;
z1 = (surf->prevVertex1[2] + z1) / 2;
x2 = (surf->prevVertex2[0] + x2) / 2;
z2 = (surf->prevVertex2[2] + z2) / 2;
}
}
// Check that the point is within the triangle bounds.
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) < 0) {
@ -466,10 +448,6 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
// To slightly save on computation time, set this later.
x3 = surf->vertex3[0];
z3 = surf->vertex3[2];
if (interpolate) {
x3 = (surf->prevVertex3[0] + x3) / 2;
z3 = (surf->prevVertex3[2] + z3) / 2;
}
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) < 0) {
continue;
@ -489,30 +467,10 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
continue;
}
if (interpolate) {
f32 y1, y2, y3;
f32 mag;
y1 = (surf->prevVertex1[1] + surf->vertex1[1]) / 2;
y2 = (surf->prevVertex2[1] + surf->vertex2[1]) / 2;
y3 = (surf->prevVertex3[1] + surf->vertex3[1]) / 2;
nx = (y2 - y1) * (z3 - z2) - (z2 - z1) * (y3 - y2);
ny = (z2 - z1) * (x3 - x2) - (x2 - x1) * (z3 - z2);
nz = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2);
mag = sqrtf(nx * nx + ny * ny + nz * nz);
if (mag < 0.0001) {
continue;
}
mag = (f32)(1.0 / mag);
nx *= mag;
ny *= mag;
nz *= mag;
oo = -(nx * x1 + ny * y1 + nz * z1);
} else {
nx = surf->normal.x;
ny = surf->normal.y;
nz = surf->normal.z;
oo = surf->originOffset;
}
nx = surf->normal.x;
ny = surf->normal.y;
nz = surf->normal.z;
oo = surf->originOffset;
// If a wall, ignore it. Likely a remnant, should never occur.
if (ny == 0.0f) {
@ -530,15 +488,6 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
*pheight = height;
}
if (interpolate) {
static struct Surface s;
s.type = surf->type;
s.normal.x = nx;
s.normal.y = ny;
s.normal.z = nz;
s.originOffset = oo;
return &s;
}
floor = surf;
break;
}

View file

@ -511,9 +511,13 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro
rotate_triangle_vertices(vertex1, vertex2, vertex3, pitch, yaw);
if (gGlobalTimer == prevTimestamp + 1) {
interpolate_vectors_s16(interpolatedVertices[0], prevVertex1, vertex1);
interpolate_vectors_s16(interpolatedVertices[1], prevVertex2, vertex2);
interpolate_vectors_s16(interpolatedVertices[2], prevVertex3, vertex3);
// TODO: fixme
//interpolate_vectors_s16(interpolatedVertices[0], prevVertex1, vertex1);
vec3s_copy(interpolatedVertices[0], vertex1);
//interpolate_vectors_s16(interpolatedVertices[1], prevVertex2, vertex2);
vec3s_copy(interpolatedVertices[1], vertex2);
//interpolate_vectors_s16(interpolatedVertices[2], prevVertex3, vertex3);
vec3s_copy(interpolatedVertices[2], vertex3);
}
vec3s_copy(prevVertex1, vertex1);
vec3s_copy(prevVertex2, vertex2);

View file

@ -187,7 +187,9 @@ void mtx_patch_interpolated(f32 delta) {
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);
gSPDisplayList(pos++, gMtxTbl[i].displayList);
if (delta >= 0.5f) {
gSPDisplayList(pos++, gMtxTbl[i].displayList);
}
}
}
@ -405,46 +407,11 @@ static void geo_process_switch(struct GraphNodeSwitchCase *node) {
}
}
void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b) {
res[0] = (a[0] + b[0]) / 2.0f;
res[1] = (a[1] + b[1]) / 2.0f;
res[2] = (a[2] + b[2]) / 2.0f;
}
void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b) {
res[0] = (a[0] + b[0]) / 2;
res[1] = (a[1] + b[1]) / 2;
res[2] = (a[2] + b[2]) / 2;
}
static s16 interpolate_angle(s16 a, s16 b) {
s32 absDiff = b - a;
if (absDiff < 0) {
absDiff = -absDiff;
}
if (absDiff >= 0x4000 && absDiff <= 0xC000) {
return b;
}
if (absDiff <= 0x8000) {
return (a + b) / 2;
} else {
return (a + b) / 2 + 0x8000;
}
}
static void interpolate_angles(Vec3s res, Vec3s a, Vec3s b) {
res[0] = interpolate_angle(a[0], b[0]);
res[1] = interpolate_angle(a[1], b[1]);
res[2] = interpolate_angle(a[2], b[2]);
}
/**
* Process a camera node.
*/
static void geo_process_camera(struct GraphNodeCamera *node) {
Mat4 cameraTransform;
Vec3f posInterpolated;
Vec3f focusInterpolated;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -463,28 +430,16 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
mtxf_mul(gMatStack[gMatStackIndex + 1], cameraTransform, gMatStack[gMatStackIndex]);
if (gGlobalTimer == node->prevTimestamp + 1 && gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->prevPos, node->pos);
interpolate_vectors(focusInterpolated, node->prevFocus, node->focus);
float magnitude = 0;
for (s32 i = 0; i < 3; i++) {
float diff = node->pos[i] - node->prevPos[i];
magnitude += diff * diff;
}
if (magnitude > 500000) {
// Observed ~479000 in BBH when toggling R camera
// Can get over 3 million in VCUTM though...
vec3f_copy(posInterpolated, node->pos);
vec3f_copy(focusInterpolated, node->focus);
}
mtxf_lookat(cameraTransform, node->prevPos, node->prevFocus, node->roll);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], cameraTransform, gMatStackPrev[gMatStackIndex]);
} else {
vec3f_copy(posInterpolated, node->pos);
vec3f_copy(focusInterpolated, node->focus);
mtxf_lookat(cameraTransform, node->pos, node->focus, node->roll);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], cameraTransform, gMatStackPrev[gMatStackIndex]);
}
vec3f_copy(node->prevPos, node->pos);
vec3f_copy(node->prevFocus, node->focus);
node->prevTimestamp = gGlobalTimer;
mtxf_lookat(cameraTransform, posInterpolated, focusInterpolated, node->roll);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], cameraTransform, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; }
@ -492,7 +447,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
if (node->fnNode.node.children != 0) {
gCurGraphNodeCamera = node;
node->matrixPtr = &gMatStack[gMatStackIndex];
node->matrixPtrInterpolated = &gMatStackPrev[gMatStackIndex];
node->matrixPtrPrev = &gMatStackPrev[gMatStackIndex];
geo_process_node_and_siblings(node->fnNode.node.children);
gCurGraphNodeCamera = NULL;
}
@ -565,20 +520,21 @@ static void geo_process_translation(struct GraphNodeTranslation *node) {
*/
static void geo_process_rotation(struct GraphNodeRotation *node) {
Mat4 mtxf;
Vec3s rotationInterpolated;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
if (gGlobalTimer == node->prevTimestamp + 1) {
interpolate_angles(rotationInterpolated, node->prevRotation, node->rotation);
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, rotationInterpolated);
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->prevRotation);
} else {
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->rotation);
}
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
vec3s_copy(node->prevRotation, node->rotation);
node->prevTimestamp = gGlobalTimer;
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; }
@ -599,13 +555,17 @@ static void geo_process_rotation(struct GraphNodeRotation *node) {
*/
static void geo_process_scale(struct GraphNodeScale *node) {
Vec3f scaleVec;
Vec3f prevScaleVec;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
vec3f_set(scaleVec, node->scale, node->scale, node->scale);
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], scaleVec);
mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex], scaleVec);
vec3f_set(prevScaleVec, node->prevScale, node->prevScale, node->prevScale);
mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex], prevScaleVec);
node->prevScale = node->scale;
// Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; }
@ -701,38 +661,33 @@ static void geo_process_generated_list(struct GraphNodeGenerated *node) {
*/
static void geo_process_background(struct GraphNodeBackground *node) {
Gfx *list = NULL;
Gfx *listInterpolated = NULL;
Gfx *listPrev = NULL;
if (node->fnNode.func != NULL) {
Vec3f posCopy;
Vec3f focusCopy;
Vec3f posInterpolated;
Vec3f focusInterpolated;
if (gGlobalTimer == node->prevCameraTimestamp + 1 &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->prevCameraPos, gLakituState.pos);
interpolate_vectors(focusInterpolated, node->prevCameraFocus, gLakituState.focus);
} else {
vec3f_copy(posInterpolated, gLakituState.pos);
vec3f_copy(focusInterpolated, gLakituState.focus);
}
vec3f_copy(node->prevCameraPos, gLakituState.pos);
vec3f_copy(node->prevCameraFocus, gLakituState.focus);
node->prevCameraTimestamp = gGlobalTimer;
list = node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node,
(struct AllocOnlyPool *) gMatStack[gMatStackIndex]);
vec3f_copy(posCopy, gLakituState.pos);
vec3f_copy(focusCopy, gLakituState.focus);
vec3f_copy(gLakituState.pos, posInterpolated);
vec3f_copy(gLakituState.focus, focusInterpolated);
listInterpolated = node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, NULL);
if (gGlobalTimer == node->prevCameraTimestamp + 1 &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
vec3f_copy(gLakituState.pos, node->prevCameraPos);
vec3f_copy(gLakituState.focus, node->prevCameraFocus);
}
listPrev = node->fnNode.func(GEO_CONTEXT_RENDER, &node->fnNode.node, NULL);
vec3f_copy(gLakituState.pos, posCopy);
vec3f_copy(gLakituState.focus, focusCopy);
vec3f_copy(node->prevCameraPos, gLakituState.pos);
vec3f_copy(node->prevCameraFocus, gLakituState.focus);
node->prevCameraTimestamp = gGlobalTimer;
}
if (list != NULL) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(list), (void *) VIRTUAL_TO_PHYSICAL(listInterpolated), node->fnNode.node.flags >> 8);
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(list), (void *) VIRTUAL_TO_PHYSICAL(listPrev), node->fnNode.node.flags >> 8);
} else if (gCurGraphNodeMasterList != NULL) {
#ifndef F3DEX_GBI_2E
Gfx *gfxStart = alloc_display_list(sizeof(Gfx) * 7);
@ -807,8 +762,8 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
Mat4 matrix;
Vec3s rotation;
Vec3f translation;
Vec3s rotationInterpolated;
Vec3f translationInterpolated;
Vec3s rotationPrev;
Vec3f translationPrev;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -818,17 +773,17 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
vec3s_copy(rotation, gVec3sZero);
vec3f_set(translation, node->translation[0], node->translation[1], node->translation[2]);
vec3s_copy(rotationInterpolated, rotation);
vec3f_copy(translationInterpolated, translation);
anim_process(translationInterpolated, rotationInterpolated, &animType, gPrevAnimFrame, &animAttribute);
vec3s_copy(rotationPrev, rotation);
vec3f_copy(translationPrev, translation);
anim_process(translationPrev, rotationPrev, &animType, gPrevAnimFrame, &animAttribute);
anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
interpolate_vectors(translationInterpolated, translationInterpolated, translation);
interpolate_angles(rotationInterpolated, rotationInterpolated, rotation);
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
mtxf_rotate_xyz_and_translate(matrix, translationInterpolated, rotationInterpolated);
mtxf_rotate_xyz_and_translate(matrix, translationPrev, rotationPrev);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return.
@ -900,7 +855,7 @@ void geo_set_animation_globals(struct AnimInfo *node, s32 hasAnimation) {
static void geo_process_shadow(struct GraphNodeShadow *node) {
Mat4 mtxf;
Vec3f shadowPos;
Vec3f shadowPosInterpolated;
Vec3f shadowPosPrev;
Vec3f animOffset;
f32 shadowScale;
@ -945,51 +900,52 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
}
if (gCurGraphNodeHeldObject != NULL) {
if (gGlobalTimer == gCurGraphNodeHeldObject->prevShadowPosTimestamp + 1) {
interpolate_vectors(shadowPosInterpolated, gCurGraphNodeHeldObject->prevShadowPos, shadowPos);
vec3f_copy(shadowPosPrev, gCurGraphNodeHeldObject->prevShadowPos);
} else {
vec3f_copy(shadowPosInterpolated, shadowPos);
vec3f_copy(shadowPosPrev, shadowPos);
}
vec3f_copy(gCurGraphNodeHeldObject->prevShadowPos, shadowPos);
gCurGraphNodeHeldObject->prevShadowPosTimestamp = gGlobalTimer;
} else {
if (gGlobalTimer == gCurGraphNodeObject->prevShadowPosTimestamp + 1 &&
gGlobalTimer != gCurGraphNodeObject->skipInterpolationTimestamp &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(shadowPosInterpolated, gCurGraphNodeObject->prevShadowPos, shadowPos);
vec3f_copy(shadowPosPrev, gCurGraphNodeObject->prevShadowPos);
} else {
vec3f_copy(shadowPosInterpolated, shadowPos);
vec3f_copy(shadowPosPrev, shadowPos);
}
vec3f_copy(gCurGraphNodeObject->prevShadowPos, shadowPos);
gCurGraphNodeObject->prevShadowPosTimestamp = gGlobalTimer;
}
extern u8 gInterpolatingSurfaces;
gInterpolatingSurfaces = TRUE;
Gfx *shadowListInterpolated = create_shadow_below_xyz(shadowPosInterpolated[0], shadowPosInterpolated[1],
shadowPosInterpolated[2], shadowScale,
node->shadowSolidity, node->shadowType);
gInterpolatingSurfaces = FALSE;
Gfx *shadowListPrev = create_shadow_below_xyz(shadowPosPrev[0], shadowPosPrev[1],
shadowPosPrev[2], shadowScale,
node->shadowSolidity, node->shadowType);
Gfx *shadowList = create_shadow_below_xyz(shadowPos[0], shadowPos[1], shadowPos[2], shadowScale,
node->shadowSolidity, node->shadowType);
if (shadowListInterpolated != NULL && shadowList != NULL) {
if (shadowListPrev != NULL && shadowList != NULL) {
mtxf_translate(mtxf, shadowPos);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtr);
mtxf_translate(mtxf, shadowPosInterpolated);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtrInterpolated);
mtxf_translate(mtxf, shadowPosPrev);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtrPrev);
// Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; }
if (gShadowAboveWaterOrLava == TRUE) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList),
(void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 4);
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 4);
} else if (gMarioOnIceOrCarpet == TRUE) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList),
(void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 5);
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 5);
} else {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList),
(void *) VIRTUAL_TO_PHYSICAL(shadowListInterpolated), 6);
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 6);
}
gMatStackIndex--;
}
@ -1080,14 +1036,6 @@ static s32 obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) {
return TRUE;
}
static void interpolate_matrix(Mat4 result, Mat4 a, Mat4 b) {
for (s32 i = 0; i < 4; i++) {
for (s32 j = 0; j < 4; j++) {
result[i][j] = (a[i][j] + b[i][j]) / 2.0f;
}
}
}
/**
* Process an object node.
*/
@ -1097,7 +1045,7 @@ static void geo_process_object(struct Object *node) {
gCurGraphNodeProcessingObject = node;
Mat4 mtxf;
s32 hasAnimation = (node->header.gfx.node.flags & GRAPH_RENDER_HAS_ANIMATION) != 0;
Vec3f scaleInterpolated;
Vec3f scalePrev;
if (node->hookRender) {
smlua_call_event_hooks_object_param(HOOK_ON_OBJECT_RENDER, node);
@ -1118,87 +1066,102 @@ static void geo_process_object(struct Object *node) {
if (node->header.gfx.areaIndex == gCurGraphNodeRoot->areaIndex) {
if (node->header.gfx.throwMatrix != NULL) {
mtxf_mul(gMatStack[gMatStackIndex + 1], *node->header.gfx.throwMatrix,
gMatStack[gMatStackIndex]);
if (gGlobalTimer == node->header.gfx.prevThrowMatrixTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_matrix(mtxf, *node->header.gfx.throwMatrix, node->header.gfx.prevThrowMatrix);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf,
gMatStackPrev[gMatStackIndex]);
mtxf_copy(mtxf, node->header.gfx.prevThrowMatrix);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
} else {
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], (void *) node->header.gfx.throwMatrix,
gMatStackPrev[gMatStackIndex]);
}
mtxf_copy(node->header.gfx.prevThrowMatrix, *node->header.gfx.throwMatrix);
node->header.gfx.prevThrowMatrixTimestamp = gGlobalTimer;
} else if ((node->header.gfx.node.flags & GRAPH_RENDER_CYLBOARD) && !(node->header.gfx.sharedChild && node->header.gfx.sharedChild->extraFlags & GRAPH_EXTRA_FORCE_3D)) {
Vec3f posInterpolated;
Vec3f posPrev;
if (gGlobalTimer == node->header.gfx.prevTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->header.gfx.prevPos, node->header.gfx.pos);
vec3f_copy(posPrev, node->header.gfx.prevPos);
} else {
vec3f_copy(posInterpolated, node->header.gfx.pos);
vec3f_copy(posPrev, node->header.gfx.pos);
}
vec3f_copy(node->header.gfx.prevPos, node->header.gfx.pos);
node->header.gfx.prevTimestamp = gGlobalTimer;
mtxf_cylboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
node->header.gfx.pos, gCurGraphNodeCamera->roll);
mtxf_cylboard(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex],
posInterpolated, gCurGraphNodeCamera->roll);
posPrev, 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)) {
Vec3f posInterpolated;
Vec3f posPrev;
if (gGlobalTimer == node->header.gfx.prevTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->header.gfx.prevPos, node->header.gfx.pos);
vec3f_copy(posPrev, node->header.gfx.prevPos);
} else {
vec3f_copy(posInterpolated, node->header.gfx.pos);
vec3f_copy(posPrev, node->header.gfx.pos);
}
vec3f_copy(node->header.gfx.prevPos, node->header.gfx.pos);
node->header.gfx.prevTimestamp = gGlobalTimer;
mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
node->header.gfx.pos, gCurGraphNodeCamera->roll);
mtxf_billboard(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex],
posInterpolated, gCurGraphNodeCamera->roll);
posPrev, gCurGraphNodeCamera->roll);
} else {
Vec3f posInterpolated;
Vec3s angleInterpolated;
Vec3f posPrev;
Vec3s anglePrev;
if (gGlobalTimer == node->header.gfx.prevTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(posInterpolated, node->header.gfx.prevPos, node->header.gfx.pos);
interpolate_angles(angleInterpolated, node->header.gfx.prevAngle, node->header.gfx.angle);
vec3f_copy(posPrev, node->header.gfx.prevPos);
vec3s_copy(anglePrev, node->header.gfx.prevAngle);
} else {
vec3f_copy(posInterpolated, node->header.gfx.pos);
vec3s_copy(angleInterpolated, node->header.gfx.angle);
vec3f_copy(posPrev, node->header.gfx.pos);
vec3s_copy(anglePrev, node->header.gfx.angle);
}
vec3f_copy(node->header.gfx.prevPos, node->header.gfx.pos);
vec3s_copy(node->header.gfx.prevAngle, node->header.gfx.angle);
node->header.gfx.prevTimestamp = gGlobalTimer;
mtxf_rotate_zxy_and_translate(mtxf, node->header.gfx.pos, node->header.gfx.angle);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_rotate_zxy_and_translate(mtxf, posInterpolated, angleInterpolated);
mtxf_rotate_zxy_and_translate(mtxf, posPrev, anglePrev);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
}
if (gGlobalTimer == node->header.gfx.prevScaleTimestamp + 1 &&
gGlobalTimer != node->header.gfx.skipInterpolationTimestamp &&
gGlobalTimer != gLakituState.skipCameraInterpolationTimestamp) {
interpolate_vectors(scaleInterpolated, node->header.gfx.prevScale, node->header.gfx.scale);
vec3f_copy(scalePrev, node->header.gfx.prevScale);
} else {
vec3f_copy(scaleInterpolated, node->header.gfx.scale);
vec3f_copy(scalePrev, node->header.gfx.scale);
}
vec3f_copy(node->header.gfx.prevScale, node->header.gfx.scale);
node->header.gfx.prevScaleTimestamp = gGlobalTimer;
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1],
node->header.gfx.scale);
mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex + 1],
scaleInterpolated);
scalePrev);
node->header.gfx.throwMatrix = &gMatStack[++gMatStackIndex];
node->header.gfx.throwMatrixInterpolated = &gMatStackPrev[gMatStackIndex];
node->header.gfx.throwMatrixPrev = &gMatStackPrev[gMatStackIndex];
node->header.gfx.cameraToObject[0] = gMatStack[gMatStackIndex][3][0];
node->header.gfx.cameraToObject[1] = gMatStack[gMatStackIndex][3][1];
node->header.gfx.cameraToObject[2] = gMatStack[gMatStackIndex][3][2];
@ -1211,13 +1174,14 @@ static void geo_process_object(struct Object *node) {
}
if (obj_is_in_view(&node->header.gfx, gMatStack[gMatStackIndex])) {
Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxInterpolated = alloc_display_list(sizeof(*mtxInterpolated));
if (mtx == NULL || mtxInterpolated == NULL) { return; }
Mtx *mtxPrev = alloc_display_list(sizeof(*mtxPrev));
if (mtx == NULL || mtxPrev == NULL) { return; }
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx;
mtxf_to_mtx(mtxInterpolated, gMatStackPrev[gMatStackIndex]);
gMatStackPrevFixed[gMatStackIndex] = mtxInterpolated;
mtxf_to_mtx(mtxPrev, gMatStackPrev[gMatStackIndex]);
gMatStackPrevFixed[gMatStackIndex] = mtxPrev;
if (node->header.gfx.sharedChild != NULL) {
gCurGraphNodeObject = (struct GraphNodeObject *) node;
node->header.gfx.sharedChild->parent = &node->header.gfx.node;
@ -1225,9 +1189,11 @@ static void geo_process_object(struct Object *node) {
node->header.gfx.sharedChild->parent = NULL;
gCurGraphNodeObject = NULL;
}
if (node->header.gfx.node.children != NULL) {
geo_process_node_and_siblings(node->header.gfx.node.children);
}
} else {
node->header.gfx.prevThrowMatrixTimestamp = 0;
node->header.gfx.prevTimestamp = 0;
@ -1237,7 +1203,7 @@ static void geo_process_object(struct Object *node) {
gMatStackIndex--;
gCurAnimType = ANIM_TYPE_NONE;
node->header.gfx.throwMatrix = NULL;
node->header.gfx.throwMatrixInterpolated = NULL;
node->header.gfx.throwMatrixPrev = NULL;
}
gCurGraphNodeProcessingObject = lastProcessingObject;
gCurGraphNodeMarioState = lastMarioState;
@ -1265,7 +1231,7 @@ static void geo_process_object_parent(struct GraphNodeObjectParent *node) {
void geo_process_held_object(struct GraphNodeHeldObject *node) {
Mat4 mat;
Vec3f translation;
Vec3f scaleInterpolated;
Vec3f scalePrev;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -1285,9 +1251,9 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
translation[2] = node->translation[2] / 4.0f;
if (gGlobalTimer == node->objNode->header.gfx.prevScaleTimestamp + 1) {
interpolate_vectors(scaleInterpolated, node->objNode->header.gfx.prevScale, node->objNode->header.gfx.scale);
vec3f_copy(scalePrev, node->objNode->header.gfx.prevScale);
} else {
vec3f_copy(scaleInterpolated, node->objNode->header.gfx.scale);
vec3f_copy(scalePrev, node->objNode->header.gfx.scale);
}
vec3f_copy(node->objNode->header.gfx.prevScale, node->objNode->header.gfx.scale);
node->objNode->header.gfx.prevScaleTimestamp = gGlobalTimer;
@ -1299,13 +1265,14 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
gMatStack[gMatStackIndex + 1][3][2] = gMatStack[gMatStackIndex][3][2];
mtxf_mul(gMatStack[gMatStackIndex + 1], mat, gMatStack[gMatStackIndex + 1]);
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1], node->objNode->header.gfx.scale);
mtxf_copy(gMatStackPrev[gMatStackIndex + 1], (void *) gCurGraphNodeObject->throwMatrixInterpolated);
mtxf_copy(gMatStackPrev[gMatStackIndex + 1], (void *) gCurGraphNodeObject->throwMatrixPrev);
gMatStackPrev[gMatStackIndex + 1][3][0] = gMatStackPrev[gMatStackIndex][3][0];
gMatStackPrev[gMatStackIndex + 1][3][1] = gMatStackPrev[gMatStackIndex][3][1];
gMatStackPrev[gMatStackIndex + 1][3][2] = gMatStackPrev[gMatStackIndex][3][2];
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mat, gMatStackPrev[gMatStackIndex + 1]);
mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex + 1],
scaleInterpolated);
scalePrev);
if (node->fnNode.func != NULL) {
node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node, (struct AllocOnlyPool *) gMatStack[gMatStackIndex + 1]);
}

View file

@ -120,7 +120,11 @@ Gfx *geo_title_screen(s32 state, struct GraphNode *sp54, UNUSED void *context) {
scaleZ = 0.0f;
}
vec3f_set(scale, scaleX, scaleY, scaleZ);
interpolate_vectors(scaleInterpolated, sIntroScale, scale);
// TODO: fixme
//interpolate_vectors(scaleInterpolated, sIntroScale, scale);
vec3f_copy(scaleInterpolated, scale);
vec3f_set(sIntroScale, scaleX, scaleY, scaleZ);
guScale(scaleMat, scaleInterpolated[0], scaleInterpolated[1], scaleInterpolated[2]);
sIntroScalePos = dlIter;

View file

@ -596,7 +596,7 @@ static struct LuaObjectField sGraphNodeObjectFields[LUA_GRAPH_NODE_OBJECT_FIELD_
{ "sharedChild", LVT_COBJECT_P, offsetof(struct GraphNodeObject, sharedChild), false, LOT_GRAPHNODE },
{ "skipInterpolationTimestamp", LVT_U32, offsetof(struct GraphNodeObject, skipInterpolationTimestamp), false, LOT_NONE },
// { "throwMatrix", LVT_???, offsetof(struct GraphNodeObject, throwMatrix), false, LOT_??? }, <--- UNIMPLEMENTED
// { "throwMatrixInterpolated", LVT_???, offsetof(struct GraphNodeObject, throwMatrixInterpolated), false, LOT_??? }, <--- UNIMPLEMENTED
// { "throwMatrixPrev", LVT_???, offsetof(struct GraphNodeObject, throwMatrixPrev), false, LOT_??? }, <--- UNIMPLEMENTED
{ "unk4C", LVT_COBJECT_P, offsetof(struct GraphNodeObject, unk4C), false, LOT_SPAWNINFO },
};

View file

@ -64,6 +64,7 @@ s8 gShowDebugText;
s32 gRumblePakPfs;
u32 gNumVblanks = 0;
f32 gRenderingDelta = 0;
f32 gGameSpeed = 1.0f; // DO NOT COMMIT
static struct AudioAPI *audio_api;
@ -133,7 +134,8 @@ void produce_uncapped_frames(void) {
u64 frames = 0;
while ((curTime = clock_elapsed_f64()) < sFrameTargetTime) {
gfx_start_frame();
f32 delta = (curTime - startTime) / (sFrameTargetTime - startTime);
f32 delta = MIN((curTime - startTime) / (sFrameTargetTime - startTime), 1);
gRenderingDelta = delta;
patch_interpolations(delta);
send_display_list(gGfxSPTask);
gfx_end_frame();

View file

@ -134,4 +134,40 @@ void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta) {
out->m[i][j] = (a->m[i][j] * antiDelta) + (b->m[i][j] * delta);
}
}
}
}
/*
void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b) {
res[0] = (a[0] + b[0]) / 2.0f;
res[1] = (a[1] + b[1]) / 2.0f;
res[2] = (a[2] + b[2]) / 2.0f;
}
void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b) {
res[0] = (a[0] + b[0]) / 2;
res[1] = (a[1] + b[1]) / 2;
res[2] = (a[2] + b[2]) / 2;
}
static s16 interpolate_angle(s16 a, s16 b) {
s32 absDiff = b - a;
if (absDiff < 0) {
absDiff = -absDiff;
}
if (absDiff >= 0x4000 && absDiff <= 0xC000) {
return b;
}
if (absDiff <= 0x8000) {
return (a + b) / 2;
} else {
return (a + b) / 2 + 0x8000;
}
}
static void interpolate_angles(Vec3s res, Vec3s a, Vec3s b) {
res[0] = interpolate_angle(a[0], b[0]);
res[1] = interpolate_angle(a[1], b[1]);
res[2] = interpolate_angle(a[2], b[2]);
}
*/