viewport scaling by camera size

This commit is contained in:
jacob 2024-03-19 21:17:49 -05:00
parent b53dfe93f8
commit c6ca5c0c9a
6 changed files with 64 additions and 46 deletions

View File

@ -5,8 +5,9 @@
* system. */ * system. */
#define RESOURCES_EMBEDDED !(DEVELOPER) #define RESOURCES_EMBEDDED !(DEVELOPER)
//#define ASPECT_RATIO (16.0 / 9.0) #define DEFAULT_CAMERA_WIDTH (6)
#define ASPECT_RATIO (4.0 / 3.0) #define DEFAULT_CAMERA_ASPECT_RATIO (16.0 / 9.0)
#define PIXELS_PER_UNIT 256 #define PIXELS_PER_UNIT 256
#define GAME_FPS 50 #define GAME_FPS 50

View File

@ -95,7 +95,7 @@ struct entity {
/* ENTITY_PROP_CAMERA */ /* ENTITY_PROP_CAMERA */
struct entity_handle camera_follow; struct entity_handle camera_follow;
struct xform camera_target_xform; /* Calculated from camera_follow */ struct xform camera_target_xform; /* Calculated from camera_follow */
f32 camera_zoom; struct v2 camera_size;
f32 camera_lerp; /* Rate at which camera xform approaches target xform */ f32 camera_lerp; /* Rate at which camera xform approaches target xform */
u32 camera_lerp_gen; u32 camera_lerp_gen;
u32 camera_applied_lerp_gen_plus_one; /* Calculated */ u32 camera_applied_lerp_gen_plus_one; /* Calculated */

View File

@ -205,7 +205,10 @@ INTERNAL void game_update(void)
entity_enable_prop(e, ENTITY_PROP_CAMERA); entity_enable_prop(e, ENTITY_PROP_CAMERA);
entity_enable_prop(e, ENTITY_PROP_CAMERA_ACTIVE); entity_enable_prop(e, ENTITY_PROP_CAMERA_ACTIVE);
e->camera_follow = player_ent->handle; e->camera_follow = player_ent->handle;
e->camera_zoom = 1;
f32 width = (f32)DEFAULT_CAMERA_WIDTH;
f32 height = width / (f32)DEFAULT_CAMERA_ASPECT_RATIO;
e->camera_size = V2(width, height);
} }
/* Sound ent */ /* Sound ent */
@ -473,8 +476,12 @@ INTERNAL void game_update(void)
ent->camera_target_xform.og = target_pos; ent->camera_target_xform.og = target_pos;
#else #else
/* "Look" style camera */ /* "Look" style camera */
f32 aspect_ratio = 1.0;
if (!v2_eq(ent->camera_size, V2(0, 0))) {
aspect_ratio = ent->camera_size.x / ent->camera_size.y;
}
f32 ratio_y = 0.33f; f32 ratio_y = 0.33f;
f32 ratio_x = ratio_y / (f32)ASPECT_RATIO; f32 ratio_x = ratio_y / aspect_ratio;
struct v2 camera_focus_dir = v2_mul_v2(follow->player_aim, V2(ratio_x, ratio_y)); struct v2 camera_focus_dir = v2_mul_v2(follow->player_aim, V2(ratio_x, ratio_y));
struct v2 camera_focus_pos = v2_add(follow->world_xform.og, camera_focus_dir); struct v2 camera_focus_pos = v2_add(follow->world_xform.og, camera_focus_dir);
ent->camera_target_xform.og = camera_focus_pos; ent->camera_target_xform.og = camera_focus_pos;

View File

@ -655,7 +655,6 @@ void renderer_canvas_release(struct renderer_canvas *canvas)
arena_release(&buffer->index_arena); arena_release(&buffer->index_arena);
/* FIXME: Clear GPU buffers */ /* FIXME: Clear GPU buffers */
} }
} }

View File

