mirror of
https://github.com/izzy2lost/Ghostship.git
synced 2026-06-19 01:17:03 -07:00
First any fps implementation
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user