use cgmath::*;
use gltf::camera::Projection as GltfProjection;
#[derive(Clone, Debug)]
pub struct Camera {
#[cfg(feature = "names")]
pub name: Option<String>,
#[cfg(feature = "extras")]
pub extras: gltf::json::extras::Extras,
pub transform: Matrix4<f32>,
pub projection: Projection,
pub zfar: f32,
pub znear: f32,
}
#[derive(Debug, Clone)]
pub enum Projection {
Perspective {
yfov: Rad<f32>,
aspect_ratio: Option<f32>,
},
Orthographic {
scale: Vector2<f32>,
},
}
impl Default for Projection {
fn default() -> Self {
Self::Perspective {
yfov: Rad(0.399),
aspect_ratio: None,
}
}
}
impl Camera {
pub fn position(&self) -> Vector3<f32> {
Vector3::new(
self.transform[3][0],
self.transform[3][1],
self.transform[3][2],
)
}
pub fn right(&self) -> Vector3<f32> {
Vector3::new(
self.transform[0][0],
self.transform[0][1],
self.transform[0][2],
)
.normalize()
}
pub fn up(&self) -> Vector3<f32> {
Vector3::new(
self.transform[1][0],
self.transform[1][1],
self.transform[1][2],
)
.normalize()
}
pub fn forward(&self) -> Vector3<f32> {
Vector3::new(
self.transform[2][0],
self.transform[2][1],
self.transform[2][2],
)
.normalize()
}
pub fn apply_transform_vector(&self, pos: &Vector3<f32>) -> Vector3<f32> {
let pos = Vector4::new(pos[0], pos[1], pos[2], 0.);
(self.transform * pos).truncate()
}
pub(crate) fn load(gltf_cam: gltf::Camera, transform: &Matrix4<f32>) -> Self {
let mut cam = Self {
transform: *transform,
..Default::default()
};
#[cfg(feature = "names")]
{
cam.name = gltf_cam.name().map(String::from);
}
#[cfg(feature = "extras")]
{
cam.extras = gltf_cam.extras().clone();
}
match gltf_cam.projection() {
GltfProjection::Orthographic(ortho) => {
cam.projection = Projection::Orthographic {
scale: Vector2::new(ortho.xmag(), ortho.ymag()),
};
cam.zfar = ortho.zfar();
cam.znear = ortho.znear();
}
GltfProjection::Perspective(pers) => {
cam.projection = Projection::Perspective {
yfov: Rad(pers.yfov()),
aspect_ratio: pers.aspect_ratio(),
};
cam.zfar = pers.zfar().unwrap_or(f32::INFINITY);
cam.znear = pers.znear();
}
};
cam
}
}
impl Default for Camera {
fn default() -> Self {
Camera {
#[cfg(feature = "names")]
name: None,
#[cfg(feature = "extras")]
extras: None,
transform: Zero::zero(),
projection: Projection::default(),
zfar: f32::INFINITY,
znear: 0.,
}
}
}