pub struct Camera {
    pub distance: f32,
    pub azimuth: f32,
    pub elevation: f32,
    pub target: [f32; 3],
    pub fov: f32,
}

impl Camera {
    pub fn new(scene_radius: f32) -> Self {
        Self {
            distance: scene_radius * 3.0,
            azimuth: 0.4,
            elevation: 0.5,
            target: [0.0, 0.0, 0.0],
            fov: 1.5,
        }
    }

    pub fn position(&self) -> [f32; 3] {
        let cos_el = self.elevation.cos();
        [
            self.target[0] + self.distance * cos_el * self.azimuth.cos(),
            self.target[1] + self.distance * cos_el * self.azimuth.sin(),
            self.target[2] + self.distance * self.elevation.sin(),
        ]
    }

    pub fn orbit(&mut self, d_azimuth: f32, d_elevation: f32) {
        self.azimuth += d_azimuth;
        self.elevation = (self.elevation + d_elevation)
            .clamp(-std::f32::consts::FRAC_PI_2 + 0.01, std::f32::consts::FRAC_PI_2 - 0.01);
    }

    pub fn zoom(&mut self, delta: f32) {
        self.distance *= (-delta * 0.1).exp();
        self.distance = self.distance.max(0.1);
    }
}
