add camera calculations

This commit is contained in:
numzero 2026-08-04 23:21:11 +03:00
parent eece7b275b
commit 759b6a4211
2 changed files with 80 additions and 0 deletions

78
src/camera.rs Normal file
View File

@ -0,0 +1,78 @@
use glam::{Affine3A, Mat3, Mat4, vec3};
pub(crate) fn rotation(yaw: f32, pitch: f32) -> Mat3 {
let (ys, yc) = yaw.sin_cos();
let (ps, pc) = pitch.sin_cos();
Mat3::from_cols_array_2d(&[[0., 0., -1.], [-1., 0., 0.], [0., 1., 0.]])
* Mat3::from_cols_array_2d(&[[pc, 0., -ps], [0., 1., 0.], [ps, 0., pc]])
* Mat3::from_cols_array_2d(&[[yc, -ys, 0.], [ys, yc, 0.], [0., 0., 1.]])
}
pub(crate) fn view(yaw: f32, pitch: f32, distance: f32) -> Affine3A {
Affine3A::from_mat3_translation(rotation(yaw, pitch), vec3(0., 0., distance))
}
pub(crate) fn projection(fovy: f32, aspect: f32) -> Mat4 {
Mat4::perspective_lh(fovy, aspect, 0.1, 10.0)
}
#[cfg(test)]
mod tests {
use super::*;
use glam::Vec3;
use std::f32::consts::PI;
#[test]
fn test_rotation() {
let mut ok = true;
for (yaw, pitch, x, y, z) in [
(0.0, 0.0, [0., 0., -1.], [-1., 0., 0.], [0., 1., 0.]),
(0.5, 0.0, [1., 0., 0.], [0., 0., -1.], [0., 1., 0.]),
(0.0, 0.5, [0., -1., 0.], [-1., 0., 0.], [0., 0., -1.]),
(0.5, 0.5, [1., 0., 0.], [0., -1., 0.], [0., 0., -1.]),
] {
let m = rotation(yaw * PI, pitch * PI);
if !m.abs_diff_eq(Mat3::from_cols_array_2d(&[x, y, z]), 1e-3) {
ok = false;
println!("Wrong rotation for {}, {}", 180. * yaw, 180. * pitch);
println!("X: expected: {}, actual: {}", Vec3::from_array(x), m.x_axis);
println!("Y: expected: {}, actual: {}", Vec3::from_array(y), m.y_axis);
println!("Z: expected: {}, actual: {}", Vec3::from_array(z), m.z_axis);
}
}
if !ok {
panic!();
}
}
#[test]
fn test_view() {
let mut ok = true;
for (yaw, pitch, x1, y1, z1) in [
(0.0, 0.0, [0., 0., 2.], [-1., 0., 3.], [0., 1., 3.]),
(0.5, 0.0, [1., 0., 3.], [0., 0., 2.], [0., 1., 3.]),
(0.0, 0.5, [0., -1., 3.], [-1., 0., 3.], [0., 0., 2.]),
(0.5, 0.5, [1., 0., 3.], [0., -1., 3.], [0., 0., 2.]),
] {
let m = view(yaw * PI, pitch * PI, 3.);
for (label, world, expected) in
[('X', Vec3::X, x1), ('Y', Vec3::Y, y1), ('Z', Vec3::Z, z1)]
{
let expected = Vec3::from_array(expected);
let actual = m.transform_point3(world);
if !actual.abs_diff_eq(expected, 1e-3) {
ok = false;
println!(
"Wrong transform for {}, {}: for {label}, expected: {expected}, got: {actual}",
180. * yaw,
180. * pitch
);
}
}
}
if !ok {
panic!();
}
}
}

View File

@ -2,6 +2,8 @@ use std::error::Error;
use glam::{UVec2, Vec4, vec4}; use glam::{UVec2, Vec4, vec4};
mod camera;
const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth16Unorm; const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth16Unorm;
const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb; const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb;