Frame interpolation (#78)

* Initial. Only enough to get it running. Missing changes to effects and actors.

* Add frame interp calls to most files in `code`

* Fix bubbles (The ones that look like bubbles)

* Fix kankyo and takkuri.

* Fix obj_grass interpolation

---------

Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
This commit is contained in:
louist103
2024-05-22 09:04:58 -05:00
committed by Garrett Cox
co-authored by Garrett Cox
parent 7573a9378c
commit ce17d97ac4
26 changed files with 1052 additions and 54 deletions
+71 -35
View File
@@ -43,7 +43,7 @@
#include "Extractor/Extract.h"
// OTRTODO
//#include <functions.h>
#include "2s2h/enhancements/interpolation/frame_interpolation.h"
#ifdef ENABLE_CROWD_CONTROL
#include "Enhancements/crowd-control/CrowdControl.h"
@@ -490,23 +490,67 @@ extern "C" void Graph_StartFrame() {
}
void RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements) {
//for (const auto& m : mtx_replacements) {
gfx_run(Commands, {});
for (const auto& m : mtx_replacements) {
gfx_run(Commands, m);
gfx_end_frame();
// }
}
}
// C->C++ Bridge
extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
#if 0
if (!audio.initialized) {
audio.initialized = true;
std::thread([]() {
for (;;) {
{
std::unique_lock<std::mutex> Lock(audio.mutex);
while (!audio.processing) {
audio.cv_to_thread.wait(Lock);
}
}
std::unique_lock<std::mutex> Lock(audio.mutex);
// AudioMgr_ThreadEntry(&gAudioMgr);
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
#define SAMPLES_HIGH 560
#define SAMPLES_LOW 528
// PAL values
//#define SAMPLES_HIGH 656
//#define SAMPLES_LOW 624
#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1)
#define NUM_AUDIO_CHANNELS 2
int samples_left = AudioPlayer_Buffered();
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
// printf("Audio samples: %d %u\n", samples_left, num_audio_samples);
// 3 is the maximum authentic frame divisor.
s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS),
num_audio_samples);
}
// for (uint32_t i = 0; i < 2 * num_audio_samples; i++) {
// audio_buffer[i] = Rand_Next() & 0xFF;
//}
// printf("Audio samples before submitting: %d\n", audio_api->buffered());
AudioPlayer_Play((u8*)audio_buffer,
num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
audio.processing = false;
audio.cv_from_thread.notify_one();
}
}).detach();
}
{
//std::unique_lock<std::mutex> Lock(audio.mutex);
//audio.processing = true;
std::unique_lock<std::mutex> Lock(audio.mutex);
audio.processing = true;
}
audio.cv_to_thread.notify_one();
#endif
//audio.cv_to_thread.notify_one();
std::vector<std::unordered_map<Mtx*, MtxF>> mtx_replacements;
int target_fps = 20;
//OTRGlobals::Instance->GetInterpolationFPS();
int target_fps = CVarGetInteger("gInterpolationFPS", 20);
static int last_fps;
static int last_update_rate;
static int time;
@@ -522,31 +566,29 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
}
// time_base = fps * original_fps (one second)
// int next_original_frame = fps;
int next_original_frame = fps;
//while (time + original_fps <= next_original_frame) {
// time += original_fps;
// if (time != next_original_frame) {
// mtx_replacements.push_back(FrameInterpolation_Interpolate((float)time / next_original_frame));
// } else {
// mtx_replacements.emplace_back();
// }
//}
while (time + original_fps <= next_original_frame) {
time += original_fps;
if (time != next_original_frame) {
mtx_replacements.push_back(FrameInterpolation_Interpolate((float)time / next_original_frame));
} else {
mtx_replacements.emplace_back();
}
}
//time -= fps;
time -= fps;
OTRGlobals::Instance->context->GetWindow()->SetTargetFps(original_fps);
// OTRGlobals::Instance->context->GetWindow()->SetTargetFps(20);
//OTRGlobals::Instance->context->GetWindow()->SetTargetFps(60);
OTRGlobals::Instance->context->GetWindow()->SetTargetFps(fps);
//int threshold = CVarGetInteger("gExtraLatencyThreshold", 80);
//OTRGlobals::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2
//: 1);
int threshold = CVarGetInteger("gExtraLatencyThreshold", 80);
OTRGlobals::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2
: 1);
RunCommands(commands, mtx_replacements);
//last_fps = fps;
//last_update_rate = R_UPDATE_RATE;
last_fps = fps;
last_update_rate = R_UPDATE_RATE;
//{
// std::unique_lock<std::mutex> Lock(audio.mutex);
@@ -554,16 +596,10 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
// audio.cv_from_thread.wait(Lock);
// }
//}
//
//if (ShouldClearTextureCacheAtEndOfFrame) {
// gfx_texture_cache_clear();
// LUS::SkeletonPatcher::UpdateSkeletons();
// ShouldClearTextureCacheAtEndOfFrame = false;
//}
// OTRTODO: FIGURE OUT END FRAME POINT
/* if (OTRGlobals::Instance->context->lastScancode != -1)
OTRGlobals::Instance->context->lastScancode = -1;*/
/* if (OTRGlobals::Instance->context->GetWindow()->lastScancode != -1)
OTRGlobals::Instance->context->GetWindow()->lastScancode = -1;*/
}
float divisor_num = 0.0f;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,61 @@
#pragma once
#include "include/z64math.h"
#ifdef __cplusplus
#include <unordered_map>
std::unordered_map<Mtx*, MtxF> FrameInterpolation_Interpolate(float step);
extern "C" {
#endif
void FrameInterpolation_StartRecord(void);
void FrameInterpolation_StopRecord(void);
void FrameInterpolation_RecordOpenChild(const void* a, int b);
void FrameInterpolation_RecordCloseChild(void);
void FrameInterpolation_DontInterpolateCamera(void);
int FrameInterpolation_GetCameraEpoch(void);
void FrameInterpolation_RecordActorPosRotMatrix(void);
void FrameInterpolation_RecordMatrixPush(void);
void FrameInterpolation_RecordMatrixPop(void);
void FrameInterpolation_RecordMatrixPut(MtxF* src);
void FrameInterpolation_RecordMatrixMult(MtxF* mf, u8 mode);
void FrameInterpolation_RecordMatrixTranslate(f32 x, f32 y, f32 z, u8 mode);
void FrameInterpolation_RecordMatrixScale(f32 x, f32 y, f32 z, u8 mode);
void FrameInterpolation_RecordMatrixRotate1Coord(u32 coord, f32 value, u8 mode);
void FrameInterpolation_RecordMatrixRotateZYX(s16 x, s16 y, s16 z, u8 mode);
void FrameInterpolation_RecordMatrixTranslateRotateZYX(Vec3f* translation, Vec3s* rotation);
void FrameInterpolation_RecordMatrixSetTranslateRotateYXZ(f32 translateX, f32 translateY, f32 translateZ, Vec3s* rot);
void FrameInterpolation_RecordMatrixMtxFToMtx(MtxF* src, Mtx* dest);
void FrameInterpolation_RecordMatrixToMtx(Mtx* dest, char* file, s32 line);
void FrameInterpolation_RecordMatrixReplaceRotation(MtxF* mf);
void FrameInterpolation_RecordMatrixRotateAxis(f32 angle, Vec3f* axis, u8 mode);
void FrameInterpolation_RecordSkinMatrixMtxFToMtx(MtxF* src, Mtx* dest);
#ifdef __cplusplus
}
#endif
+1
View File
@@ -182,6 +182,7 @@ file(GLOB_RECURSE soh__Enhancements RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
#source_group("soh\\Enhancements" REGULAR_EXPRESSION "soh/Enhancements/*")
#source_group("soh\\Enhancements\\audio" REGULAR_EXPRESSION "soh/Enhancements/audio/*")
source_group("2s2h\\Enhancements\\controls" REGULAR_EXPRESSION "2s2h/Enhancements/controls/*")
source_group("2s2h\\Enhancements\\interpolation" REGULAR_EXPRESSION "2s2h/Enhancements/interpolation/*")
#source_group("soh\\Enhancements\\cosmetics" REGULAR_EXPRESSION "soh/Enhancements/cosmetics/*")
#source_group("soh\\Enhancements\\crowd-control" REGULAR_EXPRESSION "soh/Enhancements/crowd-control/*")
#source_group("soh\\Enhancements\\custom-message" REGULAR_EXPRESSION "soh/Enhancements/custom-message/*")
+4
View File
@@ -265,6 +265,8 @@ extern Gfx gEmptyDL[];
// Use the DISP macros defined above when writing to display buffers.
#define OPEN_DISPS(gfxCtx) \
{ \
void FrameInterpolation_RecordOpenChild(const void* a, int b); \
FrameInterpolation_RecordOpenChild(__FILE__, __LINE__); \
GraphicsContext* __gfxCtx = gfxCtx; \
gDPNoOpOpenDisp(gfxCtx->polyOpa.p++, __FILE__, __LINE__); \
gDPNoOpOpenDisp(gfxCtx->polyXlu.p++, __FILE__, __LINE__); \
@@ -272,6 +274,8 @@ extern Gfx gEmptyDL[];
#define CLOSE_DISPS(gfxCtx) \
(void)0; \
void FrameInterpolation_RecordCloseChild(void); \
FrameInterpolation_RecordCloseChild(); \
gDPNoOpCloseDisp(gfxCtx->polyOpa.p++, __FILE__, __LINE__); \
gDPNoOpCloseDisp(gfxCtx->polyXlu.p++, __FILE__, __LINE__); \
gDPNoOpCloseDisp(gfxCtx->overlay.p++, __FILE__, __LINE__); \
+2 -2
View File
@@ -26,14 +26,14 @@
#define SEGMENT_END(segment) 0
//(_ ## segment ## SegmentEnd)
#define SEGMENT_SIZE(segment) (uintptr_t) NULL
#define SEGMENT_SIZE(segment) (uintptr_t) 0
//((uintptr_t)SEGMENT_END(segment) - (uintptr_t)SEGMENT_START(segment))
#define SEGMENT_ROM_START(segment) NULL
//(_ ## segment ## SegmentRomStart)
#define SEGMENT_ROM_END(segment) NULL
//(_ ## segment ## SegmentRomEnd)
#define SEGMENT_ROM_SIZE(segment) NULL
#define SEGMENT_ROM_SIZE(segment) 0
//((uintptr_t)SEGMENT_ROM_END(segment) - (uintptr_t)SEGMENT_ROM_START(segment))
#define SEGMENT_BSS_START(segment) 0
+9 -9
View File
@@ -297,15 +297,15 @@ typedef enum {
/* 3 */ PICTO_PHOTO_STATE_READY
} PictoPhotoState;
#define ROM_FILE(name) \
{ 0, 0, #name }
#define ROM_FILE_EMPTY \
{ 0, 0, "" }
#define ROM_FILE_UNSET \
{ 0 }
//#define ROM_FILE(name) \
// { 0, 0, #name }
//
//#define ROM_FILE_EMPTY \
// { 0, 0, "" }
//
//#define ROM_FILE_UNSET \
// { 0 }
//
#ifdef __cplusplus
}
#undef this
+1
View File
@@ -274,6 +274,7 @@ typedef struct EffectSs {
/* 0x5C */ s16 life; // -1 means this entry is free
/* 0x5E */ u8 priority; // Lower number mean higher priority
/* 0x5F */ u8 type;
u32 epoch;
} EffectSs; // size = 0x60
typedef struct {
+7 -2
View File
@@ -3,6 +3,7 @@
#include "z64.h"
#include <assert.h>
#include "BenPort.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
//#include <math.h>
#define SCREEN_WIDTH 320
@@ -713,7 +714,10 @@ void guOrthoF(float m[4][4], float l, float r, float b, float t, float n, float
void guOrtho(Mtx* m, float l, float r, float b, float t, float n, float f, float scale) {
float mf[4][4];
guOrthoF(mf, l, r, b, t, n, f, scale);
guMtxF2L(mf, m);
FrameInterpolation_RecordOpenChild("ortho", 0);
Matrix_MtxFToMtx((MtxF*)mf, m);
FrameInterpolation_RecordCloseChild();
//guMtxF2L(mf, m);
}
#define GU_PI 3.1415926
@@ -823,7 +827,8 @@ void guLookAt(Mtx* m, f32 xEye, f32 yEye, f32 zEye, f32 xAt, f32 yAt, f32 zAt, f
guLookAtF(mf, xEye, yEye, zEye, xAt, yAt, zAt, xUp, yUp, zUp);
guMtxF2L(mf, m);
Matrix_MtxFToMtx((MtxF*)mf, m);
//guMtxF2L(mf, m);
}
void guRotateF(float m[4][4], float a, float x, float y, float z) {
static float D_80097F90 = M_PI / 180.0f;
+20 -1
View File
@@ -41,6 +41,7 @@
#include "prevent_bss_reordering.h"
#include "global.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
/* data */
#define qs1616(e) ((s32)((e)*0x00010000))
@@ -102,6 +103,7 @@ void Matrix_Init(GameState* gameState) {
void Matrix_Push(void) {
MtxF* prev = sCurrentMatrix;
FrameInterpolation_RecordMatrixPush();
sCurrentMatrix++;
Matrix_MtxFCopy(sCurrentMatrix, prev);
}
@@ -112,6 +114,7 @@ void Matrix_Push(void) {
* @remark original name: "Matrix_pull"
*/
void Matrix_Pop(void) {
FrameInterpolation_RecordMatrixPop();
sCurrentMatrix--;
}
@@ -134,6 +137,7 @@ void Matrix_Get(MtxF* dest) {
* @remark original name: "Matrix_put"
*/
void Matrix_Put(MtxF* src) {
FrameInterpolation_RecordMatrixPut(src);
Matrix_MtxFCopy(sCurrentMatrix, src);
}
@@ -161,6 +165,7 @@ MtxF* Matrix_GetCurrent(void) {
* @remark original name: "Matrix_mult"
*/
void Matrix_Mult(MtxF* mf, MatrixMode mode) {
FrameInterpolation_RecordMatrixMult(mf, mode);
MtxF* cmf = Matrix_GetCurrent();
if (mode == MTXMODE_APPLY) {
@@ -194,6 +199,7 @@ void Matrix_Mult(MtxF* mf, MatrixMode mode) {
* @remark original name: "Matrix_translate"
*/
void Matrix_Translate(f32 x, f32 y, f32 z, MatrixMode mode) {
FrameInterpolation_RecordMatrixTranslate(x, y, z, mode);
MtxF* cmf = sCurrentMatrix;
f32 tempX;
f32 tempY;
@@ -240,6 +246,7 @@ void Matrix_Translate(f32 x, f32 y, f32 z, MatrixMode mode) {
* @remark original name: "Matrix_scale"
*/
void Matrix_Scale(f32 x, f32 y, f32 z, MatrixMode mode) {
FrameInterpolation_RecordMatrixScale(x, y, z, mode);
MtxF* cmf = sCurrentMatrix;
if (mode == MTXMODE_APPLY) {
@@ -376,6 +383,7 @@ void Matrix_RotateXS(s16 x, MatrixMode mode) {
* @remark original name may have been "Matrix_RotateX", but clashed with the previous function.
*/
void Matrix_RotateXF(f32 x, MatrixMode mode) {
FrameInterpolation_RecordMatrixRotate1Coord(0, x, mode);
MtxF* cmf;
f32 sin;
f32 cos;
@@ -643,6 +651,7 @@ void Matrix_RotateYS(s16 y, MatrixMode mode) {
* @remark original name may have been "Matrix_RotateY", but clashed with the previous function.
*/
void Matrix_RotateYF(f32 y, MatrixMode mode) {
FrameInterpolation_RecordMatrixRotate1Coord(1, y, mode);
MtxF* cmf;
f32 sin;
f32 cos;
@@ -825,6 +834,7 @@ void Matrix_RotateZS(s16 z, MatrixMode mode) {
* @remark original name may have been "Matrix_RotateZ", but clashed with the previous function.
*/
void Matrix_RotateZF(f32 z, MatrixMode mode) {
FrameInterpolation_RecordMatrixRotate1Coord(2, z, mode);
MtxF* cmf;
f32 sin;
f32 cos;
@@ -906,6 +916,7 @@ void Matrix_RotateZF(f32 z, MatrixMode mode) {
* @remark original name: "Matrix_RotateXYZ", changed to reflect rotation order.
*/
void Matrix_RotateZYX(s16 x, s16 y, s16 z, MatrixMode mode) {
FrameInterpolation_RecordMatrixRotateZYX(x, y, z, mode);
MtxF* cmf = sCurrentMatrix;
f32 temp1;
f32 temp2;
@@ -1005,6 +1016,7 @@ void Matrix_RotateZYX(s16 x, s16 y, s16 z, MatrixMode mode) {
* @remark original name appears to be "Matrix_softcv3_mult"
*/
void Matrix_TranslateRotateZYX(Vec3f* translation, Vec3s* rot) {
FrameInterpolation_RecordMatrixTranslateRotateZYX(translation, rot);
MtxF* cmf = sCurrentMatrix;
f32 sin = Math_SinS(rot->z);
f32 cos = Math_CosS(rot->z);
@@ -1156,6 +1168,7 @@ void Matrix_SetTranslateRotateYXZ(f32 x, f32 y, f32 z, Vec3s* rot) {
} else {
cmf->yx = 0.0f;
}
FrameInterpolation_RecordMatrixSetTranslateRotateYXZ(x, y, z, rot);
}
/**
@@ -1169,6 +1182,7 @@ void Matrix_SetTranslateRotateYXZ(f32 x, f32 y, f32 z, Vec3s* rot) {
* @remark original name: "_MtxF_to_Mtx"
*/
Mtx* Matrix_MtxFToMtx(MtxF* src, Mtx* dest) {
FrameInterpolation_RecordMatrixMtxFToMtx(src, dest);
// #Region 2S2H [Port] For compatibility with modern systems this has been changed to use guMtxF2L
guMtxF2L(src, dest);
return dest;
@@ -1186,7 +1200,10 @@ Mtx* Matrix_MtxFToMtx(MtxF* src, Mtx* dest) {
* @remark original name: "_Matrix_to_Mtx"
*/
Mtx* Matrix_ToMtx(Mtx* dest) {
return Matrix_MtxFToMtx(sCurrentMatrix, dest);
FrameInterpolation_RecordMatrixToMtx(dest, __FILE__, __LINE__);
guMtxF2L(sCurrentMatrix, dest);
return dest;
//return Matrix_MtxFToMtx(sCurrentMatrix, dest);
}
/**
@@ -1480,6 +1497,7 @@ void Matrix_Transpose(MtxF* mf) {
* @param[in] mf matrix whose linear part will replace the normalised part of A.
*/
void Matrix_ReplaceRotation(MtxF* mf) {
FrameInterpolation_RecordMatrixReplaceRotation(mf);
MtxF* cmf = sCurrentMatrix;
f32 acc;
f32 component;
@@ -1667,6 +1685,7 @@ void Matrix_MtxFToZYXRot(MtxF* src, Vec3s* dest, s32 nonUniformScale) {
* @remark original name may have been "Matrix_RotateVector", but clashed with the next function.
*/
void Matrix_RotateAxisF(f32 angle, Vec3f* axis, MatrixMode mode) {
FrameInterpolation_RecordMatrixRotateAxis(angle, axis, mode);
MtxF* cmf;
f32 sin;
f32 cos;
+10
View File
@@ -21,6 +21,7 @@
#include "objects/object_bdoor/object_bdoor.h"
#include <string.h>
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
// bss
// FaultClient sActorFaultClient; // 2 funcs
@@ -527,6 +528,8 @@ void Target_Draw(TargetContext* targetCtx, PlayState* play) {
s32 index;
f32 lockOnScaleX;
FrameInterpolation_RecordOpenChild(actor, 0);
if (targetCtx->rotZTick != 0) {
totalEntries = 1;
} else {
@@ -603,11 +606,14 @@ void Target_Draw(TargetContext* targetCtx, PlayState* play) {
}
}
}
FrameInterpolation_RecordCloseChild();
}
actor = targetCtx->arrowPointedActor;
if ((actor != NULL) && !(actor->flags & ACTOR_FLAG_CANT_LOCK_ON)) {
TatlColor* color = &sTatlColorList[actor->category];
FrameInterpolation_RecordOpenChild(actor, 0);
POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, SETUPDL_7);
@@ -619,6 +625,7 @@ void Target_Draw(TargetContext* targetCtx, PlayState* play) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, color->inner.r, color->inner.g, color->inner.b, 255);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_XLU_DISP++, gZTargetArrowDL);
FrameInterpolation_RecordCloseChild();
}
CLOSE_DISPS(play->state.gfxCtx);
@@ -2699,6 +2706,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
void Actor_Draw(PlayState* play, Actor* actor) {
Lights* light;
FrameInterpolation_RecordOpenChild(actor, 0);
OPEN_DISPS(play->state.gfxCtx);
light = LightContext_NewLights(&play->lightCtx, play->state.gfxCtx);
@@ -2710,6 +2718,7 @@ void Actor_Draw(PlayState* play, Actor* actor) {
(actor->flags & (ACTOR_FLAG_10000000 | ACTOR_FLAG_400000)) ? NULL : &actor->world.pos, play);
Lights_Draw(light, play->state.gfxCtx);
FrameInterpolation_RecordActorPosRotMatrix();
if (actor->flags & ACTOR_FLAG_IGNORE_QUAKE) {
Matrix_SetTranslateRotateYXZ(actor->world.pos.x + play->mainCamera.quakeOffset.x,
actor->world.pos.y +
@@ -2766,6 +2775,7 @@ void Actor_Draw(PlayState* play, Actor* actor) {
actor->isDrawn = true;
CLOSE_DISPS(play->state.gfxCtx);
FrameInterpolation_RecordCloseChild();
}
void Actor_UpdateFlaggedAudio(Actor* actor) {
+2 -1
View File
@@ -62,6 +62,7 @@ SwingAnimation D_801EDC30[4];
Vec3f D_801EDDD0;
Vec3f D_801EDDE0;
Vec3f D_801EDDF0;
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
// Camera will reload its paramData. Usually that means setting the read-only data from what is stored in
// CameraModeValue arrays. Although sometimes some read-write data is reset as well
@@ -6870,7 +6871,7 @@ s32 Camera_Special9(Camera* camera) {
if (doorParams->timer1 > 0) {
break;
}
FrameInterpolation_DontInterpolateCamera();
camera->animState++;
// Setup for the camera moving behind the door
+3
View File
@@ -1,5 +1,6 @@
#include "global.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2) {
EffectBlureElement* elem;
@@ -918,6 +919,7 @@ void EffectBlure_Draw(void* thisx, GraphicsContext* gfxCtx) {
s32 j;
s32 phi_t2;
FrameInterpolation_RecordOpenChild(this, 0);
OPEN_DISPS(gfxCtx);
gSPMatrix(POLY_XLU_DISP++, &gIdentityMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1027,4 +1029,5 @@ void EffectBlure_Draw(void* thisx, GraphicsContext* gfxCtx) {
}
CLOSE_DISPS(gfxCtx);
FrameInterpolation_RecordCloseChild();
}
+4
View File
@@ -3,6 +3,7 @@
#include "assets/code/eff_shield_particle/eff_shield_particle.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
void EffectShieldParticle_Init(void* thisx, void* initParamsx) {
EffectShieldParticle* this = (EffectShieldParticle*)thisx;
@@ -146,6 +147,8 @@ void EffectShieldParticle_Draw(void* thisx, GraphicsContext* gfxCtx) {
Color_RGBA8 primColor;
Color_RGBA8 envColor;
FrameInterpolation_RecordOpenChild(this, 0);
OPEN_DISPS(gfxCtx);
if (this != NULL) {
@@ -205,4 +208,5 @@ void EffectShieldParticle_Draw(void* thisx, GraphicsContext* gfxCtx) {
}
CLOSE_DISPS(gfxCtx);
FrameInterpolation_RecordCloseChild();
}
+3
View File
@@ -1,5 +1,6 @@
#include "global.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
void EffectSpark_Init(void* thisx, void* initParamsx) {
EffectSpark* this = (EffectSpark*)thisx;
@@ -143,6 +144,7 @@ void EffectSpark_Draw(void* thisx, GraphicsContext* gfxCtx) {
u8 sp1C4;
f32 ratio;
FrameInterpolation_RecordOpenChild(this, 0);
OPEN_DISPS(gfxCtx);
if (this != NULL) {
@@ -263,4 +265,5 @@ void EffectSpark_Draw(void* thisx, GraphicsContext* gfxCtx) {
end:
CLOSE_DISPS(gfxCtx);
FrameInterpolation_RecordCloseChild();
}
+5 -1
View File
@@ -1,7 +1,8 @@
#include "global.h"
#include "loadfragment.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
EffectSsInfo sEffectSsInfo = { NULL, 0, 0 };
EffectSsInfo sEffectSsInfo = { 0 };
void EffectSS_Init(PlayState* play, s32 numEntries) {
u32 i;
@@ -202,6 +203,7 @@ void EffectSs_Spawn(PlayState* play, s32 type, s32 priority, void* initData) {
sEffectSsInfo.data_table[index].type = type;
sEffectSsInfo.data_table[index].priority = priority;
sEffectSsInfo.data_table[index].epoch++;
if (initInfo->init(play, index, &sEffectSsInfo.data_table[index], initData) == 0) {
EffectSS_ResetEntry(&sEffectSsInfo.data_table[index]);
@@ -247,7 +249,9 @@ void EffectSS_DrawParticle(PlayState* play, s32 index) {
EffectSs* entry = &sEffectSsInfo.data_table[index];
if (entry->draw != NULL) {
FrameInterpolation_RecordOpenChild(entry, entry->epoch);
entry->draw(play, index, entry);
FrameInterpolation_RecordCloseChild();
}
}
+3
View File
@@ -2,6 +2,7 @@
#include "sys_cfb.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include <string.h>
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
LightsBuffer sLightsBuffer;
@@ -428,6 +429,7 @@ void Lights_DrawGlow(PlayState* play) {
if (params->drawGlow) {
f32 scale = SQ((f32)params->radius) * 2e-6f;
FrameInterpolation_RecordOpenChild(light, 0);
gDPSetPrimColor(dl++, 0, 0, params->color[0], params->color[1], params->color[2], 50);
Matrix_Translate(params->x, params->y, params->z, MTXMODE_NEW);
@@ -436,6 +438,7 @@ void Lights_DrawGlow(PlayState* play) {
gSPMatrix(dl++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(dl++, gameplay_keep_DL_029CF0);
FrameInterpolation_RecordCloseChild();
}
}
+3
View File
@@ -34,6 +34,7 @@ u8 sMotionBlurStatus;
#include "overlays/gamestates/ovl_file_choose/z_file_select.h"
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
#include "debug.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
#include <string.h>
s32 gDbgCamEnabled = false;
@@ -1509,7 +1510,9 @@ void Play_Main(GameState* thisx) {
if (1) {
*CONTROLLER1(&this->state) = D_801F6C18;
}
FrameInterpolation_StartRecord();
Play_Draw(this);
FrameInterpolation_StopRecord();
*CONTROLLER1(&this->state) = input;
}
+2
View File
@@ -1,4 +1,5 @@
#include "global.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
MtxF sMtxFClear = { {
{ 1.0f, 0.0f, 0.0f, 0.0f },
@@ -507,6 +508,7 @@ void SkinMatrix_Vec3sToVec3f(Vec3s* src, Vec3f* dest) {
void SkinMatrix_MtxFToMtx(MtxF* src, Mtx* dest) {
// #Region 2S2H [Port] For compatibility with modern systems this has been changed to use guMtxF2L
FrameInterpolation_RecordSkinMatrixMtxFToMtx(src, dest);
guMtxF2L(src, dest);
}
+74 -1
View File
@@ -1,6 +1,7 @@
#include "global.h"
#include "z64shrink_window.h"
#include "z64view.h"
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
s32 View_ApplyPerspective(View* view);
s32 View_ApplyOrtho(View* view);
@@ -309,6 +310,10 @@ void View_Apply(View* view, s32 mask) {
}
}
static float sqr(float a) {
return a * a;
}
s32 View_ApplyPerspective(View* view) {
f32 aspect;
s32 width;
@@ -359,10 +364,78 @@ s32 View_ApplyPerspective(View* view) {
guLookAt(viewing, view->eye.x, view->eye.y, view->eye.z, view->at.x, view->at.y, view->at.z, view->up.x, view->up.y,
view->up.z);
view->viewing = *viewing;
// Some heuristics to identify instant camera movements and skip interpolation in that case
static View old_view;
float dirx = view->eye.x - view->at.x;
float diry = view->eye.y - view->at.y;
float dirz = view->eye.z - view->at.z;
float dir_dist = sqrtf(sqr(dirx) + sqr(diry) + sqr(dirz));
dirx /= dir_dist;
diry /= dir_dist;
dirz /= dir_dist;
float odirx = old_view.eye.x - old_view.at.x;
float odiry = old_view.eye.y - old_view.at.y;
float odirz = old_view.eye.z - old_view.at.z;
float odir_dist = sqrtf(sqr(odirx) + sqr(odiry) + sqr(odirz));
odirx /= odir_dist;
odiry /= odir_dist;
odirz /= odir_dist;
float eye_dist = sqrtf(sqr(view->eye.x - old_view.eye.x) + sqr(view->eye.y - old_view.eye.y) +
sqr(view->eye.z - old_view.eye.z));
float look_dist = sqrtf(sqr(view->at.x - old_view.at.x) + sqr(view->at.y - old_view.at.y) +
sqr(view->at.z - old_view.at.z));
float up_dist =
sqrtf(sqr(view->up.x - old_view.up.x) + sqr(view->up.y - old_view.up.y) + sqr(view->up.z - old_view.up.z));
float d_dist = sqrtf(sqr(dirx - odirx) + sqr(diry - odiry) + sqr(dirz - odirz));
bool dont_interpolate = false;
if (up_dist < 0.01 && d_dist < 0.01) {
if (eye_dist + look_dist > 300) {
dont_interpolate = true;
}
} else {
if (eye_dist >= 400) {
dont_interpolate = true;
}
if (look_dist >= 100) {
dont_interpolate = true;
}
if (up_dist >= 1.50f) {
dont_interpolate = true;
}
if (d_dist >= 1.414f && look_dist >= 15) {
dont_interpolate = true;
}
if (d_dist >= 1.414f && up_dist >= 0.31f && look_dist >= 1 && eye_dist >= 300) {
dont_interpolate = true;
}
if (d_dist >= 0.5f && up_dist >= 0.31f && look_dist >= 3 && eye_dist >= 170) {
dont_interpolate = true;
}
if (look_dist >= 52 && eye_dist >= 52) {
dont_interpolate = true;
}
if (look_dist >= 30 && eye_dist >= 90) {
dont_interpolate = true;
}
}
if (dont_interpolate) {
FrameInterpolation_DontInterpolateCamera();
}
FrameInterpolation_RecordOpenChild(NULL, FrameInterpolation_GetCameraEpoch());
view->viewing = *viewing;
old_view = *view;
gSPMatrix(POLY_OPA_DISP++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
gSPMatrix(POLY_XLU_DISP++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
FrameInterpolation_RecordCloseChild();
CLOSE_DISPS(gfxCtx);

Some files were not shown because too many files have changed in this diff Show More