--- /dev/null
+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;
+}
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);
#export "on_resize" (window: GLFWwindow_p, width, height: u32) {
glViewport(0, 0, width, height);
+ camera_set_window_size(^camera, ~~width, ~~height);
update_view_matrix();
}
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;
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 :: () {