1use cgmath::InnerSpace;
7
8use crate::*;
9
10pub trait Render<T> {
12 fn render(&self, resolution: &RenderResolution) -> T;
14
15 fn is_resolution_independent(&self) -> bool {
19 false
20 }
21}
22
23#[derive(Debug, Clone)]
25pub struct RenderResolution {
26 pub linear: Scalar,
28}
29
30impl RenderResolution {
31 pub fn new(linear: Scalar) -> Self {
33 Self { linear }
34 }
35
36 pub fn coarse() -> Self {
38 Self { linear: 1.0 }
39 }
40
41 pub fn medium() -> Self {
43 Self { linear: 0.25 }
44 }
45
46 pub fn high() -> Self {
48 Self { linear: 0.1 }
49 }
50
51 pub fn circular_segments(&self, radius: Scalar) -> u32 {
55 let n = (radius / self.linear * std::f64::consts::PI * 0.5).max(3.0);
56 2_u32.pow(n.log2().ceil() as u32).clamp(8, 1024)
57 }
58}
59
60impl std::ops::Mul<Mat3> for RenderResolution {
61 type Output = RenderResolution;
62
63 fn mul(self, rhs: Mat3) -> Self::Output {
64 let scale = (rhs.x.magnitude() * rhs.y.magnitude()).sqrt();
65 Self {
66 linear: self.linear / scale,
67 }
68 }
69}
70
71impl std::ops::Mul<Mat4> for RenderResolution {
72 type Output = RenderResolution;
73
74 fn mul(self, rhs: Mat4) -> Self::Output {
75 let scale = (rhs.x.magnitude() * rhs.y.magnitude() * rhs.z.magnitude()).powf(1.0 / 3.0);
76 Self {
77 linear: self.linear / scale,
78 }
79 }
80}
81
82impl Default for RenderResolution {
83 fn default() -> Self {
84 RenderResolution::medium()
85 }
86}
87
88impl std::fmt::Display for RenderResolution {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 write!(f, "@{}mm", self.linear)
91 }
92}
93
94impl std::hash::Hash for RenderResolution {
95 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
96 bytemuck::bytes_of(&self.linear).hash(state);
97 }
98}