mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-05-27 07:37:24 -04:00
Frame interp: Fix stars
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
struct cXyz;
|
||||
class camera_process_class;
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace dusk {
|
||||
@@ -14,6 +15,7 @@ namespace frame_interp {
|
||||
|
||||
void ensure_initialized();
|
||||
|
||||
void begin_record_camera();
|
||||
void begin_record();
|
||||
void end_record();
|
||||
void interpolate(float step);
|
||||
@@ -25,12 +27,14 @@ void end_presentation_ui_pass();
|
||||
|
||||
void open_child(const void* key, int32_t id);
|
||||
void close_child();
|
||||
void record_camera(::camera_process_class* cam, int camera_id);
|
||||
void record_final_mtx_raw(const Mtx* dest, const Mtx src);
|
||||
|
||||
bool lookup_replacement(const void* source, Mtx out);
|
||||
bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out);
|
||||
|
||||
void camera_eye_from_view_mtx(MtxP view_mtx, cXyz* o_eye);
|
||||
bool build_star_view(Mtx o_view, Mtx o_cam_billboard_base, cXyz* o_anchor_eye, float* o_fovy);
|
||||
|
||||
} // namespace frame_interp
|
||||
} // namespace dusk
|
||||
|
||||
+2
-2
@@ -11042,8 +11042,8 @@ static int camera_draw(camera_process_class* i_this) {
|
||||
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_final_mtx_raw(reinterpret_cast<const Mtx*>(process->view.viewMtx),
|
||||
process->view.viewMtx);
|
||||
dusk::frame_interp::record_camera(process, camera_id);
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(process->view.viewMtx), process->view.viewMtx);
|
||||
#endif
|
||||
|
||||
#if WIDESCREEN_SUPPORT
|
||||
|
||||
+56
-4
@@ -12,6 +12,9 @@
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
#include "m_Do/m_Do_lib.h"
|
||||
#include <cstring>
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
static void vectle_calc(DOUBLE_POS* i_pos, cXyz* o_out) {
|
||||
double s = sqrt(i_pos->x * i_pos->x + i_pos->y * i_pos->y + i_pos->z * i_pos->z);
|
||||
@@ -4107,28 +4110,62 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) {
|
||||
color_reg0.b = 0xFF;
|
||||
color_reg0.a = 0xFF;
|
||||
|
||||
#if TARGET_PC
|
||||
Mtx star_gx_view;
|
||||
cXyz anchor_eye;
|
||||
f32 star_fovy = 45.0f;
|
||||
MtxP gx_load_view = drawMtx;
|
||||
bool star_use_present_view = false;
|
||||
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
star_use_present_view = dusk::frame_interp::build_star_view(star_gx_view, camMtx, &anchor_eye, &star_fovy);
|
||||
}
|
||||
|
||||
if (star_use_present_view) {
|
||||
gx_load_view = star_gx_view;
|
||||
} else {
|
||||
if (dComIfGd_getView() != NULL) {
|
||||
MTXInverse(dComIfGd_getView()->viewMtxNoTrans, camMtx);
|
||||
anchor_eye = camera->view.lookat.eye;
|
||||
star_fovy = dComIfGd_getView()->fovy;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (dComIfGd_getView() != NULL) {
|
||||
MTXInverse(dComIfGd_getView()->viewMtxNoTrans, camMtx);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(dComIfGp_getStartStageName(), "F_SP200") == 0 && dComIfG_play_c::getLayerNo(0) == 0) {
|
||||
moon_pos = envlight->moon_pos;
|
||||
} else {
|
||||
#if TARGET_PC
|
||||
moon_pos = anchor_eye + envlight->moon_pos;
|
||||
#else
|
||||
moon_pos = camera->view.lookat.eye + envlight->moon_pos;
|
||||
#endif
|
||||
if (sp38) {
|
||||
#if TARGET_PC
|
||||
moon_pos.x = 3900.0f + anchor_eye.x;
|
||||
moon_pos.y = 8052.0f + anchor_eye.y;
|
||||
moon_pos.z = -9072.0f + anchor_eye.z;
|
||||
#else
|
||||
moon_pos.x = 3900.0f + camera->view.lookat.eye.x;
|
||||
moon_pos.y = 8052.0f + camera->view.lookat.eye.y;
|
||||
moon_pos.z = -9072.0f + camera->view.lookat.eye.z;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
#if TARGET_PC
|
||||
mDoLib_project(&moon_pos, &moon_proj, {0, 0, FB_WIDTH, FB_HEIGHT});
|
||||
#else
|
||||
#else
|
||||
mDoLib_project(&moon_pos, &moon_proj);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Dusk optimization: we use vertex color rather than GX_TEVREG0 to set star color.
|
||||
// This allows us to merge all the stars into a single draw.
|
||||
@@ -4156,7 +4193,11 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) {
|
||||
MTXRotRad(rotMtx, 'Z', DEG_TO_RAD(rot));
|
||||
MTXConcat(camMtx, rotMtx, camMtx);
|
||||
|
||||
#if TARGET_PC
|
||||
GXLoadPosMtxImm(gx_load_view, GX_PNMTX0);
|
||||
#else
|
||||
GXLoadPosMtxImm(drawMtx, GX_PNMTX0);
|
||||
#endif
|
||||
GXSetCurrentMtx(GX_PNMTX0);
|
||||
|
||||
rot += 0.65f;
|
||||
@@ -4164,12 +4205,23 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) {
|
||||
rot = 0.0f;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
spBC = anchor_eye;
|
||||
#else
|
||||
spBC.x = camera->view.lookat.eye.x;
|
||||
spBC.y = camera->view.lookat.eye.y;
|
||||
spBC.z = camera->view.lookat.eye.z;
|
||||
#endif
|
||||
|
||||
f32 sp34 = -1.0f;
|
||||
int sp30 = 0;
|
||||
#if TARGET_PC
|
||||
f32 var_f30 = star_fovy / 45.0f;
|
||||
if (var_f30 >= 1.0f) {
|
||||
var_f30 = 1.0f;
|
||||
}
|
||||
var_f30 = 1.0f - var_f30;
|
||||
#else
|
||||
f32 var_f30 = 0.0f;
|
||||
|
||||
if (dComIfGd_getView() != NULL) {
|
||||
@@ -4179,7 +4231,7 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) {
|
||||
}
|
||||
var_f30 = 1.0f - var_f30;
|
||||
}
|
||||
|
||||
#endif
|
||||
f32 temp_f27 = 0.28f * (1.0f - var_f30);
|
||||
|
||||
sp98.x = 0.0f;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -8,7 +9,6 @@
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
enum class Op : uint8_t {
|
||||
OpenChild,
|
||||
FinalMtx,
|
||||
@@ -90,6 +90,13 @@ inline void lerp_matrix(Mtx out, const Mtx lhs, const Mtx rhs, float step) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void lerp_xyz(cXyz* out, const cXyz& lhs, const cXyz& rhs, float step) {
|
||||
const float old_weight = 1.0f - step;
|
||||
out->x = lhs.x * old_weight + rhs.x * step;
|
||||
out->y = lhs.y * old_weight + rhs.y * step;
|
||||
out->z = lhs.z * old_weight + rhs.z * step;
|
||||
}
|
||||
|
||||
inline bool matrix_differs(const Mtx lhs, const Mtx rhs, float epsilon = 0.0001f) {
|
||||
for (size_t row = 0; row < 3; ++row) {
|
||||
for (size_t col = 0; col < 4; ++col) {
|
||||
@@ -251,9 +258,7 @@ void clear_replacements() {
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace dusk {
|
||||
namespace frame_interp {
|
||||
|
||||
namespace dusk::frame_interp {
|
||||
void ensure_initialized() {
|
||||
g_enabled = getSettings().game.enableFrameInterpolation;
|
||||
s_initialized = true;
|
||||
@@ -405,5 +410,76 @@ void camera_eye_from_view_mtx(MtxP view_mtx, cXyz* o_eye) {
|
||||
o_eye->z = -(view_mtx[0][2] * view_mtx[0][3] + view_mtx[1][2] * view_mtx[1][3] + view_mtx[2][2] * view_mtx[2][3]);
|
||||
}
|
||||
|
||||
} // namespace frame_interp
|
||||
} // namespace dusk
|
||||
namespace {
|
||||
struct CamSnap {
|
||||
cXyz eye{};
|
||||
cXyz center{};
|
||||
cXyz up{};
|
||||
s16 bank{};
|
||||
f32 fovy{};
|
||||
bool valid{};
|
||||
};
|
||||
|
||||
CamSnap s_star_prev{};
|
||||
CamSnap s_star_curr{};
|
||||
|
||||
static void copy_view_to_snap(CamSnap* dst, const view_class& v) {
|
||||
dst->eye = v.lookat.eye;
|
||||
dst->center = v.lookat.center;
|
||||
dst->up = v.lookat.up;
|
||||
dst->bank = v.bank;
|
||||
dst->fovy = v.fovy;
|
||||
dst->valid = true;
|
||||
}
|
||||
|
||||
static void billboard_base_from_view(MtxP view_mtx, MtxP o_cam_billboard_base) {
|
||||
Mtx rot;
|
||||
MTXCopy(view_mtx, rot);
|
||||
rot[0][3] = rot[1][3] = rot[2][3] = 0.0f;
|
||||
MTXInverse(rot, o_cam_billboard_base);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void begin_record_camera() {
|
||||
::camera_process_class* cam = dComIfGp_getCamera(0);
|
||||
if (cam == nullptr) {
|
||||
return;
|
||||
}
|
||||
copy_view_to_snap(&s_star_prev, cam->view);
|
||||
}
|
||||
|
||||
void record_camera(::camera_process_class* cam, int camera_id) {
|
||||
if (!getSettings().game.enableFrameInterpolation || camera_id != 0 || cam == nullptr) {
|
||||
return;
|
||||
}
|
||||
copy_view_to_snap(&s_star_curr, cam->view);
|
||||
}
|
||||
|
||||
bool build_star_view(Mtx o_view, Mtx o_cam_billboard_base, cXyz* o_anchor_eye, float* o_fovy) {
|
||||
if (!getSettings().game.enableFrameInterpolation || !s_star_prev.valid || !s_star_curr.valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const f32 step = get_interpolation_step();
|
||||
cXyz eye;
|
||||
cXyz center;
|
||||
cXyz up;
|
||||
lerp_xyz(&eye, s_star_prev.eye, s_star_curr.eye, step);
|
||||
lerp_xyz(¢er, s_star_prev.center, s_star_curr.center, step);
|
||||
lerp_xyz(&up, s_star_prev.up, s_star_curr.up, step);
|
||||
if (!up.normalizeRS()) {
|
||||
up = s_star_curr.up;
|
||||
up.normalizeRS();
|
||||
}
|
||||
|
||||
const f32 bank_rad = S2RAD(s_star_prev.bank) * (1.0f - step) + S2RAD(s_star_curr.bank) * step;
|
||||
const s16 bank = cAngle::Radian_to_SAngle(bank_rad);
|
||||
|
||||
mDoMtx_lookAt(o_view, &eye, ¢er, &up, bank);
|
||||
billboard_base_from_view(o_view, o_cam_billboard_base);
|
||||
|
||||
*o_anchor_eye = eye;
|
||||
*o_fovy = s_star_prev.fovy + (s_star_curr.fovy - s_star_prev.fovy) * step;
|
||||
return true;
|
||||
}
|
||||
} // namespace dusk::frame_interp
|
||||
|
||||
@@ -725,6 +725,7 @@ void fapGm_After() {
|
||||
|
||||
#ifdef TARGET_PC
|
||||
static void fapGm_Before() {
|
||||
dusk::frame_interp::begin_record_camera();
|
||||
dusk::frame_interp::begin_record();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user