/ core / src / camera.rs
camera.rs
 1  //! Camera and vision related settings.
 2  
 3  use glam::{Vec2, vec2};
 4  
 5  /// The Camera scaling modes determine how far you can see when the aspect ratio changes.
 6  ///
 7  /// Each mode calculates how far the camera can see in world space units depending on the provided dimensions multiplied by the zoom value.
 8  #[derive(Clone, Copy, Debug, Default)]
 9  #[non_exhaustive]
10  pub enum CameraScaling {
11      /// Keeps the view size fixed from -1  to 1 in both axes regardless of provided dimensions.
12      #[default]
13      Stretch,
14  
15      /// Preserves the total visible surface area regardless of shape.
16      ///
17      /// This means the narrower the dimensions are, the farther you can see in that direction.
18      ///
19      /// The product of width and height equals 1 here.
20      Linear,
21  
22      /// Constrains the visible area to fit within a circle centered at the camera origin.
23      ///
24      /// Just like `Box`, but instead of a rectangular box bound, the extend fits within a circle.
25      ///
26      /// This prevents viewing further in extreme aspect ratios, a problem with `Linear`.
27      Circle,
28  
29      /// The largest side of the view is always exactly -1 to 1.
30      ///
31      /// The smaller the dimensions are, the more limited the view in the smaller dimension is.
32      Box,
33  
34      /// Makes the view grow with the render size. This is good for UI and pixel perfect rendering.
35      ///
36      /// Here one pixel equates to one unit of world space. Here you should set your zoom of the camera with this mode set.
37      Expand,
38  
39      /// The horizontal view area is locked at -1 to 1 and allows the vertical axis to expand or shrink.
40      ///
41      /// This one is useful for platformers where consistent horizontal field of view is important.
42      KeepHorizontal,
43  
44      /// The vertical view area is locked at -1 to 1 and allows the horizontal axis to expand or shrink.
45      ///
46      /// This one is great for top down or vertical scrolling games.
47      KeepVertical,
48  
49      /// User defined scaling option.
50      Custom(fn(Vec2) -> Vec2),
51  }
52  
53  #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Default)]
54  pub enum CameraMode {
55      #[default]
56      Orthographic,
57      Perspective {
58          fov_y_rad: f32,
59      },
60      Frustum,
61  }
62  
63  impl CameraScaling {
64      /// Scales the given dimensions using the given scaling algorithm.
65      ///
66      /// Takes a dimension and outputs the maximum field of view in both axis using those dimensions.
67      pub fn scale(&self, dimensions: Vec2) -> Vec2 {
68          match self {
69              // Camera view x1 and y1 max and min.
70              CameraScaling::Stretch => Vec2::ONE,
71              CameraScaling::Linear => vec2(
72                  0.5 / (dimensions.y / (dimensions.x + dimensions.y)),
73                  0.5 / (dimensions.x / (dimensions.x + dimensions.y)),
74              ),
75              CameraScaling::Circle => {
76                  let radius = 1.0 / dimensions.length();
77                  dimensions * radius
78              }
79              CameraScaling::Box => vec2(
80                  1.0 / (dimensions.y / dimensions.x.clamp(0.0, dimensions.y)),
81                  1.0 / (dimensions.x / dimensions.y.clamp(0.0, dimensions.x)),
82              ),
83              CameraScaling::Expand => dimensions,
84              CameraScaling::KeepHorizontal => vec2(1.0, 1.0 / (dimensions.x / dimensions.y)),
85              CameraScaling::KeepVertical => vec2(1.0 / (dimensions.y / dimensions.x), 1.0),
86              CameraScaling::Custom(f) => f(dimensions),
87          }
88      }
89  }