mirror of
https://github.com/HarbourMasters/2ship2harkinian.git
synced 2025-02-11 09:25:41 +00:00
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:
parent
7573a9378c
commit
ce17d97ac4
@ -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) {
|
||||
{
|
||||
//std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
//audio.processing = true;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
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;
|
||||
|
733
mm/2s2h/Enhancements/interpolation/frame_interpolation.cpp
Normal file
733
mm/2s2h/Enhancements/interpolation/frame_interpolation.cpp
Normal file
@ -0,0 +1,733 @@
|
||||
#include <libultraship/bridge.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <math.h>
|
||||
|
||||
#include "frame_interpolation.h"
|
||||
#include "2s2h/BenPort.h"
|
||||
|
||||
/*
|
||||
Frame interpolation.
|
||||
|
||||
The idea of this code is to interpolate all matrices.
|
||||
|
||||
The code contains two approaches. The first is to interpolate
|
||||
all inputs in transformations, such as angles, scale and distances,
|
||||
and then perform the same transformations with the interpolated values.
|
||||
After evaluation for some reason some animations such rolling look strange.
|
||||
|
||||
The second approach is to simply interpolate the final matrices. This will
|
||||
more or less simply interpolate the world coordinates for movements.
|
||||
This will however make rotations ~180 degrees get the "paper effect".
|
||||
The mitigation is to identify this case for actors and interpolate the
|
||||
matrix but in model coordinates instead, by "removing" the rotation-
|
||||
translation before interpolating, create a rotation matrix with the
|
||||
interpolated angle which is then applied to the matrix.
|
||||
|
||||
Currently the code contains both methods but only the second one is currently
|
||||
used.
|
||||
|
||||
Both approaches build a tree of instructions, containing matrices
|
||||
at leaves. Every node is built from OPEN_DISPS/CLOSE_DISPS and manually
|
||||
inserted FrameInterpolation_OpenChild/FrameInterpolation_Close child calls.
|
||||
These nodes contain information that should suffice to identify the matrix,
|
||||
so we can find it in an adjacent frame.
|
||||
|
||||
We can interpolate an arbitrary amount of frames between two original frames,
|
||||
given a specific interpolation factor (0=old frame, 0.5=average of frames,
|
||||
1.0=new frame).
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
|
||||
void Matrix_Init(struct GameState* gameState);
|
||||
void Matrix_Push(void);
|
||||
void Matrix_Pop(void);
|
||||
void Matrix_Get(MtxF* dest);
|
||||
void Matrix_Put(MtxF* src);
|
||||
void Matrix_Mult(MtxF* mf, u8 mode);
|
||||
void Matrix_Translate(f32 x, f32 y, f32 z, u8 mode);
|
||||
void Matrix_Scale(f32 x, f32 y, f32 z, u8 mode);
|
||||
void Matrix_RotateXF(f32 x, u8 mode);
|
||||
void Matrix_RotateYF(f32 y, u8 mode);
|
||||
void Matrix_RotateZF(f32 z, u8 mode);
|
||||
void Matrix_RotateZYX(s16 x, s16 y, s16 z, u8 mode);
|
||||
void Matrix_TranslateRotateZYX(Vec3f* translation, Vec3s* rotation);
|
||||
void Matrix_SetTranslateRotateYXZ(f32 translateX, f32 translateY, f32 translateZ, Vec3s* rot);
|
||||
Mtx* Matrix_MtxFToMtx(MtxF* src, Mtx* dest);
|
||||
Mtx* Matrix_ToMtx(Mtx* dest, char* file, s32 line);
|
||||
Mtx* Matrix_NewMtx(struct GraphicsContext* gfxCtx, char* file, s32 line);
|
||||
Mtx* Matrix_MtxFToNewMtx(MtxF* src, struct GraphicsContext* gfxCtx);
|
||||
void Matrix_MultVec3f(Vec3f* src, Vec3f* dest);
|
||||
void Matrix_MtxFCopy(MtxF* dest, MtxF* src);
|
||||
void Matrix_MtxToMtxF(Mtx* src, MtxF* dest);
|
||||
void Matrix_MultVec3fExt(Vec3f* src, Vec3f* dest, MtxF* mf);
|
||||
void Matrix_Transpose(MtxF* mf);
|
||||
void Matrix_ReplaceRotation(MtxF* mf);
|
||||
void Matrix_MtxFToYXZRotS(MtxF* mf, Vec3s* rotDest, s32 flag);
|
||||
void Matrix_MtxFToZYXRotS(MtxF* mf, Vec3s* rotDest, s32 flag);
|
||||
void Matrix_RotateAxisF(f32 angle, Vec3f* axis, u8 mode);
|
||||
MtxF* Matrix_CheckFloats(MtxF* mf, char* file, s32 line);
|
||||
void Matrix_SetTranslateScaleMtx2(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY,
|
||||
f32 translateZ);
|
||||
|
||||
MtxF* Matrix_GetCurrent(void);
|
||||
|
||||
void SkinMatrix_MtxFMtxFMult(MtxF* mfA, MtxF* mfB, MtxF* dest);
|
||||
|
||||
}
|
||||
|
||||
static bool invert_matrix(const float m[16], float invOut[16]);
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
enum class Op {
|
||||
OpenChild,
|
||||
CloseChild,
|
||||
|
||||
MatrixPush,
|
||||
MatrixPop,
|
||||
MatrixPut,
|
||||
MatrixMult,
|
||||
MatrixTranslate,
|
||||
MatrixScale,
|
||||
MatrixRotate1Coord,
|
||||
MatrixRotateZYX,
|
||||
MatrixTranslateRotateZYX,
|
||||
MatrixSetTranslateRotateYXZ,
|
||||
MatrixMtxFToMtx,
|
||||
MatrixToMtx,
|
||||
MatrixReplaceRotation,
|
||||
MatrixRotateAxis,
|
||||
SkinMatrixMtxFToMtx
|
||||
};
|
||||
|
||||
typedef pair<const void*, int> label;
|
||||
|
||||
union Data {
|
||||
Data() {
|
||||
}
|
||||
|
||||
struct {
|
||||
MtxF src;
|
||||
} matrix_put;
|
||||
|
||||
struct {
|
||||
MtxF mf;
|
||||
u8 mode;
|
||||
} matrix_mult;
|
||||
|
||||
struct {
|
||||
f32 x, y, z;
|
||||
u8 mode;
|
||||
} matrix_translate, matrix_scale;
|
||||
|
||||
struct {
|
||||
u32 coord;
|
||||
f32 value;
|
||||
u8 mode;
|
||||
} matrix_rotate_1_coord;
|
||||
|
||||
struct {
|
||||
s16 x, y, z;
|
||||
u8 mode;
|
||||
} matrix_rotate_zyx;
|
||||
|
||||
struct {
|
||||
Vec3f translation;
|
||||
Vec3s rotation;
|
||||
} matrix_translate_rotate_zyx;
|
||||
|
||||
struct {
|
||||
f32 translateX, translateY, translateZ;
|
||||
Vec3s rot;
|
||||
//MtxF mtx;
|
||||
bool has_mtx;
|
||||
} matrix_set_translate_rotate_yxz;
|
||||
|
||||
struct {
|
||||
MtxF src;
|
||||
Mtx* dest;
|
||||
} matrix_mtxf_to_mtx;
|
||||
|
||||
struct {
|
||||
Mtx* dest;
|
||||
MtxF src;
|
||||
bool has_adjusted;
|
||||
} matrix_to_mtx;
|
||||
|
||||
struct {
|
||||
MtxF mf;
|
||||
} matrix_replace_rotation;
|
||||
|
||||
struct {
|
||||
f32 angle;
|
||||
Vec3f axis;
|
||||
u8 mode;
|
||||
} matrix_rotate_axis;
|
||||
|
||||
struct {
|
||||
label key;
|
||||
size_t idx;
|
||||
} open_child;
|
||||
};
|
||||
|
||||
struct Path {
|
||||
map<label, vector<Path>> children;
|
||||
map<Op, vector<Data>> ops;
|
||||
vector<pair<Op, size_t>> items;
|
||||
};
|
||||
|
||||
struct Recording {
|
||||
Path root_path;
|
||||
};
|
||||
|
||||
bool is_recording;
|
||||
vector<Path*> current_path;
|
||||
uint32_t camera_epoch;
|
||||
uint32_t previous_camera_epoch;
|
||||
Recording current_recording;
|
||||
Recording previous_recording;
|
||||
|
||||
bool next_is_actor_pos_rot_matrix;
|
||||
bool has_inv_actor_mtx;
|
||||
MtxF inv_actor_mtx;
|
||||
size_t inv_actor_mtx_path_index;
|
||||
|
||||
Data& append(Op op) {
|
||||
auto& m = current_path.back()->ops[op];
|
||||
current_path.back()->items.emplace_back(op, m.size());
|
||||
return m.emplace_back();
|
||||
}
|
||||
|
||||
struct InterpolateCtx {
|
||||
float step;
|
||||
float w;
|
||||
unordered_map<Mtx*, MtxF> mtx_replacements;
|
||||
MtxF tmp_mtxf, tmp_mtxf2;
|
||||
Vec3f tmp_vec3f;
|
||||
Vec3s tmp_vec3s;
|
||||
MtxF actor_mtx;
|
||||
|
||||
MtxF* new_replacement(Mtx* addr) {
|
||||
return &mtx_replacements[addr];
|
||||
}
|
||||
|
||||
void interpolate_mtxf(MtxF* res, MtxF* o, MtxF* n) {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
res->mf[i][j] = w * o->mf[i][j] + step * n->mf[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float lerp(f32 o, f32 n) {
|
||||
return w * o + step * n;
|
||||
}
|
||||
|
||||
void lerp_vec3f(Vec3f* res, Vec3f* o, Vec3f* n) {
|
||||
res->x = lerp(o->x, n->x);
|
||||
res->y = lerp(o->y, n->y);
|
||||
res->z = lerp(o->z, n->z);
|
||||
}
|
||||
|
||||
float interpolate_angle(f32 o, f32 n) {
|
||||
if (o == n)
|
||||
return n;
|
||||
o = fmodf(o, 2 * M_PI);
|
||||
if (o < 0.0f) {
|
||||
o += 2 * M_PI;
|
||||
}
|
||||
n = fmodf(n, 2 * M_PI);
|
||||
if (n < 0.0f) {
|
||||
n += 2 * M_PI;
|
||||
}
|
||||
if (fabsf(o - n) > M_PI) {
|
||||
if (o < n) {
|
||||
o += 2 * M_PI;
|
||||
} else {
|
||||
n += 2 * M_PI;
|
||||
}
|
||||
}
|
||||
if (fabsf(o - n) > M_PI / 2) {
|
||||
//return n;
|
||||
}
|
||||
return lerp(o, n);
|
||||
}
|
||||
|
||||
s16 interpolate_angle(s16 os, s16 ns) {
|
||||
if (os == ns)
|
||||
return ns;
|
||||
int o = (u16)os;
|
||||
int n = (u16)ns;
|
||||
u16 res;
|
||||
int diff = o - n;
|
||||
if (-0x8000 <= diff && diff <= 0x8000) {
|
||||
if (diff < -0x4000 || diff > 0x4000) {
|
||||
return ns;
|
||||
}
|
||||
res = (u16)(w * o + step * n);
|
||||
} else {
|
||||
if (o < n) {
|
||||
o += 0x10000;
|
||||
} else {
|
||||
n += 0x10000;
|
||||
}
|
||||
diff = o - n;
|
||||
if (diff < -0x4000 || diff > 0x4000) {
|
||||
return ns;
|
||||
}
|
||||
res = (u16)(w * o + step * n);
|
||||
}
|
||||
if (os / 327 == ns / 327 && (s16)res / 327 != os / 327) {
|
||||
int bp = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void interpolate_angles(Vec3s* res, Vec3s* o, Vec3s* n) {
|
||||
res->x = interpolate_angle(o->x, n->x);
|
||||
res->y = interpolate_angle(o->y, n->y);
|
||||
res->z = interpolate_angle(o->z, n->z);
|
||||
}
|
||||
|
||||
void interpolate_branch(Path* old_path, Path *new_path) {
|
||||
for (auto& item : new_path->items) {
|
||||
Data& new_op = new_path->ops[item.first][item.second];
|
||||
|
||||
if (item.first == Op::OpenChild) {
|
||||
if (auto it = old_path->children.find(new_op.open_child.key);
|
||||
it != old_path->children.end() && new_op.open_child.idx < it->second.size()) {
|
||||
interpolate_branch(&it->second[new_op.open_child.idx],
|
||||
&new_path->children.find(new_op.open_child.key)->second[new_op.open_child.idx]);
|
||||
} else {
|
||||
interpolate_branch(
|
||||
&new_path->children.find(new_op.open_child.key)->second[new_op.open_child.idx],
|
||||
&new_path->children.find(new_op.open_child.key)->second[new_op.open_child.idx]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto it = old_path->ops.find(item.first); it != old_path->ops.end()) {
|
||||
if (item.second < it->second.size()) {
|
||||
Data& old_op = it->second[item.second];
|
||||
switch (item.first) {
|
||||
case Op::OpenChild:
|
||||
break;
|
||||
case Op::CloseChild:
|
||||
break;
|
||||
|
||||
case Op::MatrixPush:
|
||||
Matrix_Push();
|
||||
break;
|
||||
|
||||
case Op::MatrixPop:
|
||||
Matrix_Pop();
|
||||
break;
|
||||
|
||||
case Op::MatrixPut:
|
||||
interpolate_mtxf(&tmp_mtxf, &old_op.matrix_put.src, &new_op.matrix_put.src);
|
||||
Matrix_Put(&tmp_mtxf);
|
||||
break;
|
||||
|
||||
case Op::MatrixMult:
|
||||
interpolate_mtxf(&tmp_mtxf, &old_op.matrix_mult.mf, &new_op.matrix_mult.mf);
|
||||
Matrix_Mult(&tmp_mtxf, new_op.matrix_mult.mode);
|
||||
break;
|
||||
|
||||
case Op::MatrixTranslate:
|
||||
Matrix_Translate(lerp(old_op.matrix_translate.x, new_op.matrix_translate.x),
|
||||
lerp(old_op.matrix_translate.y, new_op.matrix_translate.y),
|
||||
lerp(old_op.matrix_translate.z, new_op.matrix_translate.z),
|
||||
new_op.matrix_translate.mode);
|
||||
break;
|
||||
|
||||
case Op::MatrixScale:
|
||||
Matrix_Scale(lerp(old_op.matrix_scale.x, new_op.matrix_scale.x),
|
||||
lerp(old_op.matrix_scale.y, new_op.matrix_scale.y),
|
||||
lerp(old_op.matrix_scale.z, new_op.matrix_scale.z),
|
||||
new_op.matrix_scale.mode);
|
||||
break;
|
||||
|
||||
case Op::MatrixRotate1Coord: {
|
||||
float v = interpolate_angle(old_op.matrix_rotate_1_coord.value, new_op.matrix_rotate_1_coord.value);
|
||||
u8 mode = new_op.matrix_rotate_1_coord.mode;
|
||||
switch (new_op.matrix_rotate_1_coord.coord) {
|
||||
case 0:
|
||||
Matrix_RotateXF(v, mode);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Matrix_RotateYF(v, mode);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Matrix_RotateZF(v, mode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Op::MatrixRotateZYX:
|
||||
Matrix_RotateZYX(interpolate_angle(old_op.matrix_rotate_zyx.x, new_op.matrix_rotate_zyx.x),
|
||||
interpolate_angle(old_op.matrix_rotate_zyx.y, new_op.matrix_rotate_zyx.y),
|
||||
interpolate_angle(old_op.matrix_rotate_zyx.z, new_op.matrix_rotate_zyx.z),
|
||||
new_op.matrix_rotate_zyx.mode);
|
||||
break;
|
||||
|
||||
case Op::MatrixTranslateRotateZYX:
|
||||
lerp_vec3f(&tmp_vec3f, &old_op.matrix_translate_rotate_zyx.translation, &new_op.matrix_translate_rotate_zyx.translation);
|
||||
interpolate_angles(&tmp_vec3s, &old_op.matrix_translate_rotate_zyx.rotation, &new_op.matrix_translate_rotate_zyx.rotation);
|
||||
Matrix_TranslateRotateZYX(&tmp_vec3f, &tmp_vec3s);
|
||||
break;
|
||||
|
||||
case Op::MatrixSetTranslateRotateYXZ:
|
||||
interpolate_angles(&tmp_vec3s, &old_op.matrix_set_translate_rotate_yxz.rot,
|
||||
&new_op.matrix_set_translate_rotate_yxz.rot);
|
||||
Matrix_SetTranslateRotateYXZ(lerp(old_op.matrix_set_translate_rotate_yxz.translateX,
|
||||
new_op.matrix_set_translate_rotate_yxz.translateX),
|
||||
lerp(old_op.matrix_set_translate_rotate_yxz.translateY,
|
||||
new_op.matrix_set_translate_rotate_yxz.translateY),
|
||||
lerp(old_op.matrix_set_translate_rotate_yxz.translateZ,
|
||||
new_op.matrix_set_translate_rotate_yxz.translateZ),
|
||||
&tmp_vec3s);
|
||||
if (new_op.matrix_set_translate_rotate_yxz.has_mtx && old_op.matrix_set_translate_rotate_yxz.has_mtx) {
|
||||
actor_mtx = *Matrix_GetCurrent();
|
||||
}
|
||||
break;
|
||||
|
||||
case Op::MatrixMtxFToMtx:
|
||||
interpolate_mtxf(new_replacement(new_op.matrix_mtxf_to_mtx.dest),
|
||||
&old_op.matrix_mtxf_to_mtx.src, &new_op.matrix_mtxf_to_mtx.src);
|
||||
break;
|
||||
|
||||
case Op::MatrixToMtx: {
|
||||
//*new_replacement(new_op.matrix_to_mtx.dest) = *Matrix_GetCurrent();
|
||||
if (old_op.matrix_to_mtx.has_adjusted && new_op.matrix_to_mtx.has_adjusted) {
|
||||
interpolate_mtxf(&tmp_mtxf, &old_op.matrix_to_mtx.src, &new_op.matrix_to_mtx.src);
|
||||
SkinMatrix_MtxFMtxFMult(&actor_mtx, &tmp_mtxf, new_replacement(new_op.matrix_to_mtx.dest));
|
||||
} else {
|
||||
interpolate_mtxf(new_replacement(new_op.matrix_to_mtx.dest),
|
||||
&old_op.matrix_to_mtx.src, &new_op.matrix_to_mtx.src);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Op::MatrixReplaceRotation:
|
||||
interpolate_mtxf(&tmp_mtxf, &old_op.matrix_replace_rotation.mf, &new_op.matrix_replace_rotation.mf);
|
||||
Matrix_ReplaceRotation(&tmp_mtxf);
|
||||
break;
|
||||
|
||||
case Op::MatrixRotateAxis:
|
||||
lerp_vec3f(&tmp_vec3f, &old_op.matrix_rotate_axis.axis, &new_op.matrix_rotate_axis.axis);
|
||||
Matrix_RotateAxisF(interpolate_angle(old_op.matrix_rotate_axis.angle, new_op.matrix_rotate_axis.angle),
|
||||
&tmp_vec3f, new_op.matrix_rotate_axis.mode);
|
||||
break;
|
||||
|
||||
case Op::SkinMatrixMtxFToMtx:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
unordered_map<Mtx*, MtxF> FrameInterpolation_Interpolate(float step) {
|
||||
InterpolateCtx ctx;
|
||||
ctx.step = step;
|
||||
ctx.w = 1.0f - step;
|
||||
ctx.interpolate_branch(&previous_recording.root_path, ¤t_recording.root_path);
|
||||
return ctx.mtx_replacements;
|
||||
}
|
||||
|
||||
void FrameInterpolation_StartRecord(void) {
|
||||
previous_recording = move(current_recording);
|
||||
current_recording = {};
|
||||
current_path.clear();
|
||||
current_path.push_back(¤t_recording.root_path);
|
||||
if (OTRGlobals::Instance->GetInterpolationFPS() != 20) {
|
||||
is_recording = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameInterpolation_StopRecord(void) {
|
||||
previous_camera_epoch = camera_epoch;
|
||||
is_recording = false;
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordOpenChild(const void* a, int b) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
label key = { a, b };
|
||||
auto& m = current_path.back()->children[key];
|
||||
append(Op::OpenChild).open_child = { key, m.size() };
|
||||
current_path.push_back(&m.emplace_back());
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordCloseChild(void) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
//append(Op::CloseChild);
|
||||
if (has_inv_actor_mtx && current_path.size() == inv_actor_mtx_path_index) {
|
||||
has_inv_actor_mtx = false;
|
||||
}
|
||||
current_path.pop_back();
|
||||
}
|
||||
|
||||
void FrameInterpolation_DontInterpolateCamera(void) {
|
||||
camera_epoch = previous_camera_epoch + 1;
|
||||
}
|
||||
|
||||
int FrameInterpolation_GetCameraEpoch(void) {
|
||||
return (int)camera_epoch;
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordActorPosRotMatrix(void) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
next_is_actor_pos_rot_matrix = true;
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixPush(void) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixPush);
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixPop(void) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixPop);
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixPut(MtxF* src) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixPut).matrix_put = { *src };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixMult(MtxF* mf, u8 mode) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixMult).matrix_mult = { *mf, mode };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixTranslate(f32 x, f32 y, f32 z, u8 mode) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixTranslate).matrix_translate = { x, y, z, mode };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixScale(f32 x, f32 y, f32 z, u8 mode) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixScale).matrix_scale = { x, y, z, mode };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixRotate1Coord(u32 coord, f32 value, u8 mode) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixRotate1Coord).matrix_rotate_1_coord = { coord, value, mode };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixRotateZYX(s16 x, s16 y, s16 z, u8 mode) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixRotateZYX).matrix_rotate_zyx = { x, y, z, mode };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixTranslateRotateZYX(Vec3f* translation, Vec3s* rotation) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixTranslateRotateZYX).matrix_translate_rotate_zyx = { *translation, *rotation };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixSetTranslateRotateYXZ(f32 translateX, f32 translateY, f32 translateZ, Vec3s* rot) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
auto& d = append(Op::MatrixSetTranslateRotateYXZ).matrix_set_translate_rotate_yxz = { translateX, translateY, translateZ,
|
||||
*rot };
|
||||
if (next_is_actor_pos_rot_matrix) {
|
||||
d.has_mtx = true;
|
||||
//d.mtx = *Matrix_GetCurrent();
|
||||
invert_matrix((const float *)Matrix_GetCurrent()->mf, (float *)inv_actor_mtx.mf);
|
||||
next_is_actor_pos_rot_matrix = false;
|
||||
has_inv_actor_mtx = true;
|
||||
inv_actor_mtx_path_index = current_path.size();
|
||||
}
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixMtxFToMtx(MtxF* src, Mtx* dest) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixMtxFToMtx).matrix_mtxf_to_mtx = { *src, dest };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixToMtx(Mtx* dest, char* file, s32 line) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
auto& d = append(Op::MatrixToMtx).matrix_to_mtx = { dest };
|
||||
if (has_inv_actor_mtx) {
|
||||
d.has_adjusted = true;
|
||||
SkinMatrix_MtxFMtxFMult(&inv_actor_mtx, Matrix_GetCurrent(), &d.src);
|
||||
} else {
|
||||
d.src = *Matrix_GetCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixReplaceRotation(MtxF* mf) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixReplaceRotation).matrix_replace_rotation = { *mf };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordMatrixRotateAxis(f32 angle, Vec3f* axis, u8 mode) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
append(Op::MatrixRotateAxis).matrix_rotate_axis = { angle, *axis, mode };
|
||||
}
|
||||
|
||||
void FrameInterpolation_RecordSkinMatrixMtxFToMtx(MtxF* src, Mtx* dest) {
|
||||
if (!is_recording)
|
||||
return;
|
||||
FrameInterpolation_RecordMatrixMtxFToMtx(src, dest);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
|
||||
static bool invert_matrix(const float m[16], float invOut[16]) {
|
||||
float inv[16], det;
|
||||
int i;
|
||||
|
||||
inv[0] = m[5] * m[10] * m[15] -
|
||||
m[5] * m[11] * m[14] -
|
||||
m[9] * m[6] * m[15] +
|
||||
m[9] * m[7] * m[14] +
|
||||
m[13] * m[6] * m[11] -
|
||||
m[13] * m[7] * m[10];
|
||||
|
||||
inv[4] = -m[4] * m[10] * m[15] +
|
||||
m[4] * m[11] * m[14] +
|
||||
m[8] * m[6] * m[15] -
|
||||
m[8] * m[7] * m[14] -
|
||||
m[12] * m[6] * m[11] +
|
||||
m[12] * m[7] * m[10];
|
||||
|
||||
inv[8] = m[4] * m[9] * m[15] -
|
||||
m[4] * m[11] * m[13] -
|
||||
m[8] * m[5] * m[15] +
|
||||
m[8] * m[7] * m[13] +
|
||||
m[12] * m[5] * m[11] -
|
||||
m[12] * m[7] * m[9];
|
||||
|
||||
inv[12] = -m[4] * m[9] * m[14] +
|
||||
m[4] * m[10] * m[13] +
|
||||
m[8] * m[5] * m[14] -
|
||||
m[8] * m[6] * m[13] -
|
||||
m[12] * m[5] * m[10] +
|
||||
m[12] * m[6] * m[9];
|
||||
|
||||
inv[1] = -m[1] * m[10] * m[15] +
|
||||
m[1] * m[11] * m[14] +
|
||||
m[9] * m[2] * m[15] -
|
||||
m[9] * m[3] * m[14] -
|
||||
m[13] * m[2] * m[11] +
|
||||
m[13] * m[3] * m[10];
|
||||
|
||||
inv[5] = m[0] * m[10] * m[15] -
|
||||
m[0] * m[11] * m[14] -
|
||||
m[8] * m[2] * m[15] +
|
||||
m[8] * m[3] * m[14] +
|
||||
m[12] * m[2] * m[11] -
|
||||
m[12] * m[3] * m[10];
|
||||
|
||||
inv[9] = -m[0] * m[9] * m[15] +
|
||||
m[0] * m[11] * m[13] +
|
||||
m[8] * m[1] * m[15] -
|
||||
m[8] * m[3] * m[13] -
|
||||
m[12] * m[1] * m[11] +
|
||||
m[12] * m[3] * m[9];
|
||||
|
||||
inv[13] = m[0] * m[9] * m[14] -
|
||||
m[0] * m[10] * m[13] -
|
||||
m[8] * m[1] * m[14] +
|
||||
m[8] * m[2] * m[13] +
|
||||
m[12] * m[1] * m[10] -
|
||||
m[12] * m[2] * m[9];
|
||||
|
||||
inv[2] = m[1] * m[6] * m[15] -
|
||||
m[1] * m[7] * m[14] -
|
||||
m[5] * m[2] * m[15] +
|
||||
m[5] * m[3] * m[14] +
|
||||
m[13] * m[2] * m[7] -
|
||||
m[13] * m[3] * m[6];
|
||||
|
||||
inv[6] = -m[0] * m[6] * m[15] +
|
||||
m[0] * m[7] * m[14] +
|
||||
m[4] * m[2] * m[15] -
|
||||
m[4] * m[3] * m[14] -
|
||||
m[12] * m[2] * m[7] +
|
||||
m[12] * m[3] * m[6];
|
||||
|
||||
inv[10] = m[0] * m[5] * m[15] -
|
||||
m[0] * m[7] * m[13] -
|
||||
m[4] * m[1] * m[15] +
|
||||
m[4] * m[3] * m[13] +
|
||||
m[12] * m[1] * m[7] -
|
||||
m[12] * m[3] * m[5];
|
||||
|
||||
inv[14] = -m[0] * m[5] * m[14] +
|
||||
m[0] * m[6] * m[13] +
|
||||
m[4] * m[1] * m[14] -
|
||||
m[4] * m[2] * m[13] -
|
||||
m[12] * m[1] * m[6] +
|
||||
m[12] * m[2] * m[5];
|
||||
|
||||
inv[3] = -m[1] * m[6] * m[11] +
|
||||
m[1] * m[7] * m[10] +
|
||||
m[5] * m[2] * m[11] -
|
||||
m[5] * m[3] * m[10] -
|
||||
m[9] * m[2] * m[7] +
|
||||
m[9] * m[3] * m[6];
|
||||
|
||||
inv[7] = m[0] * m[6] * m[11] -
|
||||
m[0] * m[7] * m[10] -
|
||||
m[4] * m[2] * m[11] +
|
||||
m[4] * m[3] * m[10] +
|
||||
m[8] * m[2] * m[7] -
|
||||
m[8] * m[3] * m[6];
|
||||
|
||||
inv[11] = -m[0] * m[5] * m[11] +
|
||||
m[0] * m[7] * m[9] +
|
||||
m[4] * m[1] * m[11] -
|
||||
m[4] * m[3] * m[9] -
|
||||
m[8] * m[1] * m[7] +
|
||||
m[8] * m[3] * m[5];
|
||||
|
||||
inv[15] = m[0] * m[5] * m[10] -
|
||||
m[0] * m[6] * m[9] -
|
||||
m[4] * m[1] * m[10] +
|
||||
m[4] * m[2] * m[9] +
|
||||
m[8] * m[1] * m[6] -
|
||||
m[8] * m[2] * m[5];
|
||||
|
||||
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
|
||||
|
||||
if (det == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
det = 1.0 / det;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
invOut[i] = inv[i] * det;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
61
mm/2s2h/Enhancements/interpolation/frame_interpolation.h
Normal file
61
mm/2s2h/Enhancements/interpolation/frame_interpolation.h
Normal file
@ -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
|
@ -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/*")
|
||||
|
@ -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__); \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "global.h"
|
||||
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
|
||||
|
||||
Mtx* sSkyboxDrawMatrix;
|
||||
|
||||
@ -22,6 +23,7 @@ void Skybox_SetColors(SkyboxContext* skyboxCtx, u8 primR, u8 primG, u8 primB, u8
|
||||
|
||||
void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId, s16 blend, f32 x, f32 y, f32 z) {
|
||||
OPEN_DISPS(gfxCtx);
|
||||
FrameInterpolation_RecordOpenChild(NULL, FrameInterpolation_GetCameraEpoch());
|
||||
|
||||
Gfx_SetupDL40_Opa(gfxCtx);
|
||||
|
||||
@ -60,6 +62,7 @@ void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId
|
||||
|
||||
gDPPipeSync(POLY_OPA_DISP++);
|
||||
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
CLOSE_DISPS(gfxCtx);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "z_demo_kankyo.h"
|
||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||
#include "objects/object_bubble/object_bubble.h"
|
||||
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
|
||||
|
||||
#define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_20)
|
||||
|
||||
@ -512,6 +513,7 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) {
|
||||
gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL);
|
||||
|
||||
for (i = 0; i < play->envCtx.precipitation[PRECIP_SNOW_MAX]; i++) {
|
||||
FrameInterpolation_RecordOpenChild(this, i);
|
||||
worldPos.x = this->effects[i].posBase.x + this->effects[i].posOffset.x;
|
||||
worldPos.y = this->effects[i].posBase.y + this->effects[i].posOffset.y;
|
||||
worldPos.z = this->effects[i].posBase.z + this->effects[i].posOffset.z;
|
||||
@ -578,6 +580,7 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) {
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL);
|
||||
}
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
@ -602,6 +605,7 @@ void DemoKankyo_DrawMoonAndGiant(Actor* thisx, PlayState* play2) {
|
||||
Gfx_SetupDL25_Xlu(gfxCtx);
|
||||
|
||||
for (i = 0; i < play->envCtx.precipitation[PRECIP_SNOW_MAX]; i++) {
|
||||
FrameInterpolation_RecordOpenChild(this, i);
|
||||
worldPos.x = this->effects[i].posBase.x + this->effects[i].posOffset.x;
|
||||
worldPos.y = this->effects[i].posBase.y + this->effects[i].posOffset.y;
|
||||
worldPos.z = this->effects[i].posBase.z + this->effects[i].posOffset.z;
|
||||
@ -656,6 +660,7 @@ void DemoKankyo_DrawMoonAndGiant(Actor* thisx, PlayState* play2) {
|
||||
gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL);
|
||||
}
|
||||
}
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
|
||||
CLOSE_DISPS(gfxCtx);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "z_en_thiefbird.h"
|
||||
#include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h"
|
||||
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
|
||||
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
|
||||
|
||||
#define FLAGS \
|
||||
(ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_200 | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_80000000)
|
||||
@ -1155,6 +1156,7 @@ void func_80C13354(EnThiefbird* this, PlayState* play2) {
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(this->unk_3F0); i++, ptr++) {
|
||||
if (ptr->unk_22 != 0) {
|
||||
FrameInterpolation_RecordOpenChild(ptr, i);
|
||||
Matrix_Translate(ptr->unk_00.x, ptr->unk_00.y, ptr->unk_00.z, MTXMODE_NEW);
|
||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||
Matrix_RotateYS(ptr->unk_1E, MTXMODE_APPLY);
|
||||
@ -1165,6 +1167,7 @@ void func_80C13354(EnThiefbird* this, PlayState* play2) {
|
||||
gSPMatrix(&gfx[0], Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(&gfx[1], gTakkuriFeatherModelDL);
|
||||
gfx = &gfx[2];
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
}
|
||||
POLY_OPA_DISP = gfx;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "z_obj_grass.h"
|
||||
#include "overlays/actors/ovl_Obj_Grass_Carry/z_obj_grass_carry.h"
|
||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
|
||||
|
||||
#define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_20)
|
||||
|
||||
@ -466,6 +467,8 @@ void ObjGrass_DrawOpa(Actor* thisx, PlayState* play2) {
|
||||
for (j = 0; j < grassGroup->count; j++) {
|
||||
grassElem = &grassGroup->elements[j];
|
||||
|
||||
FrameInterpolation_RecordOpenChild(this, i + j);
|
||||
|
||||
if ((grassElem->flags & OBJ_GRASS_ELEM_DRAW) && (grassElem->alpha == 255)) {
|
||||
rot.y = grassElem->rotY;
|
||||
Matrix_SetTranslateRotateYXZ(grassElem->pos.x, grassElem->pos.y, grassElem->pos.z, &rot);
|
||||
@ -478,6 +481,8 @@ void ObjGrass_DrawOpa(Actor* thisx, PlayState* play2) {
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gObjGrass_D_809AAAE0);
|
||||
}
|
||||
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -506,6 +511,8 @@ void ObjGrass_DrawXlu(Actor* thisx, PlayState* play) {
|
||||
for (j = 0; j < grassGroup->count; j++) {
|
||||
grassElem = &grassGroup->elements[j];
|
||||
|
||||
FrameInterpolation_RecordOpenChild(this, i + j);
|
||||
|
||||
if ((grassElem->flags & OBJ_GRASS_ELEM_DRAW) && (grassElem->alpha > 0) && (grassElem->alpha < 255)) {
|
||||
rot.y = grassElem->rotY;
|
||||
Matrix_SetTranslateRotateYXZ(grassElem->pos.x, grassElem->pos.y, grassElem->pos.z, &rot);
|
||||
@ -516,6 +523,8 @@ void ObjGrass_DrawXlu(Actor* thisx, PlayState* play) {
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, grassElem->alpha);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gObjGrass_D_809AAAE0);
|
||||
}
|
||||
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "z_object_kankyo.h"
|
||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
|
||||
|
||||
#define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_2000000)
|
||||
|
||||
@ -539,9 +540,10 @@ void func_808DD3C8(Actor* thisx, PlayState* play2) {
|
||||
worldPos.x = this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C;
|
||||
worldPos.y = this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10;
|
||||
worldPos.z = this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14;
|
||||
|
||||
FrameInterpolation_RecordOpenChild(this, i);
|
||||
Play_GetScreenPos(play, &worldPos, &screenPos);
|
||||
|
||||
|
||||
if ((screenPos.x >= 0.0f) && (screenPos.x < SCREEN_WIDTH) && (screenPos.y >= 0.0f) &&
|
||||
(screenPos.y < SCREEN_HEIGHT)) {
|
||||
if (!spB4) {
|
||||
@ -572,6 +574,7 @@ void func_808DD3C8(Actor* thisx, PlayState* play2) {
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gEffDustDL);
|
||||
}
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
@ -613,7 +616,7 @@ void func_808DD970(Actor* thisx, PlayState* play2) {
|
||||
worldPos.x = this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C;
|
||||
worldPos.y = this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10;
|
||||
worldPos.z = this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14;
|
||||
|
||||
FrameInterpolation_RecordOpenChild(this, i);
|
||||
Play_GetScreenPos(play, &worldPos, &screenPos);
|
||||
|
||||
if ((screenPos.x >= 0.0f) && (screenPos.x < SCREEN_WIDTH) && (screenPos.y >= 0.0f) &&
|
||||
@ -639,6 +642,7 @@ void func_808DD970(Actor* thisx, PlayState* play2) {
|
||||
gSPSetGeometryMode(POLY_XLU_DISP++, G_FOG);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gEffDustDL);
|
||||
}
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
@ -673,6 +677,7 @@ void func_808DDE9C(Actor* thisx, PlayState* play2) {
|
||||
temp_f22 = this->unk_14C[0].unk_04 + ((Rand_ZeroOne() - 0.7f) * this->unk_144);
|
||||
temp_f2 = this->unk_14C[0].unk_08 + ((Rand_ZeroOne() - 0.7f) * this->unk_144);
|
||||
|
||||
FrameInterpolation_RecordOpenChild(this, i);
|
||||
if (!((temp_f20 < -252.0f) && (temp_f20 > -500.0f) && (temp_f2 > 3820.0f) && (temp_f2 < 4150.0f))) {
|
||||
Matrix_Translate(temp_f20, temp_f22, temp_f2, MTXMODE_NEW);
|
||||
|
||||
@ -690,11 +695,13 @@ void func_808DDE9C(Actor* thisx, PlayState* play2) {
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gFallingRainDropDL);
|
||||
}
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
|
||||
phi_s5 = false;
|
||||
if (player->actor.floorHeight < play->view.eye.y) {
|
||||
for (i = 0; i < end; i++) {
|
||||
FrameInterpolation_RecordOpenChild(this, i + end);
|
||||
if (!phi_s5) {
|
||||
Gfx_SetupDL25_Xlu(play->state.gfxCtx);
|
||||
|
||||
@ -716,6 +723,7 @@ void func_808DDE9C(Actor* thisx, PlayState* play2) {
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gEffShockwaveDL);
|
||||
}
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "gfxdebuggerbridge.h"
|
||||
#include "archives/item_name_static/item_name_static.h"
|
||||
#include "archives/map_name_static/map_name_static.h"
|
||||
#include "2s2h/Enhancements/interpolation/frame_interpolation.h"
|
||||
|
||||
// Page Textures (Background of Page):
|
||||
// Broken up into multiple textures.
|
||||
// Numbered by column/row.
|
||||
@ -584,6 +586,7 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
|
||||
s16 stepG;
|
||||
s16 stepB;
|
||||
|
||||
FrameInterpolation_RecordOpenChild(NULL, pauseCtx->state + pauseCtx->pageIndex * 100);
|
||||
OPEN_DISPS(gfxCtx);
|
||||
|
||||
if (!IS_PAUSE_STATE_GAMEOVER) {
|
||||
@ -868,6 +871,7 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
|
||||
}
|
||||
|
||||
CLOSE_DISPS(gfxCtx);
|
||||
FrameInterpolation_RecordCloseChild();
|
||||
}
|
||||
|
||||
TexturePtr D_8082B998[] = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user