use cgmath::InnerSpace;
use crate::*;
pub trait Render<T> {
fn render(&self, resolution: &RenderResolution) -> T;
fn is_resolution_independent(&self) -> bool {
false
}
}
#[derive(Debug, Clone)]
pub struct RenderResolution {
pub linear: Scalar,
}
impl RenderResolution {
pub fn new(linear: Scalar) -> Self {
Self { linear }
}
pub fn coarse() -> Self {
Self { linear: 1.0 }
}
pub fn medium() -> Self {
Self { linear: 0.25 }
}
pub fn high() -> Self {
Self { linear: 0.1 }
}
pub fn circular_segments(&self, radius: Scalar) -> u32 {
let n = (radius / self.linear * std::f64::consts::PI * 0.5).max(3.0);
2_u32.pow(n.log2().ceil() as u32).clamp(8, 1024)
}
}
impl std::ops::Mul<Mat3> for RenderResolution {
type Output = RenderResolution;
fn mul(self, rhs: Mat3) -> Self::Output {
let scale = (rhs.x.magnitude() * rhs.y.magnitude()).sqrt();
Self {
linear: self.linear / scale,
}
}
}
impl std::ops::Mul<Mat4> for RenderResolution {
type Output = RenderResolution;
fn mul(self, rhs: Mat4) -> Self::Output {
let scale = (rhs.x.magnitude() * rhs.y.magnitude() * rhs.z.magnitude()).powf(1.0 / 3.0);
Self {
linear: self.linear / scale,
}
}
}
impl Default for RenderResolution {
fn default() -> Self {
RenderResolution::medium()
}
}
impl std::fmt::Display for RenderResolution {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "@{}mm", self.linear)
}
}
impl std::hash::Hash for RenderResolution {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
bytemuck::bytes_of(&self.linear).hash(state);
}
}