factored out the camera
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 17 Dec 2021 19:27:08 +0000 (13:27 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 17 Dec 2021 19:27:08 +0000 (13:27 -0600)
src/build.onyx
src/camera.onyx [new file with mode: 0644]
src/main.onyx
src/vecmath.onyx [new file with mode: 0644]

index 31d4a030b50b52ab385f591cacabdce1f65a46f3..9319bf4fb06d7104bfb252d5d1687a65861bd8e7 100644 (file)
@@ -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 (file)
index 0000000..f0b38fe
--- /dev/null
@@ -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;
+}
index 29c658e2adc07407ce918c95d6f516cfade7f84a..8307b0805b3430df2bbf3d18cf6b32175db54dde 100644 (file)
@@ -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 (file)
index 0000000..ddc33ea
--- /dev/null
@@ -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 };