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