diff options
-rw-r--r-- | examples/julia_set.c | 18 | ||||
-rw-r--r-- | reduced_system_layer.c | 84 |
2 files changed, 69 insertions, 33 deletions
diff --git a/examples/julia_set.c b/examples/julia_set.c index e5a2734..6ae8e6f 100644 --- a/examples/julia_set.c +++ b/examples/julia_set.c @@ -43,15 +43,23 @@ void update_and_render_frame(void) { view_y += g_platform.cursor_dy * view_s; } - view_s += .1 * g_platform.wheel_dy * view_s; + if (g_platform.wheel_dy != 0.) { + f64 dx = (g_platform.cursor_x * 1. - g_platform.real_width * .5); + f64 dy = (g_platform.cursor_y * 1. - g_platform.real_height * .5); + view_x -= view_s * dx; + view_y -= view_s * dy; + view_s += view_s * g_platform.wheel_dy * .1; + view_x += view_s * dx; + view_y += view_s * dy; + } for (i32 j = 0; j < g_platform.frame_height; ++j) for (i32 i = 0; i < g_platform.frame_width; ++i) { - f64 kx = ((f64) g_platform.real_width) / g_platform.frame_width * view_s; - f64 ky = ((f64) g_platform.real_height) / g_platform.frame_height * view_s; + f64 kx = ((f64) g_platform.real_width) / g_platform.frame_width; + f64 ky = ((f64) g_platform.real_height) / g_platform.frame_height; - f64 x = .003 * ((i - g_platform.frame_width * .5) * kx - view_x); - f64 y = .003 * ((j - g_platform.frame_height * .5) * ky - view_y); + f64 x = .003 * ((i - (g_platform.frame_width - 1) * .5) * kx * view_s - view_x); + f64 y = .003 * ((j - (g_platform.frame_height - 1) * .5) * ky * view_s - view_y); i64 n = 0; diff --git a/reduced_system_layer.c b/reduced_system_layer.c index 4043f58..219d360 100644 --- a/reduced_system_layer.c +++ b/reduced_system_layer.c @@ -196,27 +196,35 @@ i32 main(i32 argc, c8 **argv); #endif #ifndef MIN_PIXEL_SIZE -#define MIN_PIXEL_SIZE 1 +#define MIN_PIXEL_SIZE (1.0) #endif #ifndef MAX_PIXEL_SIZE -#define MAX_PIXEL_SIZE 16 +#define MAX_PIXEL_SIZE (16.0) +#endif + +#ifndef PIXEL_SIZE_DELTA +#define PIXEL_SIZE_DELTA (0.1) #endif #ifndef DEFAULT_PIXEL_SIZE -#define DEFAULT_PIXEL_SIZE 3 +#define DEFAULT_PIXEL_SIZE (3.0) #endif #ifndef MIN_FRAME_DURATION -#define MIN_FRAME_DURATION 9 +#define MIN_FRAME_DURATION 8 #endif #ifndef MAX_FRAME_DURATION -#if defined(__wasm__) -#define MAX_FRAME_DURATION 83 -#else -#define MAX_FRAME_DURATION 41 +#define MAX_FRAME_DURATION 34 #endif + +#ifndef NUM_FRAMES_AVERAGED +#define NUM_FRAMES_AVERAGED 400 +#endif + +#ifndef AVERAGE_FRAME_BIAS +#define AVERAGE_FRAME_BIAS (0.00) #endif #ifndef NUM_SOUND_CHANNELS @@ -519,7 +527,7 @@ typedef struct { c8 *title; i32 frame_width; i32 frame_height; - i32 pixel_size; + f64 pixel_size; b8 exact_resolution; b8 graceful_exit; @@ -610,9 +618,11 @@ Platform g_platform = {0}; static i64 _sound_clock_time = 0; static i64 _sound_clock_carry = 0; static i64 _sound_position = 0; +static i64 _frame_index = 0; static f32 _sound_ring [MAX_NUM_SOUND_FRAMES] = {0}; static u8 _drop_files_buffer [DROP_FILES_BUFFER_SIZE] = {0}; +static i64 _frame_duration [NUM_FRAMES_AVERAGED] = {0}; void p_event_loop(void) { p_init(); @@ -719,7 +729,7 @@ i8 utf8_write(c32 c, c8 *buffer) { return 0; } -u32 rgb_u32_from_f32_(vec3_f32 c) { +static u32 rgb_u32_from_f32_(vec3_f32 c) { i32 ir = (i32) floor(c.x * 255. + .5); i32 ig = (i32) floor(c.y * 255. + .5); i32 ib = (i32) floor(c.z * 255. + .5); @@ -731,6 +741,22 @@ u32 rgb_u32_from_f32_(vec3_f32 c) { return (r << 16) | (g << 8) | b; } +static i64 average_frame_duration_(i64 duration) { + _frame_duration[_frame_index] = duration; + _frame_index = (_frame_index + 1) % NUM_FRAMES_AVERAGED; + + i64 durs[NUM_FRAMES_AVERAGED + 1]; + for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i) + durs[i] = _frame_duration[i]; + + // FIXME: Use better sorting algorithm. + for (i64 i = 0; i < (i64) NUM_FRAMES_AVERAGED; ++i) + for (i64 j = i + 1; j < NUM_FRAMES_AVERAGED; ++j) + if (durs[i] < durs[j]) { i64 t = durs[i]; durs[i] = durs[j]; durs[j] = t; } + + return durs[(i64) ((NUM_FRAMES_AVERAGED - 1) * AVERAGE_FRAME_BIAS)]; +} + static i64 sound_samples_elapsed_(void) { if (_sound_clock_time == 0) { _sound_clock_time = p_time(); @@ -1396,6 +1422,9 @@ static b8 sub_str_eq_(c8 *a, c8 *b, i64 len) { } void p_init(void) { + for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i) + _frame_duration[i] = (MIN_FRAME_DURATION + MAX_FRAME_DURATION) / 2; + _display = XOpenDisplay(NULL); if (_display == NULL) { @@ -2078,13 +2107,11 @@ i32 p_handle_events(void) { i32 width = _image.width; i32 height = _image.height; - if (g_platform.pixel_size <= 0) - g_platform.pixel_size = DEFAULT_PIXEL_SIZE; - - if (g_platform.pixel_size <= MIN_PIXEL_SIZE) - g_platform.pixel_size = MIN_PIXEL_SIZE; + if (g_platform.pixel_size <= 0.) g_platform.pixel_size = DEFAULT_PIXEL_SIZE; + if (g_platform.pixel_size < MIN_PIXEL_SIZE) g_platform.pixel_size = MIN_PIXEL_SIZE; + if (g_platform.pixel_size > MAX_PIXEL_SIZE) g_platform.pixel_size = MAX_PIXEL_SIZE; - if (g_platform.pixel_size > 1) { + if (g_platform.pixel_size > 1.) { width = (i32) floor(((f64) _image.width) / g_platform.pixel_size + .5); height = (i32) floor(((f64) _image.height) / g_platform.pixel_size + .5); } @@ -2143,12 +2170,12 @@ void p_render_frame(void) { XFlush(_display); if (!g_platform.exact_resolution) { - i64 frame_duration = p_time() - _frame_time; + i64 frame_duration = average_frame_duration_(p_time() - _frame_time); if (g_platform.pixel_size < MAX_PIXEL_SIZE && frame_duration > MAX_FRAME_DURATION) - ++g_platform.pixel_size; + g_platform.pixel_size += PIXEL_SIZE_DELTA * (frame_duration - MAX_FRAME_DURATION); else if (g_platform.pixel_size > MIN_PIXEL_SIZE && frame_duration < MIN_FRAME_DURATION) - --g_platform.pixel_size; + g_platform.pixel_size -= PIXEL_SIZE_DELTA * (MIN_FRAME_DURATION - frame_duration); } } @@ -2227,6 +2254,9 @@ void p_init(void) { g_platform.done = 1; + for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i) + _frame_duration[i] = (MIN_FRAME_DURATION + MAX_FRAME_DURATION) / 2; + _sound_read = (MAX_NUM_SOUND_FRAMES + ((-SOUND_AVAIL_MIN) % MAX_NUM_SOUND_FRAMES)) % MAX_NUM_SOUND_FRAMES; } @@ -2491,13 +2521,11 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram i32 width = _frame_width; i32 height = _frame_height; - if (g_platform.pixel_size <= 0) - g_platform.pixel_size = DEFAULT_PIXEL_SIZE; - - if (g_platform.pixel_size <= MIN_PIXEL_SIZE) - g_platform.pixel_size = MIN_PIXEL_SIZE; + if (g_platform.pixel_size <= 0.) g_platform.pixel_size = DEFAULT_PIXEL_SIZE; + if (g_platform.pixel_size < MIN_PIXEL_SIZE) g_platform.pixel_size = MIN_PIXEL_SIZE; + if (g_platform.pixel_size > MAX_PIXEL_SIZE) g_platform.pixel_size = MAX_PIXEL_SIZE; - if (g_platform.pixel_size > 1) { + if (g_platform.pixel_size > 1.) { width = (i32) floor(((f64) _frame_width) / g_platform.pixel_size + .5); height = (i32) floor(((f64) _frame_height) / g_platform.pixel_size + .5); } @@ -2534,12 +2562,12 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram _sound_read = (_sound_read + num_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES; if (!g_platform.exact_resolution && do_render) { - i64 frame_duration = p_time() - frame_time; + i64 frame_duration = average_frame_duration_(p_time() - frame_time); if (g_platform.pixel_size < MAX_PIXEL_SIZE && frame_duration > MAX_FRAME_DURATION) - ++g_platform.pixel_size; + g_platform.pixel_size += PIXEL_SIZE_DELTA * (frame_duration - MAX_FRAME_DURATION); else if (g_platform.pixel_size > MIN_PIXEL_SIZE && frame_duration < MIN_FRAME_DURATION) - --g_platform.pixel_size; + g_platform.pixel_size -= PIXEL_SIZE_DELTA * (MIN_FRAME_DURATION - frame_duration); } } |