|
- #![allow(dead_code)]
-
- use glc::{
- array_buffer::{ArrayBuffer, Target, Usage},
- error::Error,
- matrix::Matrix4f,
- vector::Vector2f,
- };
-
- pub struct Camera {
- buffer: ArrayBuffer,
- data: Data,
- view_invert: Matrix4f,
- projection_invert: Matrix4f,
- update_counter: usize,
- }
-
- #[repr(C, packed)]
- #[derive(Clone)]
- struct Data {
- projection: Matrix4f,
- view: Matrix4f,
- size: Vector2f,
- }
-
- impl Camera {
- pub fn new() -> Result<Self, Error> {
- let data = Data {
- projection: Matrix4f::identity(),
- view: Matrix4f::identity(),
- size: Vector2f::default(),
- };
- let mut buffer = ArrayBuffer::new(Target::UniformBuffer)?;
- buffer.buffer_data(Usage::StaticDraw, &[data.clone()])?;
-
- Ok(Self {
- buffer,
- data,
- view_invert: Default::default(),
- projection_invert: Default::default(),
- update_counter: 0,
- })
- }
-
- pub fn projection(&self) -> &Matrix4f {
- &self.data.projection
- }
-
- pub fn projection_invert(&self) -> &Matrix4f {
- &self.projection_invert
- }
-
- pub fn view(&self) -> &Matrix4f {
- &self.data.view
- }
-
- pub fn view_invert(&self) -> &Matrix4f {
- &self.view_invert
- }
-
- pub fn update_counter(&self) -> usize {
- self.update_counter
- }
-
- pub fn size(&self) -> &Vector2f {
- &self.data.size
- }
-
- pub fn resize(&mut self, w: f32, h: f32) -> Result<(), Error> {
- self.data.projection = Matrix4f::ortho(-w / 2.0, w / 2.0, -h / 2.0, h / 2.0, -100.0, 100.0);
- self.data.size = (w, h).into();
-
- let mut data = self.buffer.map_mut::<Data>(true)?;
- data[0].projection = self.data.projection;
- data[0].size = self.data.size;
-
- self.update_counter = self.update_counter.wrapping_add(1);
- self.projection_invert = self.data.projection.invert();
-
- Ok(())
- }
-
- pub fn update(&mut self, m: Matrix4f) -> Result<(), Error> {
- self.update_with(|view| view * m)
- }
-
- pub fn update_with<F>(&mut self, f: F) -> Result<(), Error>
- where
- F: FnOnce(&Matrix4f) -> Matrix4f,
- {
- self.data.view = f(&self.data.view);
-
- let mut data = self.buffer.map_mut::<Data>(true)?;
- data[0].view = self.data.view;
-
- self.update_counter = self.update_counter.wrapping_add(1);
- self.view_invert = self.data.view.invert();
-
- Ok(())
- }
-
- pub fn bind(&self, index: gl::GLuint) -> Result<(), Error> {
- Error::checked(|| self.buffer.bind_buffer_base(index))
- }
-
- pub fn world_to_view<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
- self.data.view.transform(T::into(pos)).into()
- }
-
- pub fn view_to_world<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
- self.view_invert.transform(T::into(pos)).into()
- }
-
- pub fn view_to_window<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
- view_to_window(&self.data.size, pos)
- }
-
- pub fn window_to_view<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
- window_to_view(&self.data.size, pos)
- }
-
- pub fn world_to_window<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
- self.view_to_window(self.world_to_view(pos))
- }
-
- pub fn window_to_world<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
- self.view_to_world(self.window_to_view(pos))
- }
- }
-
- pub fn view_to_window<T: Into<Vector2f>>(res: &Vector2f, pos: T) -> Vector2f {
- let mut pos = T::into(pos);
- pos.x += res.x / 2.0;
- pos.y = res.y / 2.0 - pos.y;
-
- pos
- }
-
- pub fn window_to_view<T: Into<Vector2f>>(res: &Vector2f, pos: T) -> Vector2f {
- let mut pos = T::into(pos);
- pos.x -= res.x / 2.0;
- pos.y = res.y / 2.0 - pos.y;
-
- pos
- }
|