mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-07 20:11:46 -04:00
Merge pull request #438 from TwilitRealm/frame-interp-simplify
Frame interp simplify
This commit is contained in:
@@ -209,6 +209,10 @@ public:
|
||||
/* 0x04 */ TGXTexObj* mpTexObj;
|
||||
/* 0x08 */ Mtx mVolumeMtx;
|
||||
/* 0x38 */ Mtx mMtx;
|
||||
#if TARGET_PC
|
||||
const void* mVolumeMtxKey;
|
||||
const void* mMtxKey;
|
||||
#endif
|
||||
}; // Size: 0x68
|
||||
|
||||
struct cBgD_Vtx_t;
|
||||
|
||||
@@ -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 enabled, bool is_sim_frame, float step);
|
||||
void interpolate();
|
||||
float get_interpolation_step();
|
||||
|
||||
void request_presentation_sync();
|
||||
@@ -28,35 +29,23 @@ bool is_enabled();
|
||||
void set_ui_tick_pending(bool value);
|
||||
bool get_ui_tick_pending();
|
||||
|
||||
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);
|
||||
void record_final_mtx_raw_tagged(const Mtx* dest, const Mtx src, uint64_t stable_tag);
|
||||
bool is_sim_frame();
|
||||
|
||||
bool lookup_replacement(const void* source, Mtx out);
|
||||
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);
|
||||
|
||||
void begin_presentation_camera();
|
||||
void end_presentation_camera();
|
||||
|
||||
struct PresentationCameraScope {
|
||||
PresentationCameraScope() { begin_presentation_camera(); }
|
||||
~PresentationCameraScope() { end_presentation_camera(); }
|
||||
PresentationCameraScope(const PresentationCameraScope&) = delete;
|
||||
PresentationCameraScope& operator=(const PresentationCameraScope&) = delete;
|
||||
PresentationCameraScope(PresentationCameraScope&&) = delete;
|
||||
PresentationCameraScope& operator=(PresentationCameraScope&&) = delete;
|
||||
};
|
||||
|
||||
uint64_t alloc_simple_shadow_pair_base();
|
||||
} // namespace frame_interp
|
||||
} // namespace dusk
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef struct leafdraw_class : base_process_class {
|
||||
#endif
|
||||
/* 0xB8 */ leafdraw_method_class* leaf_methods;
|
||||
/* 0xBC */ s8 unk_0xBC;
|
||||
/* 0xBD */ u8 unk_0xBD;
|
||||
/* 0xBD */ u8 draw_interp_frame;
|
||||
/* 0xBE */ draw_priority_class draw_priority;
|
||||
} leafdraw_class;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ typedef struct process_node_class {
|
||||
/* 0x0BC */ layer_class layer;
|
||||
/* 0x0E8 */ node_list_class layer_nodelist[16];
|
||||
/* 0x1A8 */ s8 unk_0x1A8;
|
||||
/* 0x1A9 */ s8 draw_interp_frame;
|
||||
} process_node_class;
|
||||
|
||||
typedef struct node_process_profile_definition {
|
||||
|
||||
@@ -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; }
|
||||
@@ -109,9 +109,7 @@ public:
|
||||
void setAnmMtx(int jointNo, Mtx m) {
|
||||
mMtxBuffer->setAnmMtx(jointNo, m);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(
|
||||
reinterpret_cast<const Mtx*>(mMtxBuffer->getAnmMtx(jointNo)),
|
||||
mMtxBuffer->getAnmMtx(jointNo));
|
||||
dusk::frame_interp::record_final_mtx(mMtxBuffer->getAnmMtx(jointNo));
|
||||
#endif
|
||||
}
|
||||
MtxP getAnmMtx(int jointNo) { return mMtxBuffer->getAnmMtx(jointNo); }
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
class JUTFader {
|
||||
public:
|
||||
enum EStatus {
|
||||
UNKSTATUS_M1 = -1,
|
||||
UNKSTATUS_0 = 0,
|
||||
None,
|
||||
Wait,
|
||||
FadeIn,
|
||||
FadeOut,
|
||||
};
|
||||
|
||||
JUTFader(int, int, int, int, JUtility::TColor);
|
||||
@@ -29,12 +31,12 @@ public:
|
||||
void setColor(JUtility::TColor color) { mColor.set(color); }
|
||||
|
||||
/* 0x04 */ s32 mStatus;
|
||||
/* 0x08 */ u16 field_0x8;
|
||||
/* 0x0A */ u16 field_0xa;
|
||||
/* 0x08 */ u16 mDuration;
|
||||
/* 0x0A */ u16 mTimer;
|
||||
/* 0x0C */ JUtility::TColor mColor;
|
||||
/* 0x10 */ JGeometry::TBox2<f32> mBox;
|
||||
/* 0x20 */ int mEStatus;
|
||||
/* 0x24 */ u32 field_0x24;
|
||||
/* 0x20 */ int mStatusTimer;
|
||||
/* 0x24 */ u32 mNextStatus;
|
||||
};
|
||||
|
||||
#endif /* JUTFADER_H */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -465,11 +467,11 @@ void J3DModel::calc() {
|
||||
|
||||
#ifdef TARGET_PC
|
||||
for (u16 i = 0; i < mModelData->getJointNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(getAnmMtx(i)), getAnmMtx(i));
|
||||
dusk::frame_interp::record_final_mtx(getAnmMtx(i));
|
||||
}
|
||||
|
||||
for (u16 i = 0; i < mModelData->getWEvlpMtxNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(getWeightAnmMtx(i)), getWeightAnmMtx(i));
|
||||
dusk::frame_interp::record_final_mtx(getWeightAnmMtx(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -509,7 +511,7 @@ void J3DModel::viewCalc() {
|
||||
J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
|
||||
(MtxP)&mInternalView);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView);
|
||||
dusk::frame_interp::record_final_mtx(mInternalView);
|
||||
#endif
|
||||
}
|
||||
} else if (isCpuSkinningOn()) {
|
||||
@@ -517,7 +519,7 @@ void J3DModel::viewCalc() {
|
||||
J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
|
||||
(MtxP)&mInternalView);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView);
|
||||
dusk::frame_interp::record_final_mtx(mInternalView);
|
||||
#endif
|
||||
}
|
||||
} else if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
|
||||
@@ -541,7 +543,7 @@ void J3DModel::viewCalc() {
|
||||
|
||||
#ifdef TARGET_PC
|
||||
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(&getDrawMtxPtr()[i], getDrawMtxPtr()[i]);
|
||||
dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@ void J3DMaterial::diff(u32 diffFlags) {
|
||||
}
|
||||
|
||||
void J3DMaterial::calc(f32 const (*param_0)[4]) {
|
||||
if (j3dSys.checkFlag(0x40000000)) {
|
||||
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
|
||||
mTexGenBlock->calcPostTexMtx(param_0);
|
||||
} else {
|
||||
mTexGenBlock->calc(param_0);
|
||||
@@ -276,7 +276,7 @@ void J3DMaterial::calc(f32 const (*param_0)[4]) {
|
||||
}
|
||||
|
||||
void J3DMaterial::calcDiffTexMtx(f32 const (*param_0)[4]) {
|
||||
if (j3dSys.checkFlag(0x40000000)) {
|
||||
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
|
||||
mTexGenBlock->calcPostTexMtxWithoutViewMtx(param_0);
|
||||
} else {
|
||||
mTexGenBlock->calcWithoutViewMtx(param_0);
|
||||
@@ -288,7 +288,7 @@ void J3DMaterial::setCurrentMtx() {
|
||||
}
|
||||
|
||||
void J3DMaterial::calcCurrentMtx() {
|
||||
if (!j3dSys.checkFlag(0x40000000)) {
|
||||
if (!j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
|
||||
mCurrentMtx.setCurrentTexMtx(
|
||||
getTexCoord(0)->getTexGenMtx(),
|
||||
getTexCoord(1)->getTexGenMtx(),
|
||||
|
||||
@@ -37,9 +37,9 @@ void loadTexCoordGens(u32 texGenNum, J3DTexCoord* texCoords) {
|
||||
var_r28 = 61;
|
||||
J3DGDWriteXFCmdHdr(GX_XF_REG_DUALTEX0, texGenNum);
|
||||
|
||||
if (j3dSys.checkFlag(0x40000000)) {
|
||||
if (j3dSys.checkFlag(J3DSysFlag_PostTexMtx)) {
|
||||
for (int i = 0; i < texGenNum; i++) {
|
||||
if (texCoords[i].getTexGenMtx() != 60) {
|
||||
if (texCoords[i].getTexGenMtx() != GX_IDENTITY) {
|
||||
var_r28 = i * 3;
|
||||
} else {
|
||||
var_r28 = 61;
|
||||
|
||||
@@ -219,7 +219,7 @@ void JFWDisplay::endGX() {
|
||||
if (dusk::frame_interp::get_ui_tick_pending()) {
|
||||
mFader->advance();
|
||||
}
|
||||
if (mFader->getStatus() != 1) {
|
||||
if (mFader->getStatus() != JUTFader::Wait) {
|
||||
mFader->draw();
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -10,51 +10,51 @@
|
||||
|
||||
JUTFader::JUTFader(int x, int y, int width, int height, JUtility::TColor pColor)
|
||||
: mColor(pColor), mBox(x, y, x + width, y + height) {
|
||||
mStatus = 0;
|
||||
field_0x8 = 0;
|
||||
field_0xa = 0;
|
||||
field_0x24 = 0;
|
||||
mEStatus = UNKSTATUS_M1;
|
||||
mStatus = None;
|
||||
mDuration = 0;
|
||||
mTimer = 0;
|
||||
mNextStatus = 0;
|
||||
mStatusTimer = -1;
|
||||
}
|
||||
|
||||
void JUTFader::advance() {
|
||||
if (0 <= mEStatus && mEStatus-- == 0) {
|
||||
mStatus = field_0x24;
|
||||
if (0 <= mStatusTimer && mStatusTimer-- == 0) {
|
||||
mStatus = mNextStatus;
|
||||
}
|
||||
|
||||
if (mStatus == 1) {
|
||||
if (mStatus == Wait) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mStatus) {
|
||||
case 0:
|
||||
case None:
|
||||
mColor.a = 0xFF;
|
||||
break;
|
||||
case 2:
|
||||
case FadeIn:
|
||||
#if AVOID_UB
|
||||
if (field_0x8 == 0) {
|
||||
mStatus = 1;
|
||||
if (mDuration == 0) {
|
||||
mStatus = Wait;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
mColor.a = 0xFF - ((++field_0xa * 0xFF) / field_0x8);
|
||||
mColor.a = 0xFF - ((++mTimer * 0xFF) / mDuration);
|
||||
|
||||
if (field_0xa >= field_0x8) {
|
||||
mStatus = 1;
|
||||
if (mTimer >= mDuration) {
|
||||
mStatus = Wait;
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
case FadeOut:
|
||||
#if AVOID_UB
|
||||
if (field_0x8 == 0) {
|
||||
mStatus = 0;
|
||||
if (mDuration == 0) {
|
||||
mStatus = None;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
mColor.a = ((++field_0xa * 0xFF) / field_0x8);
|
||||
mColor.a = ((++mTimer * 0xFF) / mDuration);
|
||||
|
||||
if (field_0xa >= field_0x8) {
|
||||
mStatus = 0;
|
||||
if (mTimer >= mDuration) {
|
||||
mStatus = None;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -77,53 +77,53 @@ void JUTFader::draw() {
|
||||
}
|
||||
}
|
||||
|
||||
bool JUTFader::startFadeIn(int param_0) {
|
||||
bool JUTFader::startFadeIn(int duration) {
|
||||
bool statusCheck = mStatus == 0;
|
||||
|
||||
if (statusCheck) {
|
||||
mStatus = 2;
|
||||
field_0xa = 0;
|
||||
field_0x8 = param_0;
|
||||
mStatus = FadeIn;
|
||||
mTimer = 0;
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
return statusCheck;
|
||||
}
|
||||
|
||||
bool JUTFader::startFadeOut(int param_0) {
|
||||
bool JUTFader::startFadeOut(int duration) {
|
||||
bool statusCheck = mStatus == 1;
|
||||
|
||||
if (statusCheck) {
|
||||
mStatus = 3;
|
||||
field_0xa = 0;
|
||||
field_0x8 = param_0;
|
||||
mStatus = FadeOut;
|
||||
mTimer = 0;
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
return statusCheck;
|
||||
}
|
||||
|
||||
void JUTFader::setStatus(JUTFader::EStatus i_status, int param_1) {
|
||||
void JUTFader::setStatus(JUTFader::EStatus i_status, int timer) {
|
||||
switch (i_status) {
|
||||
case 0:
|
||||
if (param_1 != 0) {
|
||||
field_0x24 = 0;
|
||||
mEStatus = param_1;
|
||||
case None:
|
||||
if (timer != 0) {
|
||||
mNextStatus = None;
|
||||
mStatusTimer = timer;
|
||||
break;
|
||||
}
|
||||
|
||||
mStatus = 0;
|
||||
field_0x24 = 0;
|
||||
mEStatus = 0;
|
||||
mStatus = None;
|
||||
mNextStatus = None;
|
||||
mStatusTimer = 0;
|
||||
break;
|
||||
case 1:
|
||||
if (param_1 != 0) {
|
||||
field_0x24 = 1;
|
||||
mEStatus = param_1;
|
||||
case Wait:
|
||||
if (timer != 0) {
|
||||
mNextStatus = Wait;
|
||||
mStatusTimer = timer;
|
||||
break;
|
||||
}
|
||||
|
||||
mStatus = 1;
|
||||
field_0x24 = 1;
|
||||
mEStatus = 0;
|
||||
mStatus = Wait;
|
||||
mNextStatus = Wait;
|
||||
mStatusTimer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,6 +623,11 @@ int daBg_c::create() {
|
||||
|
||||
dComIfGp_roomControl_onStatusFlag(roomNo, 0x10);
|
||||
OS_REPORT("<BG> room%d\n", roomNo);
|
||||
|
||||
#if TARGET_PC
|
||||
draw_interp_frame = true;
|
||||
#endif
|
||||
|
||||
return cPhs_COMPLEATE_e;
|
||||
}
|
||||
|
||||
|
||||
@@ -1056,7 +1056,7 @@ void daMidna_c::setBodyPartMatrix() {
|
||||
#ifdef TARGET_PC
|
||||
// FRAME INTERP NOTE: Record weight envelopes for Midna here, as they are otherwise missed causing distortion
|
||||
for (u16 i = 0; i < mpModel->getModelData()->getWEvlpMtxNum(); i++) {
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(mpModel->getWeightAnmMtx(i)), mpModel->getWeightAnmMtx(i));
|
||||
dusk::frame_interp::record_final_mtx(mpModel->getWeightAnmMtx(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include <gf/GFGeometry.h>
|
||||
#include <gf/GFLight.h>
|
||||
#include "m_Do/m_Do_lib.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
#ifndef __MWERKS__
|
||||
#include "dusk/math.h"
|
||||
@@ -441,7 +444,12 @@ void dMirror_packet_c::draw() {
|
||||
}
|
||||
|
||||
mDoLib_clipper::resetFar();
|
||||
reset();
|
||||
#if TARGET_PC
|
||||
if (!dusk::frame_interp::is_sim_frame())
|
||||
#endif
|
||||
{
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
daMirror_c::daMirror_c() {
|
||||
|
||||
@@ -981,9 +981,7 @@ int daObjStone_c::draw() {
|
||||
if (!model) {
|
||||
f32 shadow_size = l_shadow_size[mStoneType];
|
||||
TGXTexObj* pTex = dDlst_shadowControl_c::getSimpleTex();
|
||||
cXyz pos = current.pos;
|
||||
|
||||
dComIfGd_setSimpleShadow(&pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0,
|
||||
dComIfGd_setSimpleShadow(¤t.pos, mChkObj.GetGroundH(), shadow_size, mChkObj.m_gnd, 0,
|
||||
1.0f, pTex);
|
||||
}
|
||||
return 1;
|
||||
|
||||
@@ -700,13 +700,13 @@ void dFlower_packet_c::draw() {
|
||||
#ifdef TARGET_PC
|
||||
Mtx flower_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&sp44->m_modelMtx), flower_mtx)) {
|
||||
|
||||
GXLoadPosMtxImm(flower_mtx, 0);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadPosMtxImm(sp44->m_modelMtx, 0);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
||||
|
||||
#if TARGET_PC
|
||||
@@ -855,6 +855,7 @@ void dFlower_packet_c::draw() {
|
||||
#ifdef TARGET_PC
|
||||
Mtx flower_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&sp34->m_modelMtx), flower_mtx)) {
|
||||
cMtx_concat(j3dSys.getViewMtx(), flower_mtx, flower_mtx);
|
||||
GXLoadPosMtxImm(flower_mtx, 0);
|
||||
} else {
|
||||
#endif
|
||||
@@ -994,7 +995,7 @@ void dFlower_packet_c::update() {
|
||||
mDoMtx_stack_c::scaleM(temp_f31, temp_f31, temp_f31);
|
||||
cMtx_concat(j3dSys.getViewMtx(), temp_r28, data_p->m_modelMtx);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(&data_p->m_modelMtx), data_p->m_modelMtx);
|
||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), data_p->m_modelMtx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,13 +756,13 @@ void dGrass_packet_c::draw() {
|
||||
#ifdef TARGET_PC
|
||||
Mtx grass_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(reinterpret_cast<const void*>(&var_r29->m_modelMtx), grass_mtx)) {
|
||||
cMtx_concat(j3dSys.getViewMtx(), grass_mtx, grass_mtx);
|
||||
GXLoadPosMtxImm(grass_mtx, 0);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadPosMtxImm(var_r29->m_modelMtx, 0);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
||||
if (var_r29->field_0x05 <= 3 || var_r29->field_0x05 >= 10) {
|
||||
if (var_r29->field_0x02 < -1) {
|
||||
@@ -1018,7 +1018,7 @@ void dGrass_packet_c::update() {
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), data_p->m_modelMtx);
|
||||
}
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(&data_p->m_modelMtx), data_p->m_modelMtx);
|
||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), data_p->m_modelMtx);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -11018,6 +11018,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;
|
||||
}
|
||||
@@ -11086,9 +11095,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);
|
||||
|
||||
+23
-32
@@ -1096,16 +1096,7 @@ void dDlst_shadowReal_c::draw() {
|
||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetCurrentMtx(GX_PNMTX0);
|
||||
#ifdef TARGET_PC
|
||||
Mtx receiver_proj_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(&mReceiverProjMtx, receiver_proj_mtx)) {
|
||||
GXLoadTexMtxImm(receiver_proj_mtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
} else {
|
||||
#endif
|
||||
GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
mShadowRealPoly.draw();
|
||||
}
|
||||
|
||||
@@ -1263,14 +1254,9 @@ u8 dDlst_shadowReal_c::setShadowRealMtx(cXyz* param_0, cXyz* param_1, f32 param_
|
||||
C_MTXOrtho(mRenderProjMtx, param_2, -param_2, -param_2, param_2, 1.0f, 10000.0f);
|
||||
C_MTXLightOrtho(mReceiverProjMtx, param_2, -param_2, -param_2, param_2, 0.5f, -0.5f, 0.5f, 0.5f);
|
||||
cMtx_concat(mReceiverProjMtx, mViewMtx, mReceiverProjMtx);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mViewMtx, mViewMtx);
|
||||
dusk::frame_interp::record_final_mtx_raw(&mReceiverProjMtx, mReceiverProjMtx);
|
||||
#endif
|
||||
return r29;
|
||||
}
|
||||
|
||||
|
||||
u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 param_3, f32 param_4,
|
||||
dKy_tevstr_c* param_5, f32 i_cameraZ, f32 param_7) {
|
||||
dScnKy_env_light_c* env_light = dKy_getEnvlight();
|
||||
@@ -1292,6 +1278,7 @@ u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 par
|
||||
}
|
||||
|
||||
field_0x1 = setShadowRealMtx(&sp60, param_2, param_3, param_4, param_7, param_5);
|
||||
|
||||
if (!field_0x1) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1331,14 +1318,14 @@ void dDlst_shadowSimple_c::draw() {
|
||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
|
||||
#ifdef TARGET_PC
|
||||
Mtx volume_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(&mVolumeMtx, volume_mtx)) {
|
||||
if (dusk::frame_interp::lookup_replacement(mVolumeMtxKey, volume_mtx)) {
|
||||
cMtx_concat(j3dSys.getViewMtx(), volume_mtx, volume_mtx);
|
||||
GXLoadPosMtxImm(volume_mtx, GX_PNMTX0);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadPosMtxImm(mVolumeMtx, GX_PNMTX0);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXSetCurrentMtx(GX_PNMTX0);
|
||||
GXCallDisplayList(l_frontMat, 0x40);
|
||||
GXCallDisplayList(l_shadowVolumeDL, 0x40);
|
||||
@@ -1346,14 +1333,14 @@ void dDlst_shadowSimple_c::draw() {
|
||||
GXCallDisplayList(l_shadowVolumeDL, 0x40);
|
||||
#ifdef TARGET_PC
|
||||
Mtx shadow_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(&mMtx, shadow_mtx)) {
|
||||
if (dusk::frame_interp::lookup_replacement(mMtxKey, shadow_mtx)) {
|
||||
cMtx_concat(j3dSys.getViewMtx(), shadow_mtx, shadow_mtx);
|
||||
GXLoadPosMtxImm(shadow_mtx, GX_PNMTX1);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadPosMtxImm(mMtx, GX_PNMTX1);
|
||||
#ifdef TARGET_PC
|
||||
}
|
||||
#endif
|
||||
GXSetCurrentMtx(GX_PNMTX1);
|
||||
|
||||
if (mpTexObj != NULL) {
|
||||
@@ -1383,6 +1370,12 @@ void dDlst_shadowSimple_c::draw() {
|
||||
GXCallDisplayList(l_shadowVolumeDL, 0x40);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static const void* getInterpKey(const void* base, int idx) {
|
||||
return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(base) ^ idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* param_3,
|
||||
s16 param_4, f32 param_5, TGXTexObj* param_6) {
|
||||
if (param_5 < 0.0f) {
|
||||
@@ -1406,6 +1399,10 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa
|
||||
mDoMtx_stack_c::transS(param_0->x, param_1 + f30, param_0->z);
|
||||
mDoMtx_stack_c::YrotM(param_4);
|
||||
mDoMtx_stack_c::scaleM(param_2, f30 + f30 + 16.0f, param_2 * param_5);
|
||||
#if TARGET_PC
|
||||
mVolumeMtxKey = getInterpKey(param_0, 0x1);
|
||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), mVolumeMtxKey);
|
||||
#endif
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mVolumeMtx);
|
||||
f32 f31 = JMAFastSqrt(1.0f - param_3->x * param_3->x);
|
||||
f32 f29;
|
||||
@@ -1431,17 +1428,11 @@ void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* pa
|
||||
mDoMtx_stack_c::get()[2][3] = param_0->z;
|
||||
mDoMtx_stack_c::YrotM(param_4);
|
||||
mDoMtx_stack_c::scaleM(param_2, 1.0f, param_2 * param_5);
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx);
|
||||
#ifdef TARGET_PC
|
||||
const uint64_t shadow_tag_base = dusk::frame_interp::alloc_simple_shadow_pair_base();
|
||||
if (shadow_tag_base != 0) {
|
||||
dusk::frame_interp::record_final_mtx_raw_tagged(&mVolumeMtx, mVolumeMtx, shadow_tag_base);
|
||||
dusk::frame_interp::record_final_mtx_raw_tagged(&mMtx, mMtx, shadow_tag_base + 1u);
|
||||
} else {
|
||||
dusk::frame_interp::record_final_mtx_raw(&mVolumeMtx, mVolumeMtx);
|
||||
dusk::frame_interp::record_final_mtx_raw(&mMtx, mMtx);
|
||||
}
|
||||
mMtxKey = getInterpKey(param_0, 0x2);
|
||||
dusk::frame_interp::record_final_mtx(mDoMtx_stack_c::get(), mMtxKey);
|
||||
#endif
|
||||
cMtx_concat(j3dSys.getViewMtx(), mDoMtx_stack_c::get(), mMtx);
|
||||
mpTexObj = param_6;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
@@ -8251,6 +8252,10 @@ static int dKy_Create(void* i_this) {
|
||||
kankyo_class* kankyo = (kankyo_class*)i_this;
|
||||
BOOL next_time_set = false;
|
||||
|
||||
#if TARGET_PC
|
||||
kankyo->base.draw_interp_frame = true;
|
||||
#endif
|
||||
|
||||
stage_envr_info_class* stage_envr_p = dComIfGp_getStageEnvrInfo();
|
||||
if (stage_envr_p != NULL && dComIfGp_getStartStageRoomNo() != -1) {
|
||||
stage_envr_p += dComIfGp_getStartStageRoomNo();
|
||||
|
||||
@@ -699,7 +699,7 @@ void dMw_c::collect_open_proc() {
|
||||
dMeter2Info_set2DVibrationM();
|
||||
}
|
||||
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
@@ -914,7 +914,7 @@ void dMw_c::collect_letter_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::collect_letter_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
@@ -946,7 +946,7 @@ void dMw_c::collect_fishing_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::collect_fishing_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
@@ -977,7 +977,7 @@ void dMw_c::collect_skill_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::collect_skill_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
@@ -1008,13 +1008,13 @@ void dMw_c::collect_insect_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::collect_insect_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = COLLECT_MOVE;
|
||||
}
|
||||
}
|
||||
|
||||
void dMw_c::insect_open_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
field_0x152 = 0;
|
||||
dComIfGp_setHeapLockFlag(1);
|
||||
dMw_insect_create(1);
|
||||
@@ -1050,7 +1050,7 @@ void dMw_c::insect_move_proc() {
|
||||
}
|
||||
|
||||
void dMw_c::insect_close_proc() {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::UNKSTATUS_0) {
|
||||
if (mDoGph_gInf_c::getFader()->getStatus() == JUTFader::None) {
|
||||
mMenuProc = NO_MENU;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ static void dOvlpFd_startFadeIn(int param_0) {
|
||||
JUTFader* fader = JFWDisplay::getManager()->getFader();
|
||||
JUT_ASSERT(0, fader != NULL);
|
||||
|
||||
fader->setStatus(JUTFader::UNKSTATUS_0, 0);
|
||||
fader->setStatus(JUTFader::UNKSTATUS_0, -1);
|
||||
fader->setStatus(JUTFader::None, 0);
|
||||
fader->setStatus(JUTFader::None, -1);
|
||||
fader->startFadeIn(param_0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,63 +1,16 @@
|
||||
#include "dusk/frame_interpolation.h"
|
||||
|
||||
#include <memory>
|
||||
#include "mtx.h"
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
|
||||
namespace {
|
||||
enum class Op : uint8_t {
|
||||
OpenChild,
|
||||
FinalMtx,
|
||||
};
|
||||
|
||||
struct Label {
|
||||
const void* key = nullptr;
|
||||
int32_t id = 0;
|
||||
|
||||
bool operator==(const Label& other) const {
|
||||
return key == other.key && id == other.id;
|
||||
}
|
||||
};
|
||||
|
||||
struct Data {
|
||||
Label child_label{};
|
||||
size_t child_index = 0;
|
||||
Mtx matrix{};
|
||||
const Mtx* dest = nullptr;
|
||||
uint64_t stable_tag = 0;
|
||||
};
|
||||
|
||||
struct Path;
|
||||
|
||||
struct ChildBucket {
|
||||
Label label{};
|
||||
std::vector<std::unique_ptr<Path>> nodes;
|
||||
};
|
||||
|
||||
struct OpBucket {
|
||||
Op op = Op::OpenChild;
|
||||
std::vector<Data> values;
|
||||
};
|
||||
|
||||
struct Path {
|
||||
std::vector<ChildBucket> children;
|
||||
std::vector<OpBucket> ops;
|
||||
std::vector<std::pair<Op, size_t>> items;
|
||||
Label draw_scope{};
|
||||
uint32_t simple_shadow_pair_seq = 0;
|
||||
};
|
||||
|
||||
struct Recording {
|
||||
Path root;
|
||||
std::unordered_map<uintptr_t, Mtx> matrix_values;
|
||||
};
|
||||
|
||||
struct MatrixValue {
|
||||
Mtx value;
|
||||
};
|
||||
|
||||
using FinalMtxLookup = std::unordered_map<const Mtx*, const Data*>;
|
||||
using FinalMtxLookupTagged = std::unordered_map<uint64_t, const Data*>;
|
||||
|
||||
bool s_initialized = false;
|
||||
|
||||
bool g_enabled = false;
|
||||
@@ -66,13 +19,13 @@ 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;
|
||||
Recording g_previous_recording;
|
||||
std::vector<Path*> g_current_path;
|
||||
|
||||
std::unordered_map<const Mtx*, MatrixValue> g_replacements;
|
||||
std::unordered_map<uintptr_t, Mtx> g_replacements;
|
||||
|
||||
struct CameraSnapshot {
|
||||
cXyz eye{};
|
||||
@@ -100,16 +53,6 @@ struct InterpolationCallBackWork {
|
||||
|
||||
std::vector<InterpolationCallBackWork> s_interpolationCallBackWork;
|
||||
|
||||
void set_enabled(bool enabled) {
|
||||
if (g_enabled == enabled)
|
||||
return;
|
||||
|
||||
g_enabled = enabled;
|
||||
|
||||
if (!g_enabled)
|
||||
s_interpolationCallBackWork.clear();
|
||||
}
|
||||
|
||||
void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) {
|
||||
dst->eye = v.lookat.eye;
|
||||
dst->center = v.lookat.center;
|
||||
@@ -122,14 +65,6 @@ void copy_view_to_snap(CameraSnapshot* dst, const view_class& v) {
|
||||
dst->valid = true;
|
||||
}
|
||||
|
||||
inline void copy_matrix(const Mtx src, Mtx dst) {
|
||||
MTXCopy(src, dst);
|
||||
}
|
||||
|
||||
inline void concat_matrix(const Mtx lhs, const Mtx rhs, Mtx out) {
|
||||
MTXConcat(lhs, rhs, out);
|
||||
}
|
||||
|
||||
inline void lerp_matrix(Mtx out, const Mtx lhs, const Mtx rhs, float step) {
|
||||
const float old_weight = 1.0f - step;
|
||||
for (size_t row = 0; row < 3; ++row) {
|
||||
@@ -163,162 +98,22 @@ inline bool matrix_differs(const Mtx lhs, const Mtx rhs, float epsilon = 0.0001f
|
||||
return false;
|
||||
}
|
||||
|
||||
Data& append_op(Op op) {
|
||||
auto& items = g_current_path.back()->items;
|
||||
auto& buckets = g_current_path.back()->ops;
|
||||
auto it = std::find_if(buckets.begin(), buckets.end(),
|
||||
[op](const OpBucket& bucket) { return bucket.op == op; });
|
||||
if (it == buckets.end()) {
|
||||
buckets.push_back({op, {}});
|
||||
it = buckets.end() - 1;
|
||||
}
|
||||
items.emplace_back(op, it->values.size());
|
||||
return it->values.emplace_back();
|
||||
}
|
||||
|
||||
const Data* find_matching_data(const Path& path, Op op, size_t index) {
|
||||
auto it = std::find_if(path.ops.begin(), path.ops.end(),
|
||||
[op](const OpBucket& bucket) { return bucket.op == op; });
|
||||
if (it == path.ops.end() || index >= it->values.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &it->values[index];
|
||||
}
|
||||
|
||||
const OpBucket* find_op_bucket(const Path& path, Op op) {
|
||||
auto it = std::find_if(path.ops.begin(), path.ops.end(),
|
||||
[op](const OpBucket& bucket) { return bucket.op == op; });
|
||||
if (it == path.ops.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &*it;
|
||||
}
|
||||
|
||||
void build_final_mtx_lookups(const Path& path, FinalMtxLookup& dest_lookup, FinalMtxLookupTagged& tag_lookup) {
|
||||
dest_lookup.clear();
|
||||
tag_lookup.clear();
|
||||
|
||||
const OpBucket* bucket = find_op_bucket(path, Op::FinalMtx);
|
||||
if (bucket == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const Data& data : bucket->values) {
|
||||
if (data.dest != nullptr) {
|
||||
dest_lookup[data.dest] = &data;
|
||||
}
|
||||
if (data.stable_tag != 0) {
|
||||
tag_lookup[data.stable_tag] = &data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Data* find_matching_final_mtx(const FinalMtxLookup& lookup, const Data& new_data) {
|
||||
if (new_data.dest == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto it = lookup.find(new_data.dest);
|
||||
if (it == lookup.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ChildBucket& get_child_bucket(Path& path, const Label& label) {
|
||||
auto it = std::find_if(path.children.begin(), path.children.end(),
|
||||
[&label](const ChildBucket& bucket) { return bucket.label == label; });
|
||||
if (it == path.children.end()) {
|
||||
path.children.push_back({});
|
||||
it = path.children.end() - 1;
|
||||
it->label = label;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
const ChildBucket* find_child_bucket(const Path& path, const Label& label) {
|
||||
auto it = std::find_if(path.children.begin(), path.children.end(),
|
||||
[&label](const ChildBucket& bucket) { return bucket.label == label; });
|
||||
if (it == path.children.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &*it;
|
||||
}
|
||||
|
||||
void store_replacement(const Data& old_data, const Data& new_data, float step) {
|
||||
if (new_data.dest == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& replacement = g_replacements[new_data.dest];
|
||||
lerp_matrix(replacement.value, old_data.matrix, new_data.matrix, step);
|
||||
}
|
||||
|
||||
void interpolate_branch(const Path& old_path, const Path& new_path, float step) {
|
||||
FinalMtxLookup old_final_mtx_lookup;
|
||||
FinalMtxLookupTagged old_final_mtx_lookup_tagged;
|
||||
build_final_mtx_lookups(old_path, old_final_mtx_lookup, old_final_mtx_lookup_tagged);
|
||||
|
||||
for (const auto& item : new_path.items) {
|
||||
const Op op = item.first;
|
||||
const size_t index = item.second;
|
||||
const Data* new_data = find_matching_data(new_path, op, index);
|
||||
if (new_data == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (op == Op::OpenChild) {
|
||||
const ChildBucket* new_children = find_child_bucket(new_path, new_data->child_label);
|
||||
if (new_children == nullptr || new_data->child_index >= new_children->nodes.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Path& new_child = *new_children->nodes[new_data->child_index];
|
||||
const ChildBucket* old_children = find_child_bucket(old_path, new_data->child_label);
|
||||
if (old_children != nullptr && new_data->child_index < old_children->nodes.size())
|
||||
{
|
||||
interpolate_branch(*old_children->nodes[new_data->child_index], new_child, step);
|
||||
} else {
|
||||
interpolate_branch(new_child, new_child, step);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const Data* indexed_old_data = find_matching_data(old_path, op, index);
|
||||
const Data* old_data = nullptr;
|
||||
if (op == Op::FinalMtx) {
|
||||
if (new_data->stable_tag != 0) {
|
||||
const auto it = old_final_mtx_lookup_tagged.find(new_data->stable_tag);
|
||||
old_data = it != old_final_mtx_lookup_tagged.end() ? it->second : nullptr;
|
||||
} else {
|
||||
old_data = find_matching_final_mtx(old_final_mtx_lookup, *new_data);
|
||||
}
|
||||
} else {
|
||||
old_data = indexed_old_data;
|
||||
}
|
||||
if (op == Op::FinalMtx) {
|
||||
store_replacement(old_data != nullptr ? *old_data : *new_data, *new_data, step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Mtx* resolve_replacement(const Mtx* source, Mtx* scratch) {
|
||||
if (!g_interpolating || source == nullptr || dusk::frame_interp::presentation_sync_active()) {
|
||||
return source;
|
||||
}
|
||||
|
||||
auto it = g_replacements.find(source);
|
||||
auto it = g_replacements.find(reinterpret_cast<uintptr_t>(source));
|
||||
if (it == g_replacements.end()) {
|
||||
return source;
|
||||
}
|
||||
|
||||
copy_matrix(it->second.value, *scratch);
|
||||
MTXCopy(it->second, *scratch);
|
||||
return scratch;
|
||||
}
|
||||
|
||||
bool has_recording_data(const Recording& recording) {
|
||||
return !recording.root.items.empty() || !recording.root.children.empty();
|
||||
return !recording.matrix_values.empty();
|
||||
}
|
||||
|
||||
void clear_replacements() {
|
||||
@@ -329,14 +124,26 @@ void clear_replacements() {
|
||||
|
||||
namespace dusk::frame_interp {
|
||||
void ensure_initialized() {
|
||||
set_enabled(getSettings().game.enableFrameInterpolation);
|
||||
s_initialized = true;
|
||||
}
|
||||
|
||||
void begin_frame(bool enabled, bool is_sim_frame, float step) {
|
||||
g_enabled = enabled;
|
||||
g_is_sim_frame = is_sim_frame;
|
||||
g_step = std::clamp(step, 0.0f, 1.0f);
|
||||
if (is_sim_frame) {
|
||||
s_interpolationCallBackWork.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_enabled() {
|
||||
return g_enabled;
|
||||
}
|
||||
|
||||
bool is_sim_frame() {
|
||||
return g_is_sim_frame;
|
||||
}
|
||||
|
||||
void begin_record() {
|
||||
ensure_initialized();
|
||||
|
||||
@@ -345,7 +152,6 @@ void begin_record() {
|
||||
g_sync_presentation = false;
|
||||
g_previous_recording = {};
|
||||
g_current_recording = {};
|
||||
g_current_path.clear();
|
||||
clear_replacements();
|
||||
s_cam_prev.valid = false;
|
||||
s_cam_curr.valid = false;
|
||||
@@ -355,8 +161,6 @@ void begin_record() {
|
||||
g_sync_presentation = false;
|
||||
g_previous_recording = std::move(g_current_recording);
|
||||
g_current_recording = {};
|
||||
g_current_path.clear();
|
||||
g_current_path.push_back(&g_current_recording.root);
|
||||
g_recording = true;
|
||||
g_interpolating = false;
|
||||
clear_replacements();
|
||||
@@ -366,11 +170,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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,16 +177,20 @@ 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;
|
||||
}
|
||||
const Path& old_root = has_recording_data(g_previous_recording) ? g_previous_recording.root : g_current_recording.root;
|
||||
interpolate_branch(old_root, g_current_recording.root, g_step);
|
||||
for (auto const& old : g_previous_recording.matrix_values) {
|
||||
if (auto it = g_current_recording.matrix_values.find(old.first);
|
||||
it != g_current_recording.matrix_values.end())
|
||||
{
|
||||
lerp_matrix(g_replacements[old.first], old.second, it->second, g_step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void request_presentation_sync() {
|
||||
@@ -420,63 +223,30 @@ bool get_ui_tick_pending() {
|
||||
return g_enabled ? g_ui_tick_pending : true;
|
||||
}
|
||||
|
||||
void open_child(const void* key, int32_t id) {
|
||||
if (!s_initialized || !g_recording) {
|
||||
void record_final_mtx(Mtx m, const void* key) {
|
||||
if (!s_initialized || !g_recording || m == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Label label{key, id};
|
||||
auto& siblings = get_child_bucket(*g_current_path.back(), label).nodes;
|
||||
Data& data = append_op(Op::OpenChild);
|
||||
data.child_label = label;
|
||||
data.child_index = siblings.size();
|
||||
siblings.emplace_back(std::make_unique<Path>());
|
||||
Path* const child = siblings.back().get();
|
||||
child->draw_scope = label;
|
||||
g_current_path.push_back(child);
|
||||
auto& it = g_current_recording.matrix_values[reinterpret_cast<uintptr_t>(key)];
|
||||
MTXCopy(m, it);
|
||||
}
|
||||
|
||||
void close_child() {
|
||||
if (!s_initialized || !g_recording || g_current_path.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_current_path.pop_back();
|
||||
void record_final_mtx(Mtx m) {
|
||||
record_final_mtx(m, m);
|
||||
}
|
||||
|
||||
void record_final_mtx_raw(const Mtx* dest, const Mtx src) {
|
||||
if (!s_initialized || !g_recording || dest == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Data& data = append_op(Op::FinalMtx);
|
||||
data.dest = dest;
|
||||
data.stable_tag = 0;
|
||||
copy_matrix(src, data.matrix);
|
||||
}
|
||||
|
||||
void record_final_mtx_raw_tagged(const Mtx* dest, const Mtx src, uint64_t stable_tag) {
|
||||
if (!s_initialized || !g_recording || dest == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Data& data = append_op(Op::FinalMtx);
|
||||
data.dest = dest;
|
||||
data.stable_tag = stable_tag;
|
||||
copy_matrix(src, data.matrix);
|
||||
}
|
||||
|
||||
bool lookup_replacement(const void* source, Mtx out) {
|
||||
if (presentation_sync_active() || !g_interpolating || source == nullptr) {
|
||||
bool lookup_replacement(const void* key, Mtx out) {
|
||||
if (presentation_sync_active() || !g_interpolating || key == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto it = g_replacements.find(reinterpret_cast<const Mtx*>(source));
|
||||
auto it = g_replacements.find(reinterpret_cast<uintptr_t>(key));
|
||||
if (it == g_replacements.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_matrix(it->second.value, out);
|
||||
MTXCopy(it->second, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -493,7 +263,7 @@ bool lookup_concat_replacement(const void* lhs, const void* rhs, Mtx out) {
|
||||
return false;
|
||||
}
|
||||
|
||||
concat_matrix(*resolved_lhs, *resolved_rhs, out);
|
||||
MTXConcat(*resolved_lhs, *resolved_rhs, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -501,25 +271,62 @@ 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) {
|
||||
if (!g_enabled)
|
||||
return;
|
||||
|
||||
if (!s_cam_prev.valid || !s_cam_curr.valid)
|
||||
return;
|
||||
|
||||
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);
|
||||
@@ -544,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_);
|
||||
@@ -652,20 +432,4 @@ void end_presentation_camera() {
|
||||
std::memcpy(view, &s_presentation_view_backup, sizeof(view_class));
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t alloc_simple_shadow_pair_base() {
|
||||
if (!s_initialized || !g_recording || g_current_path.size() <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Path* const scope = g_current_path.back();
|
||||
const uint64_t h = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(scope->draw_scope.key));
|
||||
const uint32_t lo = scope->simple_shadow_pair_seq;
|
||||
scope->simple_shadow_pair_seq += 2;
|
||||
uint64_t tag0 = (h << 17) ^ (static_cast<uint64_t>(lo) << 1u);
|
||||
if (tag0 == 0) {
|
||||
tag0 = 2;
|
||||
}
|
||||
return tag0;
|
||||
}
|
||||
} // namespace dusk::frame_interp
|
||||
|
||||
@@ -9,53 +9,109 @@
|
||||
#include "f_pc/f_pc_layer_iter.h"
|
||||
#include "f_pc/f_pc_leaf.h"
|
||||
#include "f_pc/f_pc_node.h"
|
||||
#include "d/d_debug_viewer.h"
|
||||
#include "imgui.h"
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuTools.hpp"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
namespace dusk {
|
||||
bool showTreeRecursive;
|
||||
static bool BeginProcTable() {
|
||||
static ImGuiTableFlags table_flags =
|
||||
ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable |
|
||||
ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
||||
|
||||
if (ImGui::BeginTable("proc_table", 7)) {
|
||||
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 128);
|
||||
ImGui::TableSetupColumn("En", ImGuiTableColumnFlags_WidthFixed, 32);
|
||||
ImGui::TableSetupColumn("Vs", ImGuiTableColumnFlags_WidthFixed, 32);
|
||||
ImGui::TableSetupColumn("ProcName");
|
||||
ImGui::TableSetupColumn("Param", ImGuiTableColumnFlags_WidthFixed, 128);
|
||||
ImGui::TableSetupColumn("Pi", ImGuiTableColumnFlags_WidthFixed, 64);
|
||||
ImGui::TableSetupColumn("DwPi", ImGuiTableColumnFlags_WidthFixed, 64);
|
||||
ImGui::TableHeadersRow();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ShowProcess(void* p, void*) {
|
||||
auto proc = static_cast<base_process_class*>(p);
|
||||
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%d", proc->id);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::PushID(proc);
|
||||
bool pending = proc->create_req != nullptr;
|
||||
if (pending)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, {255, 200, 0, 255});
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImVec2 avail = ImGui::GetContentRegionAvail();
|
||||
char id_buf[32];
|
||||
sprintf(id_buf, "%d", proc->id);
|
||||
|
||||
ImVec2 vec = { avail.x, 0 };
|
||||
if (ImGui::BeginChild(buf, vec, ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) {
|
||||
ImGui::Text("[%d] %s", proc->id, GetProcName(proc->profname));
|
||||
ImGui::Text("init_state: %d, create_phase: %d", proc->state.init_state, proc->state.create_phase);
|
||||
int flags = ImGuiTreeNodeFlags_SpanAllColumns;
|
||||
bool isLayer = fpcBs_Is_JustOfType(g_fpcNd_type, proc->subtype);
|
||||
if (isLayer) {
|
||||
flags |= ImGuiTreeNodeFlags_DefaultOpen;
|
||||
} else {
|
||||
flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen;
|
||||
}
|
||||
|
||||
const char* ofTypeName = "unknown";
|
||||
if (proc->subtype == g_fpcNd_type) {
|
||||
ofTypeName = "Node";
|
||||
}
|
||||
else if (proc->subtype == g_fpcLf_type) {
|
||||
ofTypeName = "Leaf";
|
||||
}
|
||||
bool open = ImGui::TreeNodeEx(id_buf, flags);
|
||||
fopAc_ac_c* ac = fopAcM_IsActor(proc) ? (fopAc_ac_c*)proc : nullptr;
|
||||
if (ac != nullptr && ImGui::IsItemHovered()) {
|
||||
fopAcM_DrawCullingBox(ac, {0, 255, 255, 255});
|
||||
}
|
||||
|
||||
ImGui::Text("OfType: %d (%s), layer: %d", proc->subtype, ofTypeName, proc->layer_tag.layer->layer_id);
|
||||
ImGui::TableNextColumn();
|
||||
bool enable = !fpcM_IsPause(proc, 1);
|
||||
if (ImGui::Checkbox("##enable", &enable)) {
|
||||
if (enable)
|
||||
fpcM_PauseDisable(proc, 1);
|
||||
else
|
||||
fpcM_PauseEnable(proc, 1);
|
||||
}
|
||||
|
||||
if (proc->create_req != nullptr) {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Pending create request");
|
||||
}
|
||||
|
||||
if (showTreeRecursive) {
|
||||
if (fpcBs_Is_JustOfType(g_fpcNd_type, proc->subtype)) {
|
||||
auto procNode = static_cast<process_node_class*>(p);
|
||||
|
||||
ImGui::Text("Owns layer %d", procNode->layer.layer_id);
|
||||
|
||||
fpcLyIt_OnlyHere(&procNode->layer, ShowProcess, nullptr);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
if (fpcBs_Is_JustOfType(g_fpcLf_type, proc->subtype)) {
|
||||
leafdraw_class* lf = (leafdraw_class*)proc;
|
||||
bool vis = lf->unk_0xBC == 0;
|
||||
if (ImGui::Checkbox("##visible", &vis)) {
|
||||
if (vis)
|
||||
lf->unk_0xBC = 0;
|
||||
else
|
||||
lf->unk_0xBC = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", ac != nullptr ? fopAcM_getProcNameString(ac) : GetProcName(proc->profname));
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (proc->profname == fpcNm_ROOM_SCENE_e) {
|
||||
ImGui::Text("Room %d", proc->parameters);
|
||||
} else {
|
||||
ImGui::Text("%08x", proc->parameters);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", proc->priority.current_info.list_id);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (fpcBs_Is_JustOfType(g_fpcLf_type, proc->subtype)) {
|
||||
ImGui::Text("%d", fpcM_DrawPriority(proc));
|
||||
} else {
|
||||
ImGui::Text("--");
|
||||
}
|
||||
|
||||
if (isLayer && open) {
|
||||
auto procNode = static_cast<process_node_class*>(p);
|
||||
fpcLyIt_OnlyHere(&procNode->layer, ShowProcess, nullptr);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (pending)
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopID();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -76,15 +132,11 @@ namespace dusk {
|
||||
|
||||
if (ImGui::Begin("Processes", &m_showProcessManagement)) {
|
||||
if (ImGui::BeginTabBar("Tabs")) {
|
||||
showTreeRecursive = true;
|
||||
if (ImGui::BeginTabItem("Tree")) {
|
||||
fpcLyIt_OnlyHere(fpcLy_RootLayer(), ShowProcess, nullptr);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
showTreeRecursive = false;
|
||||
if (ImGui::BeginTabItem("All layers")) {
|
||||
fpcLyIt_All(ShowProcess, nullptr);
|
||||
if (BeginProcTable()) {
|
||||
fpcLyIt_OnlyHere(fpcLy_RootLayer(), ShowProcess, nullptr);
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,13 +26,7 @@ int fpcDw_Execute(base_process_class* i_proc) {
|
||||
}
|
||||
|
||||
fpcLy_SetCurrentLayer(i_proc->layer_tag.layer);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::open_child(i_proc, 0);
|
||||
#endif
|
||||
ret = draw_func(i_proc);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::close_child();
|
||||
#endif
|
||||
fpcLy_SetCurrentLayer(save_layer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
#include "f_pc/f_pc_leaf.h"
|
||||
#include "f_pc/f_pc_debug_sv.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
s16 fpcLf_GetPriority(const leafdraw_class* i_leaf) {
|
||||
return fpcDwPi_Get(&i_leaf->draw_priority);
|
||||
}
|
||||
@@ -16,6 +20,11 @@ int fpcLf_DrawMethod(leafdraw_method_class* i_methods, void* i_process) {
|
||||
|
||||
int fpcLf_Draw(leafdraw_class* i_leaf) {
|
||||
int ret = 0;
|
||||
#if TARGET_PC
|
||||
if (!i_leaf->draw_interp_frame && !dusk::frame_interp::is_sim_frame()) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (i_leaf->unk_0xBC == 0) {
|
||||
ret = fpcLf_DrawMethod(i_leaf->leaf_methods, i_leaf);
|
||||
}
|
||||
@@ -56,6 +65,9 @@ int fpcLf_Create(leafdraw_class* i_leaf) {
|
||||
LEAFDRAW_BASE(i_leaf).subtype = fpcBs_MakeOfType(&g_fpcLf_type);
|
||||
fpcDwPi_Init(&i_leaf->draw_priority, pprofile->priority);
|
||||
i_leaf->unk_0xBC = 0;
|
||||
#if TARGET_PC
|
||||
i_leaf->draw_interp_frame = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ret = fpcMtd_Create(&i_leaf->leaf_methods->base, i_leaf);
|
||||
|
||||
@@ -65,7 +65,7 @@ void fpcM_Management(fpcM_ManagementFunc i_preExecuteFn, fpcM_ManagementFunc i_p
|
||||
|
||||
#ifdef TARGET_PC
|
||||
// FRAME INTERP NOTE: Called in m_Do_main when interp is enabled
|
||||
if (!dusk::getSettings().game.enableFrameInterpolation || dusk::getTransientSettings().skipFrameRateLimit)
|
||||
if (!dusk::frame_interp::is_enabled())
|
||||
#endif
|
||||
{
|
||||
cAPIGph_Painter();
|
||||
|
||||
+18
-1
@@ -7,6 +7,13 @@
|
||||
#include "f_pc/f_pc_layer_iter.h"
|
||||
#include "f_pc/f_pc_debug_sv.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "f_op/f_op_draw_iter.h"
|
||||
#include "f_pc/f_pc_manager.h"
|
||||
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
int fpcNd_DrawMethod(nodedraw_method_class* i_method_class, void* i_data) {
|
||||
return fpcMtd_Method(i_method_class->draw_method, i_data);
|
||||
}
|
||||
@@ -18,7 +25,17 @@ int fpcNd_Draw(process_node_class* i_procNode) {
|
||||
if (i_procNode->unk_0x1A8 == 0) {
|
||||
layer_class* save_layer = fpcLy_CurrentLayer();
|
||||
fpcLy_SetCurrentLayer(&var_r28->layer);
|
||||
ret = fpcNd_DrawMethod(i_procNode->nodedraw_method, i_procNode);
|
||||
#if TARGET_PC
|
||||
if (!i_procNode->draw_interp_frame && !dusk::frame_interp::is_sim_frame()) {
|
||||
for (create_tag_class* i = fopDwIt_Begin(); i != NULL; i = fopDwIt_Next(i)) {
|
||||
void* process = i->mpTagData;
|
||||
fpcM_Draw(process);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = fpcNd_DrawMethod(i_procNode->nodedraw_method, i_procNode);
|
||||
}
|
||||
fpcLy_SetCurrentLayer(save_layer);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
|
||||
u8 mDoExt::CurrentHeapAdjustVerbose;
|
||||
u8 mDoExt::HeapAdjustVerbose;
|
||||
@@ -349,6 +350,11 @@ void mDoExt_modelUpdateDL(J3DModel* i_model) {
|
||||
}
|
||||
|
||||
void mDoExt_modelEntryDL(J3DModel* i_model) {
|
||||
#if TARGET_PC
|
||||
if (!dusk::frame_interp::is_sim_frame())
|
||||
return;
|
||||
#endif
|
||||
|
||||
modelMtxErrorCheck(i_model);
|
||||
|
||||
J3DModelData* model_data = i_model->getModelData();
|
||||
|
||||
+11
-5
@@ -71,6 +71,7 @@
|
||||
#include "dusk/settings.h"
|
||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||
#include "tracy/Tracy.hpp"
|
||||
#include "f_pc/f_pc_draw.h"
|
||||
|
||||
// --- GLOBALS ---
|
||||
s8 mDoMain::developmentMode = -1;
|
||||
@@ -250,21 +251,26 @@ void main01(void) {
|
||||
|
||||
mDoGph_gInf_c::updateRenderSize();
|
||||
|
||||
dusk::frame_interp::begin_frame(pacing.is_interpolating, pacing.do_sim_tick, pacing.interpolation_step);
|
||||
if (pacing.is_interpolating) {
|
||||
if (pacing.do_sim_tick) {
|
||||
dusk::frame_interp::reset_interpolation_callbacks();
|
||||
dusk::frame_interp::set_ui_tick_pending(true);
|
||||
mDoCPd_c::read();
|
||||
DuskDebugPad();
|
||||
dusk::gyro::read(pacing.sim_pace);
|
||||
fapGm_Execute();
|
||||
mDoAud_Execute();
|
||||
dusk::game_clock::reset_accumulator();
|
||||
}
|
||||
dusk::frame_interp::interpolate(pacing.interpolation_step);
|
||||
{
|
||||
dusk::frame_interp::PresentationCameraScope presentation_camera;
|
||||
cAPIGph_Painter();
|
||||
dusk::frame_interp::interpolate();
|
||||
dusk::frame_interp::begin_presentation_camera();
|
||||
if (!pacing.do_sim_tick) {
|
||||
// run draw functions for anything specially marked to handle interp on non-sim
|
||||
// ticks
|
||||
fpcM_DrawIterater((fpcM_DrawIteraterFunc)fpcM_Draw);
|
||||
}
|
||||
cAPIGph_Painter();
|
||||
dusk::frame_interp::end_presentation_camera();
|
||||
dusk::frame_interp::set_ui_tick_pending(false);
|
||||
} else {
|
||||
dusk::frame_interp::set_ui_tick_pending(true);
|
||||
|
||||
Reference in New Issue
Block a user