diff --git a/camera.odin b/camera.odin index a945c91..cedc8bf 100644 --- a/camera.odin +++ b/camera.odin @@ -1,29 +1,28 @@ package renderer +import "core:math" import "core:math/linalg" Camera :: struct { position: [3]f32, - forward, up: [3]f32, + forward, up, right: [3]f32, - fov: f32, + fov_degrees: f32, near, far: f32, - - yaw, pitch: f32, } -create_camera :: proc(renderer: ^Renderer, position: [3]f32, forward, up: [3]f32, fov, near, far: f32) -> Camera { +create_camera :: proc(renderer: ^Renderer, position: [3]f32, forward, up: [3]f32, fov_degrees, near, far: f32) -> Camera { c: Camera c.position = position c.forward = forward c.up = up - c.fov = fov + c.fov_degrees = fov_degrees c.near = near c.far = far assert(c.forward != {}) assert(c.up != {}) - assert(fov > 0) + assert(fov_degrees > 0) assert(near > 0) assert(far > 0) @@ -34,25 +33,51 @@ get_camera_view_matrix :: proc(camera: ^Camera) -> (linalg.Matrix4f32, bool) { if camera == nil { return {}, false } - + center := camera.position + camera.forward - view_matrix := linalg.identity(linalg.Matrix4x4f32) - view_matrix *= linalg.matrix4_look_at_f32(camera.position, center, camera.up) + view_matrix := linalg.MATRIX4F32_IDENTITY + view_matrix *= linalg.matrix4_look_at_f32(camera.position, center, camera.up, flip_z_axis = true) return view_matrix, true } + get_camera_projection_matrix :: proc(renderer: ^Renderer, camera: ^Camera) -> (linalg.Matrix4f32, bool) { if camera == nil { return {}, false } - projection_matrix := linalg.identity(linalg.Matrix4x4f32) - projection_matrix *= linalg.matrix4_perspective(camera.fov, get_aspect_ratio(renderer), camera.near, camera.far) + projection_matrix := linalg.MATRIX4F32_IDENTITY + projection_matrix *= linalg.matrix4_perspective( + linalg.to_radians(f32(camera.fov_degrees)), + get_aspect_ratio(renderer), + camera.near, + camera.far, + flip_z_axis = true, + ) return projection_matrix, true } +rotate_camera :: proc(camera: ^Camera, yaw, pitch, roll: f32) { + pitch := clamp(pitch, -89.0, 89.0) + + pitch_rad := linalg.to_radians(pitch) + yaw_rad := linalg.to_radians(yaw) + roll_rad := linalg.to_radians(roll) + + camera.forward = [3]f32{ + math.cos(pitch_rad) * math.cos(yaw_rad), + math.sin(pitch_rad), + math.cos(pitch_rad) * math.sin(yaw_rad), + } + + WORLD_UP :: [3]f32{0, 1, 0} + camera.right = linalg.normalize(linalg.cross(camera.forward, WORLD_UP)) + camera.up = linalg.normalize(linalg.cross(camera.right, camera.forward)) + // TODO: SS - Support 'roll'. +} + set_active_camera :: proc(renderer: ^Renderer, camera: ^Camera) { renderer.active_camera = camera } diff --git a/pass.odin b/pass.odin index 8b780a3..fe45475 100644 --- a/pass.odin +++ b/pass.odin @@ -19,6 +19,7 @@ Draw_Command :: struct { mesh: Mesh, material: Material, position: [3]f32, + rotation: [3]f32, scale: [3]f32, // TODO: SS - Add rotation. } diff --git a/renderer.odin b/renderer.odin index df1ee68..02b7ef5 100644 --- a/renderer.odin +++ b/renderer.odin @@ -99,24 +99,25 @@ render_frame :: proc(renderer: ^Renderer) { set_clear_color(renderer, pass.clear_color) clear_screen(renderer, pass.should_clear_depth) enable_depth_testing(renderer, pass.should_test_depth) - + for i in 0..