use super::typ::CameraOP; use crate::{ camera::Camera, components::Program, graphics::{AttaWithProgram, AttachWithMouse}, }; pub struct Operation { camera: Camera, projection: Projection, operation: T, need_update: bool, } impl Operation { pub fn new(operation: T, aspect: f32, fov: f32, z_near: f32, z_far: f32) -> Self { let projection = Projection::new(aspect, fov, z_near, z_far); Self { projection, camera: operation.init_camera(), operation, need_update: true, } } pub fn deal_io(&mut self, io: &super::io::IO) { self.need_update = self.operation.attach_with_mouse( &T::State::from_context(io), &mut self.camera, &mut self.projection, ); } pub fn set_camera(&mut self, f: impl Fn(&mut Camera)) { f(&mut self.camera); self.need_update = true; } pub fn set_projection(&mut self, f: impl Fn(&mut Projection)) { f(&mut self.projection); self.need_update = true; } pub fn attach_with_program(&self, gl: &glow::Context, program: &mut Program) { use glow::HasContext; unsafe { let projection = program.get_uniform_location(gl, "trackball_projection"); gl.uniform_matrix_4_f32_slice(projection.as_ref(), false, self.projection.as_slice()); let view = program.get_uniform_location(gl, "trackball_view"); gl.uniform_matrix_4_f32_slice( view.as_ref(), false, self.camera.get_view_matrix().as_slice(), ); } self.operation.attach_with_program(gl, program); } pub fn attach_with_mouse(&mut self, camera_op: &T::State) -> bool { self.operation .attach_with_mouse(camera_op, &mut self.camera, &mut self.projection) } pub fn is_need_update(&self) -> bool { self.need_update } pub fn reset(&mut self) { self.operation.reset(); self.need_update = true; } } pub struct Projection { fov: f32, z_near: f32, z_far: f32, aspect: f32, projection: nalgebra_glm::Mat4, } impl Projection { fn new(aspect: f32, fov: f32, z_near: f32, z_far: f32) -> Self { let projection = nalgebra_glm::perspective(aspect, fov.to_radians(), z_near, z_far); Self { aspect, fov, z_far, z_near, projection, } } fn new_perspective(&self) -> nalgebra_glm::Mat4 { nalgebra_glm::perspective(self.aspect, self.fov.to_radians(), self.z_near, self.z_far) } pub fn set_aspect(&mut self, aspect: f32) { self.aspect = aspect; self.projection = self.new_perspective(); } pub fn set_fov(&mut self, fov: f32) { self.fov = fov; self.projection = self.new_perspective(); } pub fn set_z_near(&mut self, z_near: f32) { self.z_near = z_near; self.projection = self.new_perspective(); } pub fn set_z_far(&mut self, z_far: f32) { self.z_far = z_far; self.projection = self.new_perspective(); } pub fn fov(&self) -> f32 { self.fov } fn as_slice(&self) -> &[f32] { self.projection.as_slice() } }