diff --git a/include/types.h b/include/types.h index 1e1f0928..f54d6c10 100644 --- a/include/types.h +++ b/include/types.h @@ -152,7 +152,7 @@ struct GraphNodeObject /*0x50*/ Mat4 *throwMatrix; // matrix ptr Mat4 prevThrowMatrix; u32 prevThrowMatrixTimestamp; - Mat4 *throwMatrixInterpolated; + Mat4 *throwMatrixPrev; /*0x54*/ Vec3f cameraToObject; u32 skipInterpolationTimestamp; }; diff --git a/src/engine/graph_node.c b/src/engine/graph_node.c index 9de10590..bda0445a 100644 --- a/src/engine/graph_node.c +++ b/src/engine/graph_node.c @@ -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; } diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index a44689a7..fc56ebe7 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -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. diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 5c1ff50a..f6c9d790 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -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; } diff --git a/src/game/envfx_bubbles.c b/src/game/envfx_bubbles.c index b708fc44..ac34ddb4 100644 --- a/src/game/envfx_bubbles.c +++ b/src/game/envfx_bubbles.c @@ -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); diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 405e260c..62b8ea0a 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -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]); } diff --git a/src/menu/intro_geo.c b/src/menu/intro_geo.c index d270d419..32368bd7 100644 --- a/src/menu/intro_geo.c +++ b/src/menu/intro_geo.c @@ -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; diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index c0857312..3d362c51 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -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 }, }; diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index f937ac0a..af1322ed 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -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(); diff --git a/src/pc/utils/misc.c b/src/pc/utils/misc.c index e0357e89..edadf720 100644 --- a/src/pc/utils/misc.c +++ b/src/pc/utils/misc.c @@ -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); } } -} \ No newline at end of file +} + +/* + +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]); +} +*/ \ No newline at end of file