aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/camera.rs
diff options
context:
space:
mode:
Diffstat (limited to 'stockton-render/src/camera.rs')
-rw-r--r--stockton-render/src/camera.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/stockton-render/src/camera.rs b/stockton-render/src/camera.rs
new file mode 100644
index 0000000..dcc9d93
--- /dev/null
+++ b/stockton-render/src/camera.rs
@@ -0,0 +1,59 @@
+//! Things related to converting 3D world space to 2D screen space
+
+use legion::maybe_changed;
+use na::{look_at_lh, perspective_lh_zo};
+use stockton_types::{
+ components::{CameraSettings, CameraVPMatrix, Transform},
+ Vector3,
+};
+
+use stockton_skeleton::{draw_passes::DrawPass, Renderer};
+
+fn euler_to_direction(euler: &Vector3) -> Vector3 {
+ let pitch = euler.x;
+ let yaw = euler.y;
+ let _roll = euler.z; // TODO: Support camera roll
+
+ Vector3::new(
+ yaw.sin() * pitch.cos(),
+ pitch.sin(),
+ yaw.cos() * pitch.cos(),
+ )
+}
+
+#[system(for_each)]
+#[filter(maybe_changed::<Transform>() | maybe_changed::<CameraSettings>())]
+pub fn calc_vp_matrix<DP: DrawPass + 'static>(
+ transform: &Transform,
+ settings: &CameraSettings,
+ matrix: &mut CameraVPMatrix,
+ #[resource] renderer: &Renderer<DP>,
+) {
+ // Get look direction from euler angles
+ let direction = euler_to_direction(&transform.rotation);
+
+ // Converts world space to camera space
+ let view_matrix = look_at_lh(
+ &transform.position,
+ &(transform.position + direction),
+ &Vector3::new(0.0, 1.0, 0.0),
+ );
+
+ // Converts camera space to screen space
+ let projection_matrix = {
+ let mut temp = perspective_lh_zo(
+ renderer.get_aspect_ratio(),
+ settings.fov,
+ settings.near,
+ settings.far,
+ );
+
+ // Vulkan's co-ord system is different from OpenGLs
+ temp[(1, 1)] *= -1.0;
+
+ temp
+ };
+
+ // Chain them together into a single matrix
+ matrix.vp_matrix = projection_matrix * view_matrix;
+}