From: Brendan Hansen Date: Fri, 17 Dec 2021 19:27:08 +0000 (-0600) Subject: factored out the camera X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=caeaa03196cca5cb4bb96fe15c671ca434e49c1a;p=voxel-shooter.git factored out the camera --- diff --git a/src/build.onyx b/src/build.onyx index 31d4a03..9319bf4 100644 --- a/src/build.onyx +++ b/src/build.onyx @@ -9,6 +9,8 @@ // Primary source files #load "config" #load "main" +#load "camera" +#load "vecmath" // Onyx library code #load "stb_truetype" diff --git a/src/camera.onyx b/src/camera.onyx new file mode 100644 index 0000000..f0b38fe --- /dev/null +++ b/src/camera.onyx @@ -0,0 +1,70 @@ +use package core + +Camera :: struct { + fov: f32; // Radians + window_width, window_height: f32; + + z_near := 0.01f; + z_far := 100.0f; + + x_rot, y_rot: f32; + position: Vector3; +} + +camera_set_fov :: (cam: ^Camera, fov: f32) { + cam.fov = fov * math.PI / 180; + cam.fov = math.clamp(cam.fov, 0, math.PI - 0.001f); +} + +camera_set_window_size :: (use cam: ^Camera, ww, wh: f32) { + window_width = ww; + window_height = wh; +} + +camera_get_view_matrix :: (use cam: ^Camera, out: [16] f32) { + ar := window_width / window_height; + z_range := z_far - z_near; + tan_half_fov := math.sin(fov / 2) / math.cos(fov / 2); + + out[0] = 1 / (tan_half_fov * ar); + out[5] = 1 / tan_half_fov; + out[10] = -z_far / z_range; + out[11] = -1; + out[14] = -z_far*z_near/z_range; +} + +camera_get_forward :: (use cam: ^Camera) -> Vector3 { + return Vector3.{ + math.cos(x_rot) * math.sin(y_rot), + -math.sin(x_rot), + math.cos(y_rot) * math.cos(x_rot) + } |> Vector3.norm(); +} + +camera_get_world_matrix :: (use cam: ^Camera, out: [16] f32) { + forward := Vector3.{ + math.cos(x_rot) * math.sin(y_rot), + -math.sin(x_rot), + math.cos(y_rot) * math.cos(x_rot) + } |> Vector3.norm(); + + side := Vector3.cross(forward, .{0,1,0}) |> Vector3.norm(); + new_up := Vector3.cross(side, forward); + + neg_pos := Vector3.neg(position); + neg_forward := Vector3.neg(forward); + + out[0] = side.x; + out[1] = new_up.x; + out[2] = neg_forward.x; + out[4] = side.y; + out[5] = new_up.y; + out[6] = neg_forward.y; + out[8] = side.z; + out[9] = new_up.z; + out[10] = neg_forward.z; + out[12] = Vector3.dot(side, neg_pos); + out[13] = Vector3.dot(new_up, neg_pos); + out[14] = Vector3.dot(neg_forward, neg_pos); + out[15] = 1; +} diff --git a/src/main.onyx b/src/main.onyx index 29c658e..8307b08 100644 --- a/src/main.onyx +++ b/src/main.onyx @@ -3,9 +3,11 @@ use package core use package glfw3 use package opengles use package stb_truetype - +use package core.intrinsics.onyx { __initialize } window: GLFWwindow_p; +camera: Camera; + create_window :: () => { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); @@ -25,6 +27,7 @@ create_window :: () => { #export "on_resize" (window: GLFWwindow_p, width, height: u32) { glViewport(0, 0, width, height); + camera_set_window_size(^camera, ~~width, ~~height); update_view_matrix(); } @@ -164,84 +167,35 @@ setup_opengl :: () { cube_mesh = make_cube_mesh(); + __initialize(^camera); + camera.position = .{5,5,5}; + camera_set_fov(^camera, 75); + ww, wh: i32; + glfwGetWindowSize(window, ^ww, ^wh); + camera_set_window_size(^camera, ~~ww, ~~wh); + update_view_matrix(); - // update_world_matrix(); + update_world_matrix(); } update_view_matrix :: () { - fov := 75 * math.PI / 180; - fov = math.clamp(fov, 0, math.PI - 0.01f); - - width, height: u32; - glfwGetWindowSize(window, ^width, ^height); - ar := cast(f32) width / cast(f32) height; - z_near := 0.01f; - z_far := 100.0f; - z_range := z_far - z_near; - tan_half_fov := math.sin(fov / 2) / math.cos(fov / 2); - - matrix := GLfloat.[ - 1 / (tan_half_fov * ar), 0, 0, 0, - 0, 1 / (tan_half_fov), 0, 0, - 0, 0, (-z_far) / z_range, -1, - 0, 0, -(z_far*z_near)/z_range, 0, - ]; + view_mat: [16] f32; + camera_get_view_matrix(^camera, view_mat); glBindBuffer(GL_UNIFORM_BUFFER, matrix_block_buffer); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof matrix, ^matrix); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof view_mat, ^view_mat); glBindBuffer(GL_UNIFORM_BUFFER, -1); } -Vector3 :: struct { - x, y, z: f32; - - neg :: macro (v: Vector3) => Vector3.{ -v.x, -v.y, -v.z }; - - dot :: macro (v1, v2: Vector3) -> f32 { - return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; - } - - norm :: macro (v: Vector3) -> Vector3 { - l := math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - return .{ v.x / l, v.y / l, v.z / l }; - } - - cross :: macro (v1, v2: Vector3) -> Vector3 { - return .{ - v1.y * v2.z - v1.z * v2.y, - v1.z * v2.x - v1.x * v2.z, - v1.x * v2.y - v1.y * v2.x, - }; - } -} - -#operator + macro (v1, v2: Vector3) => Vector3.{ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; -#operator - macro (v1, v2: Vector3) => Vector3.{ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; -#operator * macro (v: Vector3, s: f32) => Vector3.{ v.x * s, v.y * s, v.z * s }; - -update_world_matrix :: (position: Vector3, facing: Vector3, up: Vector3) { - forward := Vector3.norm(facing); //center - position); - side := Vector3.cross(forward, up) |> Vector3.norm(); - new_up := Vector3.cross(side, forward); - - neg_pos := Vector3.neg(position); - - matrix := GLfloat.[ - side.x, new_up.x, -forward.x, 0, - side.y, new_up.y, -forward.y, 0, - side.z, new_up.z, -forward.z, 0, - Vector3.dot(side, neg_pos), Vector3.dot(new_up, neg_pos), Vector3.dot(Vector3.neg(forward), neg_pos), 1, - ]; +update_world_matrix :: () { + world_mat: [16] f32; + camera_get_world_matrix(^camera, world_mat); glBindBuffer(GL_UNIFORM_BUFFER, matrix_block_buffer); - glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof f32, sizeof typeof matrix, ^matrix); + glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof f32, sizeof typeof world_mat, ^world_mat); glBindBuffer(GL_UNIFORM_BUFFER, -1); } -theta := 0.0f; // y-axis -phi := 0.0f; // x-axis -pos := Vector3.{ 5, 5, 5 }; - update :: (dt: f32) { #persist t := 0.0f; t += dt; @@ -251,34 +205,28 @@ update :: (dt: f32) { mx, my: f64; glfwGetCursorPos(window, ^mx, ^my); - theta += ~~(last_mouse_x - mx) / 400.0f; - phi += ~~(my - last_mouse_y) / 400.0f; - phi = math.clamp(phi, -math.PI / 2 + 0.1, math.PI / 2 - 0.1); + camera.y_rot += ~~(last_mouse_x - mx) / 400.0f; + camera.x_rot += ~~(my - last_mouse_y) / 400.0f; + camera.x_rot = math.clamp(camera.x_rot, -math.PI / 2 + 0.1, math.PI / 2 - 0.1); last_mouse_x = mx; last_mouse_y = my; - facing := Vector3.{ - math.cos(phi) * math.sin(theta), - -math.sin(phi), - math.cos(theta) * math.cos(phi) - }; - - up := Vector3.{0,1,0}; + facing := camera_get_forward(^camera); if glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS { - pos += Vector3.norm(facing) * 3 * dt; + camera.position += Vector3.norm(facing) * 3 * dt; } if glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS { - pos -= Vector3.norm(facing) * 3 * dt; + camera.position -= Vector3.norm(facing) * 3 * dt; } if glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS { - pos += Vector3.norm(Vector3.cross(facing, up)) * 3 * dt; + camera.position += Vector3.norm(Vector3.cross(facing, .{0,1,0})) * 3 * dt; } if glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS { - pos -= Vector3.norm(Vector3.cross(facing, up)) * 3 * dt; + camera.position -= Vector3.norm(Vector3.cross(facing, .{0,1,0})) * 3 * dt; } - update_world_matrix(pos, facing, up); + update_world_matrix(); } draw :: () { diff --git a/src/vecmath.onyx b/src/vecmath.onyx new file mode 100644 index 0000000..ddc33ea --- /dev/null +++ b/src/vecmath.onyx @@ -0,0 +1,27 @@ + +Vector3 :: struct { + x, y, z: f32; + + neg :: macro (v: Vector3) => Vector3.{ -v.x, -v.y, -v.z }; + + dot :: macro (v1, v2: Vector3) -> f32 { + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; + } + + norm :: macro (v: Vector3) -> Vector3 { + l := math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + return .{ v.x / l, v.y / l, v.z / l }; + } + + cross :: macro (v1, v2: Vector3) -> Vector3 { + return .{ + v1.y * v2.z - v1.z * v2.y, + v1.z * v2.x - v1.x * v2.z, + v1.x * v2.y - v1.y * v2.x, + }; + } +} + +#operator + macro (v1, v2: Vector3) => Vector3.{ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; +#operator - macro (v1, v2: Vector3) => Vector3.{ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; +#operator * macro (v: Vector3, s: f32) => Vector3.{ v.x * s, v.y * s, v.z * s };