@ -98,7 +98,7 @@ struct sys_window_settings settings_default_window_settings(struct sys_window *w
struct v2 monitor_size = sys_window_get_monitor_size(window); struct v2 monitor_size = sys_window_get_monitor_size(window);
i32 width = 1280; i32 width = 1280;
i32 height = math_round(width / (f32)ASPECT_RATIO); i32 height = math_round(width / (f32)DEFAULT_CAMERA_ASPECT_RATIO);
i32 x = math_round(monitor_size.x / 2.f - width / 2); i32 x = math_round(monitor_size.x / 2.f - width / 2);
i32 y = math_round(monitor_size.y / 2.f - height / 2); i32 y = math_round(monitor_size.y / 2.f - height / 2);

View File

@ -38,7 +38,6 @@ GLOBAL struct {
struct renderer_canvas *world_canvas; struct renderer_canvas *world_canvas;
struct renderer_canvas *viewport_bg_canvas; struct renderer_canvas *viewport_bg_canvas;
struct renderer_canvas *viewport_canvas; struct renderer_canvas *viewport_canvas;
struct xform world_view_last_frame;
struct xform world_view; struct xform world_view;
struct blend_tick *head_free_blend_tick; struct blend_tick *head_free_blend_tick;
@ -342,34 +341,8 @@ INTERNAL void user_update(void)
f64 cur_time = sys_timestamp_seconds(sys_timestamp()); f64 cur_time = sys_timestamp_seconds(sys_timestamp());
L.dt = max_f64(0.0, cur_time - L.time); L.dt = max_f64(0.0, cur_time - L.time);
L.time += L.dt; L.time += L.dt;
/* Calculate screen & viewport dimensions */
{
/* Get screen dimensions */
L.screen_size = sys_window_get_size(L.window); L.screen_size = sys_window_get_size(L.window);
/* Enforce viewport at aspect ratio */
f32 aspect_ratio = ASPECT_RATIO;
f32 width = L.screen_size.x;
f32 height = L.screen_size.y;
if (width / height > aspect_ratio) {
width = height * aspect_ratio;
} else {
height = (f32)math_ceil(width / aspect_ratio);
}
L.viewport_size = V2(width, height);
/* Center viewport in window */
f32 x = 0;
f32 y = 0;
x = math_round(L.screen_size.x / 2 - width / 2);
y = math_round(L.screen_size.y / 2 - height / 2);
L.viewport_screen_offset = V2(x, y);
/* Get center */
L.viewport_center = v2_mul(L.viewport_size, 0.5);
}
/* ========================== * /* ========================== *
* Produce interpolated tick * Produce interpolated tick
* ========================== */ * ========================== */
@ -426,7 +399,7 @@ INTERNAL void user_update(void)
e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend); e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend);
e->animation_time_in_frame = math_lerp_f64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend); e->animation_time_in_frame = math_lerp_f64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
e->camera_zoom = math_lerp(e0->camera_zoom, e1->camera_zoom, tick_blend); e->camera_size = v2_lerp(e0->camera_size, e1->camera_size, tick_blend);
e->camera_target_xform = xform_lerp(e0->camera_target_xform, e1->camera_target_xform, tick_blend); e->camera_target_xform = xform_lerp(e0->camera_target_xform, e1->camera_target_xform, tick_blend);
} }
} }
@ -497,7 +470,6 @@ INTERNAL void user_update(void)
/* Update mouse pos */ /* Update mouse pos */
if (event->kind == SYS_EVENT_KIND_CURSOR_MOVE) { if (event->kind == SYS_EVENT_KIND_CURSOR_MOVE) {
L.screen_cursor = event->cursor_position; L.screen_cursor = event->cursor_position;
L.viewport_cursor = v2_sub(L.screen_cursor, L.viewport_screen_offset);;
} }
/* Update bind states */ /* Update bind states */
@ -548,12 +520,6 @@ INTERNAL void user_update(void)
} }
} }
/* ========================== *
* Update view
* ========================== */
L.world_view_last_frame = L.world_view;
if (L.bind_states[USER_BIND_KIND_DEBUG_DRAW].num_presses > 0) { if (L.bind_states[USER_BIND_KIND_DEBUG_DRAW].num_presses > 0) {
L.debug_draw = !L.debug_draw; L.debug_draw = !L.debug_draw;
} }
@ -562,6 +528,46 @@ INTERNAL void user_update(void)
L.debug_camera = !L.debug_camera; L.debug_camera = !L.debug_camera;
} }
/* ========================== *
* Update viewport
* ========================== */
/* Calculate screen viewport dimensions */
if (L.debug_camera) {
L.viewport_size = L.screen_size;
L.viewport_screen_offset = V2(0, 0);
} else {
/* Determine viewport size by camera & window dimensions */
f32 aspect_ratio = 1.0;
if (!v2_eq(active_camera->camera_size, V2(0, 0))) {
aspect_ratio = active_camera->camera_size.x / active_camera->camera_size.y;
}
f32 width = L.screen_size.x;
f32 height = L.screen_size.y;
if (width / height > aspect_ratio) {
width = height * aspect_ratio;
} else {
height = (f32)math_ceil(width / aspect_ratio);
}
L.viewport_size = V2(width, height);
/* Center viewport in window */
f32 x = 0;
f32 y = 0;
x = math_round(L.screen_size.x / 2 - width / 2);
y = math_round(L.screen_size.y / 2 - height / 2);
L.viewport_screen_offset = V2(x, y);
}
L.viewport_center = v2_mul(L.viewport_size, 0.5);
L.viewport_cursor = v2_sub(L.screen_cursor, L.viewport_screen_offset);
/* ========================== *
* Update view
* ========================== */
if (L.debug_camera) { if (L.debug_camera) {
/* Pan view */ /* Pan view */
if (L.bind_states[USER_BIND_KIND_PAN].is_held) { if (L.bind_states[USER_BIND_KIND_PAN].is_held) {
@ -602,13 +608,18 @@ INTERNAL void user_update(void)
} else { } else {
struct v2 center = active_camera->world_xform.og; struct v2 center = active_camera->world_xform.og;
f32 rot = xform_get_rotation(active_camera->world_xform); f32 rot = xform_get_rotation(active_camera->world_xform);
f32 zoom = active_camera->camera_zoom;
zoom = zoom > 0 ? zoom : 1; /* Scale view into viewport based on camera size */
struct v2 size = L.viewport_size;
if (!v2_eq(active_camera->camera_size, V2(0, 0))) {
size = v2_div_v2(size, active_camera->camera_size);
}
f32 scale = min_f32(size.x, size.y);
struct trs trs = TRS( struct trs trs = TRS(
.t = v2_sub(L.viewport_center, center), .t = v2_sub(L.viewport_center, center),
.r = rot, .r = rot,
.s = v2_mul(V2(PIXELS_PER_UNIT, PIXELS_PER_UNIT), zoom) .s = V2(scale, scale)
); );
struct v2 pivot = center; struct v2 pivot = center;