First any fps implementation

This commit is contained in:
KiritoDv
2023-10-09 07:00:04 -06:00
parent 953d72a045
commit 4e7ae7aaf4
6 changed files with 95 additions and 32 deletions
+1
View File
@@ -1,6 +1,7 @@
#include <libultra/types.h>
#include "sm64.h"
#include "engine/math_util.h"
#include "game/ingame_menu.h"
#include "graph_node.h"
#include "behavior_script.h"
+1
View File
@@ -10,6 +10,7 @@
#include "engine/behavior_script.h"
#include "audio/external.h"
#include "textures.h"
#include "rendering_graph_node.h"
/**
* This file implements environment effects that are not snow:
+58 -18
View File
@@ -42,6 +42,8 @@ Mtx *gMatStackFixed[32];
Mat4 gMatStackInterpolated[32];
Mtx *gMatStackInterpolatedFixed[32];
extern float gInterpolationStep;
/**
* Animation nodes have state in global variables, so this struct captures
* the animation state so a 'context switch' can be made when rendering the
@@ -379,31 +381,69 @@ static void geo_process_switch(struct GraphNodeSwitchCase *node) {
}
}
float lerp(f32 o, f32 n) {
return (1 - gInterpolationStep) * o + gInterpolationStep * n;
}
s16 lerp_s(s16 o, s16 n) {
if (o == n)
return n;
int diff = o - n;
float w = 1 - gInterpolationStep;
if (-0x8000 <= diff && diff <= 0x8000) {
return (s16)(w * o + gInterpolationStep * n);
} else {
if (o < n) {
o += 0x10000;
} else {
n += 0x10000;
}
diff = o - n;
return (s16)(w * o + gInterpolationStep * n);
}
}
void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b) {
res[0] = (a[0] + b[0]) / 2.0f;
res[1] = (a[1] + b[1]) / 2.0f;
res[2] = (a[2] + b[2]) / 2.0f;
res[0] = lerp(a[0], b[0]);
res[1] = lerp(a[1], b[1]);
res[2] = lerp(a[2], b[2]);
}
void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b) {
res[0] = (a[0] + b[0]) / 2;
res[1] = (a[1] + b[1]) / 2;
res[2] = (a[2] + b[2]) / 2;
res[0] = lerp_s(a[0], b[0]);
res[1] = lerp_s(a[1], b[1]);
res[2] = lerp_s(a[2], b[2]);
}
static s16 interpolate_angle(s16 a, s16 b) {
s32 absDiff = b - a;
if (absDiff < 0) {
absDiff = -absDiff;
}
if (absDiff >= 0x4000 && absDiff <= 0xC000) {
return b;
}
if (absDiff <= 0x8000) {
return (a + b) / 2;
static 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;
float w = 1 - gInterpolationStep;
if (-0x8000 <= diff && diff <= 0x8000) {
if (diff < -0x4000 || diff > 0x4000) {
return ns;
}
res = (u16)(w * o + gInterpolationStep * n);
} else {
return (a + b) / 2 + 0x8000;
if (o < n) {
o += 0x10000;
} else {
n += 0x10000;
}
diff = o - n;
if (diff < -0x4000 || diff > 0x4000) {
return ns;
}
res = (u16)(w * o + gInterpolationStep * n);
}
if (os / 327 == ns / 327 && (s16)res / 327 != os / 327) {
int bp = 0;
}
return res;
}
static void interpolate_angles(Vec3s res, Vec3s a, Vec3s b) {
@@ -1067,7 +1107,7 @@ static void interpolate_matrix(Mat4 result, Mat4 a, Mat4 b) {
s32 i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
result[i][j] = (a[i][j] + b[i][j]) / 2.0f;
result[i][j] = (1 - gInterpolationStep) * a[i][j] + gInterpolationStep * b[i][j];
}
}
}
+2
View File
@@ -29,5 +29,7 @@ extern u16 gAreaUpdateCounter;
void geo_process_node_and_siblings(struct GraphNode *firstNode);
void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor);
void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b);
void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b);
#endif // RENDERING_GRAPH_NODE_H
+1
View File
@@ -12,6 +12,7 @@
#include "game/game_init.h"
#include "audio/external.h"
#include "gfx_dimensions.h"
#include "game/rendering_graph_node.h"
// frame counts for the zoom in, hold, and zoom out of title model
#define INTRO_STEPS_ZOOM_IN 20
+32 -14
View File
@@ -9,13 +9,15 @@ extern "C" {
#include "sm64.h"
}
float gInterpolationStep = 0.0f;
void alloc_pool() {
static u64 pool[1024 * 1024 * 4];
main_pool_init(pool, pool + sizeof(pool) / sizeof(pool[0]));
gEffectsMemoryPool = mem_pool_init(0x4000, MEMORY_POOL_LEFT);
}
void patch_interpolations(void) {
void patch_interpolations() {
mtx_patch_interpolated();
patch_screen_transition_interpolated();
patch_title_screen_scales();
@@ -26,24 +28,40 @@ void patch_interpolations(void) {
patch_interpolated_snow_particles();
}
#define ROUND_30(x) floor(x / 30) * 30
extern "C"
void exec_display_list(SPTask *spTask) {
uint32_t targetFPS = GameEngine::GetInterpolationFPS();
GameEngine::Instance->context->GetWindow()->SetTargetFps(targetFPS);
int target_fps = GameEngine::GetInterpolationFPS();
static int last_fps;
static int time;
int fps = target_fps;
int original_fps = 30;
if (target_fps == 30 || original_fps > target_fps) {
fps = original_fps;
}
if (last_fps != fps) {
time = 0;
}
int next_original_frame = fps;
while (time + original_fps <= next_original_frame) {
time += original_fps;
if (time != next_original_frame) {
gInterpolationStep = (float)time / next_original_frame;
}
GameEngine::RunCommands((Gfx *) spTask->task.t.data_ptr);
patch_interpolations();
}
time -= fps;
GameEngine::Instance->context->GetWindow()->SetTargetFps(fps);
int threshold = CVarGetInteger("gExtraLatencyThreshold", 80);
GameEngine::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && targetFPS >= threshold ? 2 : 1);
GameEngine::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1);
GameEngine::RunCommands((Gfx*) spTask->task.t.data_ptr);
if (targetFPS > 30) {
for (size_t i = 0; i < (ROUND_30(targetFPS) - 30) / 30; i++) {
patch_interpolations();
GameEngine::RunCommands((Gfx *) spTask->task.t.data_ptr);
}
}
last_fps = fps;
}
void push_frame() {