#pragma once
#include <algorithm>
#include "core/globals.h"
#include "core/platform.h"
#include "shaders/renderer_types.h"
using NodeHandle = u32;
constexpr NodeHandle NODE_INVALID = 0xffffffffu;
struct Camera {
NodeHandle node = NODE_INVALID;
vec3 position = vec3(0.0f, 0.0f, 3.0f);
f32 aspect = 0;
// Degrees
f32 yaw_deg = 0.0f; // -Z forward
f32 pitch_deg = 0.0f;
f32 fov_y_deg = 60.0f;
f32 near_plane = 0.01f;
f32 far_plane = 1000.0f;
f32 move_speed = 10.0f;
f32 fast_multiplier = 5.0f;
f32 look_sensitivity = 0.10f; // deg per pixel
static constexpr f32 DEG_TO_RAD = 0.017453292519943295769f;
vec3 forward() const {
f32 yaw = yaw_deg * DEG_TO_RAD;
f32 pitch = pitch_deg * DEG_TO_RAD;
vec3 fwd;
fwd.x = std::cos(yaw) * std::cos(pitch);
fwd.y = std::sin(yaw) * std::cos(pitch);
fwd.z = std::sin(pitch);
return fwd.normalized();
}
vec3 right() const {
return cross(forward(), vec3(0.0f, 0.0f, 1.0f)).normalized();
}
vec3 up() const {
return cross(right(), forward()).normalized();
}
mat4 view;
mat4 proj;
mat4 view_proj;
mat4 inv_view;
mat4 inv_proj;
mat4 inv_view_proj;
};
static void update_camera(Camera &camera, PlatformInput &input) {
camera.yaw_deg -= input.mouse_dx * camera.look_sensitivity;
camera.pitch_deg -= input.mouse_dy * camera.look_sensitivity;
camera.pitch_deg = std::clamp(camera.pitch_deg, -89.0f, 89.0f);
vec3 move_dir(0.0f);
if (input.move_forward)
move_dir += camera.forward();
if (input.move_backward)
move_dir -= camera.forward();
if (input.move_right)
move_dir += camera.right();
if (input.move_left)
move_dir -= camera.right();
if (input.move_up)
move_dir += vec3(0.0f, 0.0f, 1.0f);
if (input.move_down)
move_dir -= vec3(0.0f, 0.0f, 1.0f);
if (move_dir.dot(move_dir) > 0.0f)
move_dir = move_dir.normalized();
f32 speed = camera.move_speed;
if (input.fast)
speed *= camera.fast_multiplier;
camera.position += move_dir * speed * input.dt;
vec3 upv = vec3(0.0f, 0.0f, 1.0f);
camera.view = look_at(camera.position, camera.position + camera.forward(), upv);
camera.proj = perspective(radians(camera.fov_y_deg), camera.aspect, camera.near_plane);
camera.view_proj = camera.view * camera.proj;
camera.inv_view = inverse(camera.view);
camera.inv_proj = inverse(camera.proj);
camera.inv_view_proj = inverse(camera.view_proj);
}