mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-05-28 07:54:51 -04:00
frame interp camera cleanups
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
#ifndef DUSK_FRAME_INTERP_H
|
||||
#define DUSK_FRAME_INTERP_H
|
||||
#pragma once
|
||||
|
||||
#include <dolphin/mtx.h>
|
||||
#include <stdbool.h>
|
||||
@@ -7,6 +6,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
class camera_process_class;
|
||||
class view_class;
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace dusk {
|
||||
@@ -16,7 +16,8 @@ void ensure_initialized();
|
||||
|
||||
void begin_record();
|
||||
void end_record();
|
||||
void interpolate(float step);
|
||||
void begin_frame(bool is_sim_frame, float step);
|
||||
void interpolate();
|
||||
float get_interpolation_step();
|
||||
|
||||
void request_presentation_sync();
|
||||
@@ -29,14 +30,14 @@ void set_ui_tick_pending(bool value);
|
||||
bool get_ui_tick_pending();
|
||||
|
||||
void record_camera(::camera_process_class* cam, int camera_id);
|
||||
void interp_view(::view_class* view);
|
||||
void record_final_mtx(Mtx m, const void *key);
|
||||
void record_final_mtx(Mtx m);
|
||||
|
||||
bool lookup_replacement(const void* key, Mtx out);
|
||||
bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out);
|
||||
|
||||
typedef void (*InterpolationCallBack)(void* pUserWork);
|
||||
void reset_interpolation_callbacks();
|
||||
typedef void (*InterpolationCallBack)(bool isSimFrame, void* pUserWork);
|
||||
// call on a sim tick, will get called during presentation
|
||||
void add_interpolation_callback(InterpolationCallBack pCallBack, void* pUserWork);
|
||||
|
||||
@@ -55,5 +56,3 @@ struct PresentationCameraScope {
|
||||
} // namespace frame_interp
|
||||
} // namespace dusk
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
virtual ~J3DModel() {}
|
||||
|
||||
#if TARGET_PC
|
||||
static void interp_callback(void* pUserWork);
|
||||
static void interp_callback(bool isSimFrame, void* pUserWork);
|
||||
#endif
|
||||
|
||||
J3DModelData* getModelData() { return mModelData; }
|
||||
|
||||
@@ -98,10 +98,12 @@ s32 J3DModel::entryModelData(J3DModelData* pModelData, u32 mdlFlags, u32 mtxNum)
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void J3DModel::interp_callback(void* pUserWork) {
|
||||
void J3DModel::interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
J3DModel* i_this = static_cast<J3DModel*>(pUserWork);
|
||||
i_this->calcMaterial();
|
||||
i_this->diff();
|
||||
if (!isSimFrame) {
|
||||
i_this->calcMaterial();
|
||||
i_this->diff();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+9
-3
@@ -11009,6 +11009,15 @@ static int camera_execute(camera_process_class* i_this) {
|
||||
i_this->mCamera.CalcTrimSize();
|
||||
|
||||
store(i_this);
|
||||
|
||||
#ifdef TARGET_PC
|
||||
// record new camera for our sim frame
|
||||
dusk::frame_interp::record_camera(i_this, get_camera_id(i_this));
|
||||
// interpolate the view now so that this sim frame's view matrix matches what
|
||||
// we'll be rendering with later
|
||||
dusk::frame_interp::interp_view(&i_this->view);
|
||||
#endif
|
||||
|
||||
view_setup(i_this);
|
||||
return 1;
|
||||
}
|
||||
@@ -11077,9 +11086,6 @@ static int camera_draw(camera_process_class* i_this) {
|
||||
C_MTXPerspective(process->view.projMtx, process->view.fovy, process->view.aspect, process->view.near_, process->view.far_);
|
||||
mDoMtx_lookAt(process->view.viewMtx, &process->view.lookat.eye, &process->view.lookat.center,
|
||||
&process->view.lookat.up, process->view.bank);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_camera(process, camera_id);
|
||||
#endif
|
||||
|
||||
#if WIDESCREEN_SUPPORT
|
||||
mDoGph_gInf_c::setWideZoomProjection(process->view.projMtx);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#if TARGET_PC
|
||||
#include "dusk/imgui/ImGuiBloomWindow.hpp"
|
||||
#include "dusk/settings.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
static void GxXFog_set();
|
||||
@@ -8105,11 +8106,23 @@ void dKankyo_HIO_c::genMessage(JORMContext* mctx) {
|
||||
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
static void interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
if (!isSimFrame) {
|
||||
g_env_light.drawKankyo();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void dScnKy_env_light_c::drawKankyo() {
|
||||
setSunpos();
|
||||
SetBaseLight();
|
||||
setLight();
|
||||
dKy_setLight_nowroom(g_env_light.PrevCol);
|
||||
|
||||
#if TARGET_PC
|
||||
dusk::frame_interp::add_interpolation_callback(interp_callback, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dKy_undwater_filter_draw() {
|
||||
|
||||
@@ -19,6 +19,7 @@ bool g_interpolating = false;
|
||||
bool g_sync_presentation = false;
|
||||
|
||||
float g_step = 0.0f;
|
||||
bool g_is_sim_frame = false;
|
||||
bool g_ui_tick_pending = false;
|
||||
|
||||
Recording g_current_recording;
|
||||
@@ -141,6 +142,14 @@ bool is_enabled() {
|
||||
return g_enabled;
|
||||
}
|
||||
|
||||
void begin_frame(bool is_sim_frame, float step) {
|
||||
g_is_sim_frame = is_sim_frame;
|
||||
g_step = std::clamp(step, 0.0f, 1.0f);
|
||||
if (is_sim_frame) {
|
||||
s_interpolationCallBackWork.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void begin_record() {
|
||||
ensure_initialized();
|
||||
|
||||
@@ -167,11 +176,6 @@ void begin_record() {
|
||||
s_cam_prev.valid = false;
|
||||
s_cam_curr.valid = false;
|
||||
return;
|
||||
} else {
|
||||
copy_view_to_snap(&s_cam_prev, cam->view);
|
||||
#if WIDESCREEN_SUPPORT
|
||||
s_cam_prev.wideZoom = s_cam_curr.valid ? s_cam_curr.wideZoom : false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,10 +183,9 @@ void end_record() {
|
||||
g_recording = false;
|
||||
}
|
||||
|
||||
void interpolate(float step) {
|
||||
void interpolate() {
|
||||
ensure_initialized();
|
||||
clear_replacements();
|
||||
g_step = std::clamp(step, 0.0f, 1.0f);
|
||||
g_interpolating = g_enabled && !g_recording && !g_sync_presentation && has_recording_data(g_current_recording);
|
||||
if (!g_interpolating) {
|
||||
return;
|
||||
@@ -274,25 +277,56 @@ void record_camera(::camera_process_class* cam, int camera_id) {
|
||||
if (!g_enabled || camera_id != 0 || cam == nullptr) {
|
||||
return;
|
||||
}
|
||||
s_cam_prev = std::move(s_cam_curr);
|
||||
copy_view_to_snap(&s_cam_curr, cam->view);
|
||||
#if WIDESCREEN_SUPPORT
|
||||
s_cam_curr.wideZoom = mDoGph_gInf_c::isWideZoom();
|
||||
#endif
|
||||
}
|
||||
|
||||
void interp_view(::view_class* view) {
|
||||
const f32 step = get_interpolation_step();
|
||||
cXyz eye;
|
||||
cXyz center;
|
||||
cXyz up;
|
||||
lerp_xyz(&eye, s_cam_prev.eye, s_cam_curr.eye, step);
|
||||
lerp_xyz(¢er, s_cam_prev.center, s_cam_curr.center, step);
|
||||
lerp_xyz(&up, s_cam_prev.up, s_cam_curr.up, step);
|
||||
if (!up.normalizeRS()) {
|
||||
up = s_cam_curr.up;
|
||||
up.normalizeRS();
|
||||
}
|
||||
|
||||
view->lookat.eye = eye;
|
||||
view->lookat.center = center;
|
||||
view->lookat.up = up;
|
||||
view->bank = lerp_bank(s_cam_prev.bank, s_cam_curr.bank, step);
|
||||
view->fovy = s_cam_prev.fovy + (s_cam_curr.fovy - s_cam_prev.fovy) * step;
|
||||
view->aspect = s_cam_prev.aspect + (s_cam_curr.aspect - s_cam_prev.aspect) * step;
|
||||
view->near_ = s_cam_prev.near_ + (s_cam_curr.near_ - s_cam_prev.near_) * step;
|
||||
view->far_ = s_cam_prev.far_ + (s_cam_curr.far_ - s_cam_prev.far_) * step;
|
||||
|
||||
// FRAME INTERP TODO: It might be better if I rewired the game to not clear this flag until the
|
||||
// next sim frame, but I don't care enough to right now
|
||||
#if WIDESCREEN_SUPPORT
|
||||
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && step >= 0.5f ?
|
||||
s_cam_curr.wideZoom :
|
||||
s_cam_prev.wideZoom)
|
||||
{
|
||||
mDoGph_gInf_c::onWideZoom();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void run_interpolation_callbacks() {
|
||||
for (size_t i = 0; i < s_interpolationCallBackWork.size(); i++) {
|
||||
auto const& work = s_interpolationCallBackWork[i];
|
||||
work.pCallBack(work.pUserWork);
|
||||
work.pCallBack(g_is_sim_frame, work.pUserWork);
|
||||
}
|
||||
}
|
||||
|
||||
void reset_interpolation_callbacks() {
|
||||
s_interpolationCallBackWork.clear();
|
||||
}
|
||||
|
||||
void add_interpolation_callback(InterpolationCallBack pCallBack, void* pUserWork) {
|
||||
if (!is_enabled() || s_presentation_depth > 0)
|
||||
if (!is_enabled() || s_presentation_depth > 0 || !g_is_sim_frame)
|
||||
return;
|
||||
|
||||
s_interpolationCallBackWork.emplace_back(pCallBack, pUserWork);
|
||||
@@ -317,34 +351,7 @@ void begin_presentation_camera() {
|
||||
}
|
||||
|
||||
std::memcpy(&s_presentation_view_backup, view, sizeof(view_class));
|
||||
|
||||
const f32 step = get_interpolation_step();
|
||||
cXyz eye;
|
||||
cXyz center;
|
||||
cXyz up;
|
||||
lerp_xyz(&eye, s_cam_prev.eye, s_cam_curr.eye, step);
|
||||
lerp_xyz(¢er, s_cam_prev.center, s_cam_curr.center, step);
|
||||
lerp_xyz(&up, s_cam_prev.up, s_cam_curr.up, step);
|
||||
if (!up.normalizeRS()) {
|
||||
up = s_cam_curr.up;
|
||||
up.normalizeRS();
|
||||
}
|
||||
|
||||
view->lookat.eye = eye;
|
||||
view->lookat.center = center;
|
||||
view->lookat.up = up;
|
||||
view->bank = lerp_bank(s_cam_prev.bank, s_cam_curr.bank, step);
|
||||
view->fovy = s_cam_prev.fovy + (s_cam_curr.fovy - s_cam_prev.fovy) * step;
|
||||
view->aspect = s_cam_prev.aspect + (s_cam_curr.aspect - s_cam_prev.aspect) * step;
|
||||
view->near_ = s_cam_prev.near_ + (s_cam_curr.near_ - s_cam_prev.near_) * step;
|
||||
view->far_ = s_cam_prev.far_ + (s_cam_curr.far_ - s_cam_prev.far_) * step;
|
||||
|
||||
// FRAME INTERP TODO: It might be better if I rewired the game to not clear this flag until the next sim frame, but I don't care enough to right now
|
||||
#if WIDESCREEN_SUPPORT
|
||||
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && step >= 0.5f ? s_cam_curr.wideZoom : s_cam_prev.wideZoom) {
|
||||
mDoGph_gInf_c::onWideZoom();
|
||||
}
|
||||
#endif
|
||||
interp_view(view);
|
||||
|
||||
// FRAME INTERP TODO: Largely copied from d_camera's camera_draw function from this point, got any better ideas?
|
||||
C_MTXPerspective(view->projMtx, view->fovy, view->aspect, view->near_, view->far_);
|
||||
|
||||
@@ -234,8 +234,8 @@ void main01(void) {
|
||||
mDoGph_gInf_c::updateRenderSize();
|
||||
|
||||
if (pacing.is_interpolating) {
|
||||
dusk::frame_interp::begin_frame(pacing.do_sim_tick, pacing.interpolation_step);
|
||||
if (pacing.do_sim_tick) {
|
||||
dusk::frame_interp::reset_interpolation_callbacks();
|
||||
dusk::frame_interp::set_ui_tick_pending(true);
|
||||
mDoCPd_c::read();
|
||||
dusk::gyro::read(pacing.sim_pace);
|
||||
@@ -243,7 +243,7 @@ void main01(void) {
|
||||
mDoAud_Execute();
|
||||
dusk::game_clock::reset_accumulator();
|
||||
}
|
||||
dusk::frame_interp::interpolate(pacing.interpolation_step);
|
||||
dusk::frame_interp::interpolate();
|
||||
{
|
||||
dusk::frame_interp::PresentationCameraScope presentation_camera;
|
||||
cAPIGph_Painter();
|
||||
|
||||
Reference in New Issue
Block a user