You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.7 KiB

  1. #![allow(dead_code)]
  2. use glc::{
  3. array_buffer::{ArrayBuffer, Target, Usage},
  4. error::Error,
  5. matrix::Matrix4f,
  6. vector::Vector2f,
  7. };
  8. pub struct Camera {
  9. buffer: ArrayBuffer,
  10. data: Data,
  11. view_invert: Matrix4f,
  12. projection_invert: Matrix4f,
  13. update_counter: usize,
  14. }
  15. #[repr(C, packed)]
  16. #[derive(Clone)]
  17. struct Data {
  18. projection: Matrix4f,
  19. view: Matrix4f,
  20. size: Vector2f,
  21. }
  22. impl Camera {
  23. pub fn new() -> Result<Self, Error> {
  24. let data = Data {
  25. projection: Matrix4f::identity(),
  26. view: Matrix4f::identity(),
  27. size: Vector2f::default(),
  28. };
  29. let mut buffer = ArrayBuffer::new(Target::UniformBuffer)?;
  30. buffer.buffer_data(Usage::StaticDraw, &[data.clone()])?;
  31. Ok(Self {
  32. buffer,
  33. data,
  34. view_invert: Default::default(),
  35. projection_invert: Default::default(),
  36. update_counter: 0,
  37. })
  38. }
  39. pub fn projection(&self) -> &Matrix4f {
  40. &self.data.projection
  41. }
  42. pub fn projection_invert(&self) -> &Matrix4f {
  43. &self.projection_invert
  44. }
  45. pub fn view(&self) -> &Matrix4f {
  46. &self.data.view
  47. }
  48. pub fn view_invert(&self) -> &Matrix4f {
  49. &self.view_invert
  50. }
  51. pub fn update_counter(&self) -> usize {
  52. self.update_counter
  53. }
  54. pub fn size(&self) -> &Vector2f {
  55. &self.data.size
  56. }
  57. pub fn resize(&mut self, w: f32, h: f32) -> Result<(), Error> {
  58. self.data.projection = Matrix4f::ortho(-w / 2.0, w / 2.0, -h / 2.0, h / 2.0, -100.0, 100.0);
  59. self.data.size = (w, h).into();
  60. let mut data = self.buffer.map_mut::<Data>(true)?;
  61. data[0].projection = self.data.projection;
  62. data[0].size = self.data.size;
  63. self.update_counter = self.update_counter.wrapping_add(1);
  64. self.projection_invert = self.data.projection.invert();
  65. Ok(())
  66. }
  67. pub fn update(&mut self, m: Matrix4f) -> Result<(), Error> {
  68. self.update_with(|view| view * m)
  69. }
  70. pub fn update_with<F>(&mut self, f: F) -> Result<(), Error>
  71. where
  72. F: FnOnce(&Matrix4f) -> Matrix4f,
  73. {
  74. self.data.view = f(&self.data.view);
  75. let mut data = self.buffer.map_mut::<Data>(true)?;
  76. data[0].view = self.data.view;
  77. self.update_counter = self.update_counter.wrapping_add(1);
  78. self.view_invert = self.data.view.invert();
  79. Ok(())
  80. }
  81. pub fn bind(&self, index: gl::GLuint) -> Result<(), Error> {
  82. Error::checked(|| self.buffer.bind_buffer_base(index))
  83. }
  84. pub fn world_to_view<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
  85. self.data.view.transform(T::into(pos)).into()
  86. }
  87. pub fn view_to_world<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
  88. self.view_invert.transform(T::into(pos)).into()
  89. }
  90. pub fn view_to_window<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
  91. view_to_window(&self.data.size, pos)
  92. }
  93. pub fn window_to_view<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
  94. window_to_view(&self.data.size, pos)
  95. }
  96. pub fn world_to_window<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
  97. self.view_to_window(self.world_to_view(pos))
  98. }
  99. pub fn window_to_world<T: Into<Vector2f>>(&self, pos: T) -> Vector2f {
  100. self.view_to_world(self.window_to_view(pos))
  101. }
  102. }
  103. pub fn view_to_window<T: Into<Vector2f>>(res: &Vector2f, pos: T) -> Vector2f {
  104. let mut pos = T::into(pos);
  105. pos.x += res.x / 2.0;
  106. pos.y = res.y / 2.0 - pos.y;
  107. pos
  108. }
  109. pub fn window_to_view<T: Into<Vector2f>>(res: &Vector2f, pos: T) -> Vector2f {
  110. let mut pos = T::into(pos);
  111. pos.x -= res.x / 2.0;
  112. pos.y = res.y / 2.0 - pos.y;
  113. pos
  114. }