use rin_math::{
Deg, Rad, Angle, Pnt3, pnt3, Mat4, vec4, Perspective3, Unit, Vec3, UnitQuat, Vec4, one, ToVec,
FastInverse, Vec2
};
use super::{Node, NodeRef, NodeMut, CoordinateOrigin};
use rin_window as window;
use rin_util::{ValueCache, Result};
use std::mem;
use std::f32;
#[cfg(feature="serialize")]
use serde_derive::{Serialize, Deserialize};
#[derive(Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct Camera{
node: Node,
view: Mat4,
projection: Mat4,
proj_view: Mat4,
aspect_ratio: f32,
znear: f32,
zfar: Option<f32>,
fov: Deg<f32>,
sensor_width_mm: f32,
target: ValueCache<Pnt3>,
up: Unit<Vec3>,
projection_changed: bool,
clamp_depth: bool,
reversed_z: bool,
oblique_clip_plane: Option<Vec4>,
}
pub struct Builder{
eye: Pnt3,
look_at: Pnt3,
fov: Deg<f32>,
sensor_width_mm: f32,
aspect_ratio: f32,
znear_far: Option<(f32, Option<f32>)>,
up: Unit<Vec3>,
clamp_depth: bool,
reversed_z: bool,
infinite_far: bool,
oblique_clip_plane: Option<Vec4>,
}
impl Builder{
pub fn new(aspect_ratio: f32) -> Builder{
Builder{
eye: Pnt3::origin(),
look_at: pnt3(0., 0., -1.),
fov: Deg(60f32),
sensor_width_mm: 35.,
aspect_ratio: aspect_ratio,
znear_far: None,
up: Unit::new_unchecked(Vec3::y()),
clamp_depth: false,
reversed_z: false,
infinite_far: false,
oblique_clip_plane: None,
}
}
pub fn from_window<W: window::WindowExt>(window: &W) -> Builder{
Builder::new(window.aspect_ratio())
}
#[deprecated(since = "0.11", note = "Please use near_far instead")]
pub fn clip_planes(&mut self, znear: f32, zfar: f32) -> &mut Builder{
self.znear_far = Some((znear, Some(zfar)));
self
}
pub fn near_far<F: Into<Option<f32>>>(&mut self, znear: f32, zfar: F) -> &mut Builder{
self.znear_far = Some((znear, zfar.into()));
self
}
pub fn near_with_far_at_infinity(&mut self, znear: f32) -> &mut Builder{
self.znear_far = Some((znear, None));
self.infinite_far = true;
self
}
pub fn up_axis(&mut self, up: Unit<Vec3>) -> &mut Builder{
self.up = up;
self
}
pub fn position(&mut self, pos: Pnt3) -> &mut Builder{
self.eye = pos;
self
}
pub fn look_at(&mut self, target: Pnt3) -> &mut Builder{
self.look_at = target;
self
}
pub fn fov(&mut self, fov: Deg<f32>) -> &mut Builder{
self.fov = fov;
self
}
pub fn hfov(&mut self, hfov: Deg<f32>) -> &mut Builder{
self.fov = Rad(2. * ((hfov * 0.5).tan() * self.aspect_ratio).atan()).to_deg();
self
}
pub fn aspect_ratio(&mut self, aspect_ratio: f32) -> &mut Builder{
self.aspect_ratio = aspect_ratio;
self
}
pub fn clamp_depth(&mut self) -> &mut Builder{
self.clamp_depth = true;
self
}
pub fn reversed_z(&mut self) -> &mut Builder{
self.reversed_z = true;
self
}
pub fn oblique_near_clip_plane(&mut self, plane: Vec4) -> &mut Builder {
self.oblique_clip_plane = Some(plane);
self
}
pub fn sensor_width_mm(&mut self, sensor_width: f32) -> &mut Builder {
self.sensor_width_mm = sensor_width;
self
}
pub fn focal_length(&mut self, f: f32) -> &mut Builder {
self.fov = Rad(2. * (self.sensor_width_mm * 0.5 / f).atan()).to_deg();
self
}
pub fn build(&self) -> Result<Camera>{
let znear;
let zfar;
if let Some((near, far)) = self.znear_far{
zfar = if self.infinite_far{
None
}else{
far
};
znear = near;
}else{
let half_fov = self.fov/2.0;
let tan = half_fov.tan();
let dist = (self.look_at - self.eye).norm() / tan;
znear = dist / 100.0;
zfar = if self.infinite_far{ None } else { Some(dist * 10.0) };
};
let node = Node::new_look_at(self.eye, self.look_at, *self.up)?;
let view = node.inv_global_transformation();
let mut camera = Camera {
fov: self.fov,
sensor_width_mm: self.sensor_width_mm,
znear: znear,
zfar: zfar,
view: view,
aspect_ratio: self.aspect_ratio,
proj_view: one(),
projection: one(),
target: ValueCache::new(self.look_at),
up: self.up,
node: node,
projection_changed: true,
clamp_depth: self.clamp_depth,
reversed_z: self.reversed_z,
oblique_clip_plane: self.oblique_clip_plane,
};
camera.refresh_projection();
Ok(camera)
}
}
impl Camera{
pub fn new(eye: Pnt3, look_at: Pnt3, up: Unit<Vec3>, fov: Deg<f32>, aspect_ratio: f32) -> Result<Camera> {
Builder::new(aspect_ratio)
.position(eye)
.look_at(look_at)
.up_axis(up)
.fov(fov)
.build()
}
pub fn new_with_frustum(
eye: Pnt3,
look_at: Pnt3,
up: Unit<Vec3>,
fov: Deg<f32>,
aspect_ratio: f32,
znear: f32,
zfar: f32) -> Result<Camera>
{
Builder::new(aspect_ratio)
.position(eye)
.look_at(look_at)
.up_axis(up)
.fov(fov)
.near_far(znear, zfar)
.build()
}
pub fn with_pixel_coordinates(size: Vec2<i32>, fov: Deg<f32>, coordinate_origin: CoordinateOrigin) -> Camera {
let eye_x = size.x as f32 / 2.0;
let eye_y = size.y as f32 / 2.0;
let aspect_ratio = size.x as f32 / size.y as f32;
let half_fov = fov * 0.5;
let the_tan = half_fov.tan();
let fd = 1.0 / the_tan;
let dist = eye_y * fd;
let (eye_x, eye_y, up) = match coordinate_origin{
CoordinateOrigin::TopLeft => (-eye_x, eye_y, -Vec3::y_axis()),
CoordinateOrigin::BottomLeft => (eye_x, eye_y, Vec3::y_axis()),
CoordinateOrigin::CenterDown => (0., 0., -Vec3::y_axis() ),
CoordinateOrigin::CenterUp => (0., 0., Vec3::y_axis() )
};
let znear = dist / 10.;
let zfar = dist * 10.;
Builder::new(aspect_ratio)
.position(pnt3!(eye_x, eye_y, dist))
.fov(fov)
.near_far(znear, zfar)
.look_at(pnt3!(eye_x, eye_y, 0.))
.up_axis(up)
.build()
.unwrap()
}
pub fn projection(&self) -> Mat4{
self.projection
}
pub fn view(&self) -> Mat4{
self.view
}
pub fn projection_view(&self) -> Mat4{
self.proj_view
}
pub fn fov(&self) -> Deg<f32>{
self.fov
}
pub fn hfov(&self) -> Deg<f32> {
Rad(2. * ((self.fov * 0.5).tan() * self.aspect_ratio).atan()).to_deg()
}
pub fn set_fov(&mut self, fov: Deg<f32>){
self.fov = fov;
self.refresh_projection();
}
pub fn focal_length(&self) -> f32 {
self.sensor_width_mm * 0.5 / (self.fov * 0.5).tan()
}
pub fn set_focal_length(&mut self, f: f32) {
self.fov = Rad(2. * (self.sensor_width_mm * 0.5 / f).atan()).to_deg();
self.refresh_projection();
}
pub fn set_sensor_width(&mut self, w: f32) {
let f = self.focal_length();
self.sensor_width_mm = w;
self.set_focal_length(f)
}
pub fn near_far_clip(&self) -> (f32, Option<f32>){
(self.znear, self.zfar)
}
pub fn near_clip(&self) -> f32{
self.znear
}
pub fn far_clip(&self) -> Option<f32>{
self.zfar
}
pub fn set_near(&mut self, near: f32){
self.znear = near;
self.refresh_projection();
}
pub fn set_far(&mut self, far: f32){
self.zfar = Some(far);
self.refresh_projection();
}
pub fn set_far_at_infinity(&mut self){
self.zfar = None;
self.refresh_projection();
}
pub fn set_reversed_z(&mut self, reversed_z: bool) {
self.reversed_z = reversed_z;
self.refresh_projection();
}
pub fn set_near_far<F: Into<Option<f32>>>(&mut self, near: f32, far: F){
self.znear = near;
self.zfar = far.into();
self.refresh_projection();
}
pub fn set_aspect_ratio(&mut self, aspect: f32){
self.aspect_ratio = aspect;
self.refresh_projection();
}
pub fn target(&self) -> &Pnt3{
&self.target
}
pub fn set_target(&mut self, target: Pnt3){
*self.target = target;
}
pub fn enable_depth_clamp(&mut self){
self.clamp_depth = true;
}
pub fn disable_depth_clamp(&mut self){
self.clamp_depth = false;
}
pub fn depth_clamp(&self) -> bool{
self.clamp_depth
}
pub fn far_at_infinity(&self) -> bool{
self.zfar.is_none()
}
pub fn reversed_z(&self) -> bool {
self.reversed_z
}
pub fn set_oblique_near_clip_plane<P: Into<Option<Vec4>>>(&mut self, plane: P) {
self.oblique_clip_plane = plane.into()
}
pub fn oblique_clip_plane(&self) -> Option<&Vec4>{
self.oblique_clip_plane.as_ref()
}
pub fn update(&mut self) -> bool{
self.update_with_parent(None)
}
fn refresh_projection(&mut self){
self.projection_changed = true;
if let Some(zfar) = self.zfar {
if self.reversed_z {
let proj = Perspective3::new(self.aspect_ratio, self.fov.to_rad().value(), zfar, self.znear);
self.projection = *proj.as_matrix();
}else{
let proj = Perspective3::new(self.aspect_ratio, self.fov.to_rad().value(), self.znear, zfar);
self.projection = *proj.as_matrix();
}
}else{
let f = 1. / (self.fov * 0.5).tan();
if self.reversed_z{
self.projection = Mat4::new(
f / self.aspect_ratio, 0., 0., 0.,
0., f, 0., 0.,
0., 0., 0., self.znear,
0., 0., -1., 0.
);
}else{
self.projection = Mat4::new(
f / self.aspect_ratio, 0., 0., 0.,
0., f, 0., 0.,
0., 0., -1., -self.znear,
0., 0., -1., 0.
);
}
}
if let Some(plane) = self.oblique_clip_plane{
let q = vec4(
(plane.x.signum() + self.projection[(0,2)]) / self.projection[(0,0)],
(plane.y.signum() + self.projection[(1,2)]) / self.projection[(1,1)],
-1.,
(1. + self.projection[(2,2)]) / self.projection[(2,3)]
);
let c = plane * (2. / plane.dot(&q));
self.projection[(2,0)] = c.x;
self.projection[(2,1)] = c.y;
self.projection[(2,2)] = c.z + 1.;
self.projection[(2,3)] = c.w;
}
self.proj_view = self.projection * self.view;
}
}
impl NodeRef for Camera {
fn node(&self) -> &Node{
&self.node
}
}
impl NodeMut for Camera{
fn node_mut(&mut self) -> &mut Node{
&mut self.node
}
fn update_with_parent_parts(
&mut self,
parent_loc: Option<&Node>,
parent_orientation: Option<&Node>,
parent_scale: Option<&Node>) -> bool
{
if self.target.has_changed(){
let _ = self.node.look_at(&self.target, &self.up);
}
self.target.update();
if self.node.update_with_parent_parts(parent_loc, parent_orientation, parent_scale) {
self.view = self.node.global_transformation().fast_orthonormal_inverse();
self.proj_view = self.projection * self.view;
self.projection_changed = false;
true
}else{
mem::replace(&mut self.projection_changed, false)
}
}
fn look_at(&mut self, at: &Pnt3, up: &Vec3) -> Result<()>{
let ret = self.node_mut().look_at(at, up);
if ret.is_ok() {
*self.target = *at;
self.up = Unit::new_normalize(*up);
}
ret
}
fn rotate(&mut self, angle: Rad<f32>, axis: &Unit<Vec3>){
let orientation = UnitQuat::from_axis_angle(axis, angle.value());
let new_target = orientation * *self.target;
self.target.set(new_target);
self.node_mut().append_orientation(&orientation);
}
fn append_orientation(&mut self, orientation: &UnitQuat){
let new_target = orientation * *self.target;
self.target.set(new_target);
self.node_mut().append_orientation(orientation);
}
fn tilt(&mut self, angle: Rad<f32>){
let axis = self.local_x_axis();
self.node_mut().rotate(angle, &axis);
}
fn pan(&mut self, angle: Rad<f32>){
let axis = self.local_y_axis();
self.node_mut().rotate(angle, &axis);
}
fn roll(&mut self, angle: Rad<f32>){
let axis = self.local_z_axis();
self.node_mut().rotate(angle, &axis);
}
fn set_scale(&mut self, _: Vec3){
}
fn translate(&mut self, t: &Vec3){
self.node_mut().translate(t);
*self.target += *t;
}
fn set_position(&mut self, pos: Pnt3){
let diff = pos - self.position().to_vec();
self.node_mut().set_position(pos);
*self.target += diff.to_vec();
}
fn set_angle_axis(&mut self, angle: Rad<f32>, axis: &Unit<Vec3>){
let orientation = UnitQuat::from_axis_angle(axis, angle.value());
let new_target = orientation * *self.target;
self.target.set(new_target);
self.node_mut().set_orientation(orientation);
}
fn set_orientation(&mut self, orientation: UnitQuat){
let new_target = orientation * *self.target;
self.target.set(new_target);
self.node_mut().set_orientation(orientation);
}
}
pub trait CameraExt: NodeRef + NodeMut {
fn projection(&self) -> Mat4;
fn view(&self) -> Mat4;
fn projection_view(&self) -> Mat4;
fn fov(&self) -> Option<Deg<f32>>;
fn width(&self) -> Option<f32>;
fn near_far_clip(&self) -> (f32, Option<f32>);
fn near_clip(&self) -> f32;
fn far_clip(&self) -> Option<f32>;
fn target(&self) -> &Pnt3;
fn up(&self) -> &Unit<Vec3>;
fn aspect_ratio(&self) -> f32;
fn set_near(&mut self, near: f32);
fn set_far(&mut self, far: f32);
fn set_near_far(&mut self, near: f32, far: f32);
fn set_aspect_ratio(&mut self, aspect: f32);
fn set_target(&mut self, target: Pnt3);
fn set_reversed_z(&mut self, reversed_z: bool);
fn reversed_z(&self) -> bool;
fn far_at_infinity(&self) -> bool;
fn hfov(&self) -> Option<Deg<f32>>;
fn focal_length(&self) -> Option<f32>;
fn sensor_width_mm(&self) -> Option<f32>;
fn enable_depth_clamp(&mut self);
fn disable_depth_clamp(&mut self);
fn depth_clamp(&self) -> bool;
fn update(&mut self) -> bool;
}
pub trait CameraPerspective: CameraExt {
fn set_fov(&mut self, fov: Deg<f32>);
fn set_near_with_far_at_infinity(&mut self, near: f32);
}
pub trait CameraOrthographic: CameraExt{
fn set_width(&mut self, width: f32);
}
impl CameraExt for Camera{
fn projection(&self) -> Mat4{
self.projection
}
fn view(&self) -> Mat4{
self.view
}
fn projection_view(&self) -> Mat4{
self.proj_view
}
fn fov(&self) -> Option<Deg<f32>>{
Some(self.fov)
}
fn width(&self) -> Option<f32>{
None
}
fn near_far_clip(&self) -> (f32, Option<f32>){
(self.znear, self.zfar)
}
fn near_clip(&self) -> f32{
self.znear
}
fn far_clip(&self) -> Option<f32>{
self.zfar
}
fn set_near(&mut self, near: f32){
self.znear = near;
self.refresh_projection();
}
fn set_far(&mut self, far: f32){
self.zfar = Some(far);
self.refresh_projection();
}
fn set_near_far(&mut self, near: f32, far: f32){
self.znear = near;
self.zfar = Some(far);
self.refresh_projection();
}
fn set_aspect_ratio(&mut self, aspect: f32){
self.aspect_ratio = aspect;
self.refresh_projection();
}
fn hfov(&self) -> Option<Deg<f32>> {
Some(Rad(2. * ((self.fov * 0.5).tan() * self.aspect_ratio).atan()).to_deg())
}
fn focal_length(&self) -> Option<f32> {
Some(self.sensor_width_mm * 0.5 / (self.fov * 0.5).tan())
}
fn sensor_width_mm(&self) -> Option<f32> {
Some(self.sensor_width_mm)
}
fn aspect_ratio(&self) -> f32{
self.aspect_ratio
}
fn target(&self) -> &Pnt3{
&*self.target
}
fn up(&self) -> &Unit<Vec3>{
&self.up
}
fn set_target(&mut self, target: Pnt3){
*self.target = target;
}
fn enable_depth_clamp(&mut self){
self.clamp_depth = true;
}
fn disable_depth_clamp(&mut self){
self.clamp_depth = false;
}
fn depth_clamp(&self) -> bool{
self.clamp_depth
}
fn set_reversed_z(&mut self, reversed_z: bool){
self.reversed_z = reversed_z;
self.refresh_projection();
}
fn reversed_z(&self) -> bool{
self.reversed_z
}
fn far_at_infinity(&self) -> bool{
self.zfar.is_none()
}
fn update(&mut self) -> bool{
self.update()
}
}
impl CameraPerspective for Camera{
fn set_fov(&mut self, fov: Deg<f32>){
self.fov = fov;
self.refresh_projection();
}
fn set_near_with_far_at_infinity(&mut self, near: f32){
self.znear = near;
self.zfar = None;
self.refresh_projection();
}
}
pub mod ortho_camera {
use rin_math::{
Deg, Rad, Angle, Pnt3, Mat4, vec4, Vec4, Unit, Vec3, UnitQuat, Orthographic3, pnt3, one,
FastInverse, ToVec, Vec2
};
use crate::{Node, NodeRef, NodeMut, CoordinateOrigin};
use super::{CameraExt, CameraOrthographic};
use rin_util::{ValueCache, Result};
use rin_window as window;
use std::mem;
pub struct OrthoCamera{
node: Node,
target: ValueCache<Pnt3>,
up: Unit<Vec3>,
view: Mat4,
projection: Mat4,
proj_view: Mat4,
left: f32,
right: f32,
bottom: f32,
top: f32,
znear: f32,
zfar: f32,
projection_changed: bool,
clamp_depth: bool,
reversed_z: bool,
oblique_clip_plane: Option<Vec4>,
}
pub struct Builder{
eye: Pnt3,
look_at: Pnt3,
aspect_ratio: f32,
znear_far: Option<(f32,f32)>,
width: Option<f32>,
up: Unit<Vec3>,
clamp_depth: bool,
reversed_z: bool,
oblique_clip_plane: Option<Vec4>,
}
impl Builder{
pub fn new(aspect_ratio: f32) -> Builder{
Builder{
eye: Pnt3::origin(),
look_at: pnt3(0., 0., -1.),
aspect_ratio: aspect_ratio,
znear_far: None,
width: None,
up: Vec3::y_axis(),
clamp_depth: false,
reversed_z: false,
oblique_clip_plane: None,
}
}
pub fn from_window<W: window::WindowExt>(window: &W) -> Builder{
Builder::new(window.aspect_ratio())
}
#[deprecated(since = "0.11", note = "Please use near_far instead")]
pub fn clip_planes(&mut self, znear: f32, zfar: f32) -> &mut Builder{
self.znear_far = Some((znear, zfar));
self
}
pub fn near_far(&mut self, znear: f32, zfar: f32) -> &mut Builder{
self.znear_far = Some((znear, zfar));
self
}
pub fn up_axis(&mut self, up: Unit<Vec3>) -> &mut Builder{
self.up = up;
self
}
pub fn position(&mut self, pos: Pnt3) -> &mut Builder{
self.eye = pos;
self
}
pub fn look_at(&mut self, target: Pnt3) -> &mut Builder{
self.look_at = target;
self
}
pub fn aspect_ratio(&mut self, aspect_ratio: f32) -> &mut Builder{
self.aspect_ratio = aspect_ratio;
self
}
pub fn width(&mut self, width: f32) -> &mut Builder{
self.width = Some(width);
self
}
pub fn clamp_depth(&mut self) -> &mut Builder{
self.clamp_depth = true;
self
}
pub fn reversed_z(&mut self) -> &mut Builder{
self.reversed_z = true;
self
}
pub fn oblique_near_clip_plane(&mut self, plane: Vec4) -> &mut Builder {
self.oblique_clip_plane = Some(plane);
self
}
pub fn build(&self) -> Result<OrthoCamera>{
let width = self.width.unwrap_or_else(||{
let dist = (self.look_at - self.eye).norm();
dist
});
let left = -width / 2.;
let right = width / 2.;
let bottom = left / self.aspect_ratio;
let top = right / self.aspect_ratio;
let znear;
let zfar;
if let Some((near, far)) = self.znear_far{
znear = near;
zfar = far;
}else{
let dist = (self.look_at - self.eye).norm();
znear = dist / 100.0;
zfar = dist * 10.0;
};
let node = Node::new_look_at(self.eye, self.look_at, *self.up)?;
let view = node.inv_global_transformation();
let mut camera = OrthoCamera {
left,
right,
bottom,
top,
znear,
zfar,
target: ValueCache::new(self.look_at),
up: self.up,
view: view,
proj_view: one(),
projection: one(),
node: node,
projection_changed: true,
clamp_depth: self.clamp_depth,
reversed_z: self.reversed_z,
oblique_clip_plane: self.oblique_clip_plane,
};
camera.refresh_projection();
Ok(camera)
}
}
impl OrthoCamera{
pub fn new(eye: Pnt3,
look_at: Pnt3,
up: Unit<Vec3>,
aspect_ratio: f32) -> Result<OrthoCamera>
{
Builder::new(aspect_ratio)
.position(eye)
.look_at(look_at)
.up_axis(up)
.build()
}
pub fn new_with_frustum(eye: Pnt3,
look_at: Pnt3,
up: Unit<Vec3>,
left: f32,
right: f32,
bottom: f32,
top: f32,
znear: f32,
zfar: f32) -> Result<OrthoCamera> {
let node = Node::new_look_at(eye, look_at, *up)?;
let view = node.inv_global_transformation();
let mut camera = OrthoCamera {
left,
right,
bottom,
top,
znear,
zfar,
target: ValueCache::new(look_at),
up,
view: view,
proj_view: one(),
projection: one(),
node: node,
projection_changed: true,
clamp_depth: false,
reversed_z: false,
oblique_clip_plane: None,
};
camera.refresh_projection();
Ok(camera)
}
pub fn with_pixel_coordinates(size: Vec2<i32>, coordinate_origin: CoordinateOrigin) -> OrthoCamera {
let (eye_x, eye_y, up) = match coordinate_origin {
CoordinateOrigin::CenterUp => (0., 0., Vec3::y_axis()),
CoordinateOrigin::CenterDown => (0., 0., - Vec3::y_axis()),
CoordinateOrigin::BottomLeft => (size.x as f32 * 0.5, size.y as f32 * 0.5, Vec3::y_axis()),
CoordinateOrigin::TopLeft => (-size.x as f32 * 0.5, size.y as f32 * 0.5, -Vec3::y_axis()),
};
Builder::new(size.x as f32 / size.y as f32)
.near_far(-1., 1.)
.width(size.x as f32)
.position(pnt3(eye_x, eye_y, 0.))
.look_at(pnt3(eye_x, eye_y, -1.))
.up_axis(up)
.build()
.unwrap()
}
pub fn projection(&self) -> Mat4{
self.projection
}
pub fn view(&self) -> Mat4{
self.view
}
pub fn projection_view(&self) -> Mat4{
self.proj_view
}
pub fn near_far_clip(&self) -> (f32,f32){
(self.znear, self.zfar)
}
pub fn near_clip(&self) -> f32{
self.znear
}
pub fn far_clip(&self) -> f32{
self.zfar
}
pub fn set_near(&mut self, near: f32){
self.znear = near;
self.refresh_projection();
}
pub fn set_far(&mut self, far: f32){
self.zfar = far;
self.refresh_projection();
}
pub fn set_near_far(&mut self, near: f32, far: f32){
self.znear = near;
self.zfar = far;
self.refresh_projection();
}
pub fn set_aspect_ratio(&mut self, aspect: f32){
self.bottom = self.left / aspect;
self.top = self.right / aspect;
self.refresh_projection();
}
pub fn target(&self) -> &Pnt3{
&self.target
}
pub fn set_target(&mut self, target: Pnt3){
*self.target = target;
}
pub fn left(&self) -> f32{
self.left
}
pub fn right(&self) -> f32{
self.right
}
pub fn bottom(&self) -> f32{
self.bottom
}
pub fn top(&self) -> f32{
self.top
}
pub fn set_left(&mut self, left: f32) {
self.left = left;
self.refresh_projection();
}
pub fn set_right(&mut self, right: f32) {
self.right = right;
self.refresh_projection();
}
pub fn set_bottom(&mut self, bottom: f32) {
self.bottom = bottom;
self.refresh_projection();
}
pub fn set_top(&mut self, top: f32) {
self.top = top;
self.refresh_projection();
}
pub fn set_reversed_z(&mut self, reversed_z: bool) {
self.reversed_z = reversed_z;
self.refresh_projection();
}
pub fn enable_depth_clamp(&mut self){
self.clamp_depth = true;
}
pub fn disable_depth_clamp(&mut self){
self.clamp_depth = false;
}
pub fn depth_clamp(&self) -> bool{
self.clamp_depth
}
pub fn reversed_z(&self) -> bool {
self.reversed_z
}
pub fn set_oblique_near_clip_plane<P: Into<Option<Vec4>>>(&mut self, plane: P) {
self.oblique_clip_plane = plane.into()
}
pub fn oblique_clip_plane(&self) -> Option<&Vec4>{
self.oblique_clip_plane.as_ref()
}
pub fn update(&mut self) -> bool{
self.update_with_parent(None)
}
fn refresh_projection(&mut self){
self.projection_changed = true;
if self.reversed_z {
let proj = Orthographic3::new(self.left, self.right, self.bottom, self.top, self.zfar, self.znear);
self.projection = *proj.as_matrix();
}else{
let proj = Orthographic3::new(self.left, self.right, self.bottom, self.top, self.znear, self.zfar);
self.projection = *proj.as_matrix();
}
if let Some(plane) = self.oblique_clip_plane.as_ref(){
let q = self.projection.try_inverse().unwrap() * vec4(
plane.x.signum(),
plane.y.signum(),
1.,
1.
);
let c = plane * (2. / plane.dot(&q));
self.projection[(2,0)] = c.x;
self.projection[(2,1)] = c.y;
self.projection[(2,2)] = c.z;
self.projection[(2,3)] = c.w - 1.;
}
self.proj_view = self.projection * self.view;
}
}
impl NodeRef for OrthoCamera {
fn node(&self) -> &Node{
&self.node
}
}
impl CameraOrthographic for OrthoCamera{
fn set_width(&mut self, width: f32){
self.left = -width / 2.;
self.right = width / 2.;
}
}
impl NodeMut for OrthoCamera{
fn node_mut(&mut self) -> &mut Node{
&mut self.node
}
fn update_with_parent_parts(
&mut self,
parent_loc: Option<&Node>,
parent_orientation: Option<&Node>,
parent_scale: Option<&Node>) -> bool
{
if self.target.has_changed(){
let _ = self.node.look_at(&self.target, &self.up);
}
self.target.update();
if self.node.update_with_parent_parts(parent_loc, parent_orientation, parent_scale) {
self.view = self.node.global_transformation().fast_orthonormal_inverse();
self.proj_view = self.projection * self.view;
self.projection_changed = false;
true
}else{
mem::replace(&mut self.projection_changed, false)
}
}
fn update_with_parent(&mut self, parent: Option<&Node>) -> bool{
self.update_with_parent_parts(parent, parent, parent)
}
fn look_at(&mut self, at: &Pnt3, up: &Vec3) -> Result<()>{
let result = self.node_mut().look_at(at, up);
if result.is_ok() {
*self.target = *at;
self.up = Unit::new_normalize(*up);
}
result
}
fn rotate(&mut self, angle: Rad<f32>, axis: &Unit<Vec3>){
let orientation = UnitQuat::from_axis_angle(axis, angle.value());
let new_target = orientation * *self.target;
self.target.set(new_target);
self.node_mut().append_orientation(&orientation);
}
fn append_orientation(&mut self, orientation: &UnitQuat){
let new_target = orientation * *self.target;
self.target.set(new_target);
self.node_mut().append_orientation(orientation);
}
fn tilt(&mut self, angle: Rad<f32>){
let axis = self.local_x_axis();
self.node_mut().rotate(angle, &axis);
}
fn pan(&mut self, angle: Rad<f32>){
let axis = self.local_y_axis();
self.node_mut().rotate(angle, &axis);
}
fn roll(&mut self, angle: Rad<f32>){
let axis = self.local_z_axis();
self.node_mut().rotate(angle, &axis);
}
fn translate(&mut self, t: &Vec3){
self.node_mut().translate(t);
*self.target += *t;
}
fn set_position(&mut self, pos: Pnt3){
let diff = pos - self.position().to_vec();
self.node_mut().set_position(pos);
*self.target += diff.to_vec();
}
fn set_angle_axis(&mut self, angle: Rad<f32>, axis: &Unit<Vec3>){
let orientation = UnitQuat::from_axis_angle(axis, angle.value());
let new_target = orientation * *self.target;
self.target.set(new_target);
self.node_mut().set_orientation(orientation);
}
fn set_orientation(&mut self, orientation: UnitQuat){
let new_target = orientation * *self.target;
self.target.set(new_target);
self.node_mut().set_orientation(orientation);
}
}
impl CameraExt for OrthoCamera{
fn projection(&self) -> Mat4{
self.projection
}
fn view(&self) -> Mat4{
self.view
}
fn projection_view(&self) -> Mat4{
self.proj_view
}
fn fov(&self) -> Option<Deg<f32>>{
None
}
fn width(&self) -> Option<f32>{
Some(self.right - self.left)
}
fn near_far_clip(&self) -> (f32, Option<f32>){
(self.znear, Some(self.zfar))
}
fn near_clip(&self) -> f32{
self.znear
}
fn far_clip(&self) -> Option<f32>{
Some(self.zfar)
}
fn set_near(&mut self, near: f32){
self.znear = near;
self.refresh_projection();
}
fn set_far(&mut self, far: f32){
self.zfar = far;
self.refresh_projection();
}
fn set_near_far(&mut self, near: f32, far: f32){
self.znear = near;
self.zfar = far;
self.refresh_projection();
}
fn set_aspect_ratio(&mut self, aspect: f32){
self.bottom = self.left / aspect;
self.top = self.right / aspect;
self.refresh_projection();
}
fn aspect_ratio(&self) -> f32{
let w = self.right - self.left;
let h = self.top - self.bottom;
w / h
}
fn target(&self) -> &Pnt3{
&*self.target
}
fn up(&self) -> &Unit<Vec3>{
&self.up
}
fn set_target(&mut self, target: Pnt3){
*self.target = target;
}
fn enable_depth_clamp(&mut self){
self.clamp_depth = true;
}
fn disable_depth_clamp(&mut self){
self.clamp_depth = false;
}
fn depth_clamp(&self) -> bool{
self.clamp_depth
}
fn set_reversed_z(&mut self, reversed_z: bool){
self.reversed_z = reversed_z;
self.refresh_projection();
}
fn reversed_z(&self) -> bool{
self.reversed_z
}
fn far_at_infinity(&self) -> bool{
false
}
fn hfov(&self) -> Option<Deg<f32>> {
None
}
fn focal_length(&self) -> Option<f32> {
None
}
fn sensor_width_mm(&self) -> Option<f32> {
None
}
fn update(&mut self) -> bool{
self.update()
}
}
}
pub mod arcball_camera {
use rin_math::{
Deg, Rad, Angle, Pnt3, Mat4, Unit, Vec3, UnitQuat, Pnt2, Vec2, vec2, pnt3, atan2
};
use crate::{Node, NodeRef, NodeMut};
use rin_window::events::*;
use rin_window as window;
use seitan::{self as events, StreamExt};
use std::mem;
use super::{Camera, CameraExt, CameraPerspective, CameraOrthographic};
use rin_util::Result;
#[derive(Clone, Debug, Copy, PartialEq)]
pub enum ViewsEvent{
Front,
Back,
Left,
Right,
Top,
Bottom,
OrbitUp(Deg<f32>),
OrbitDown(Deg<f32>),
OrbitLeft(Deg<f32>),
OrbitRight(Deg<f32>),
}
impl ViewsEvent{
pub fn stream_from_numpad_keys<S: StreamExt<'static, Event>>(events: S) -> events::Stream<'static, ViewsEvent>{
let keys = events.keys().rc();
let front_back = keys.clone().pressed(Key::Kp1)
.scan(false, |b, _| {
*b = !*b;
if *b { Some(ViewsEvent::Front) } else { Some(ViewsEvent::Back) }
});
let left_right = keys.clone().pressed(Key::Kp3)
.scan(false, |b, _| {
*b = !*b;
if *b { Some(ViewsEvent::Left) } else { Some(ViewsEvent::Right) }
});
let top_bottom = keys.clone().pressed(Key::Kp7)
.scan(false, |b, _| {
*b = !*b;
if *b { Some(ViewsEvent::Top) } else { Some(ViewsEvent::Bottom) }
});
let left = keys.clone().pressed(Key::Kp4).map(|_| ViewsEvent::OrbitLeft(Deg(10.)));
let right = keys.clone().pressed(Key::Kp6).map(|_| ViewsEvent::OrbitRight(Deg(10.)));
let up = keys.clone().pressed(Key::Kp8).map(|_| ViewsEvent::OrbitUp(Deg(10.)));
let down = keys.clone().pressed(Key::Kp2).map(|_| ViewsEvent::OrbitDown(Deg(10.)));
events::Stream::merge_all(vec![
front_back,
left_right,
top_bottom,
left,
right,
up,
down,
])
}
}
pub struct ArcballCamera<C = Camera>{
camera: C,
prev_mouse: Pnt2<f64>,
mouse_pressed: bool,
translating: bool,
window_size: Vec2<i32>,
window_size_iter: events::TryIter<'static, Vec2<i32>>,
prev_camera: Node,
rolling: bool,
up: Unit<Vec3>,
do_roll: bool,
events: events::TryIter<'static, window::Event>,
camera_views: events::TryIter<'static, ViewsEvent>,
}
pub struct Builder{
events_stream: events::StreamRc<'static, window::Event>,
camera_views: events::Stream<'static, ViewsEvent>,
window_size: Vec2<i32>,
eye: Pnt3,
look_at: Pnt3,
fov: Deg<f32>,
aspect_ratio: f32,
znear_far: Option<(f32,f32)>,
up: Unit<Vec3>,
do_roll: bool,
}
impl Builder{
pub fn new<S: events::StreamExt<'static, window::Event>>(events_stream: S,
window_size: Vec2<i32>) -> Builder{
Builder{
events_stream: events_stream.rc(),
camera_views: events::Stream::never(),
window_size,
eye: Pnt3::origin(),
look_at: pnt3(0., 0., -1.),
fov: Deg(60f32),
aspect_ratio: window_size.x as f32 / window_size.y as f32,
znear_far: None,
up: Unit::new_unchecked(Vec3::y()),
do_roll: false,
}
}
pub fn from_window<W: window::WindowExt>(window: &mut W) -> Builder{
Builder::new(window.event_stream(), window.size())
}
pub fn from_camera_view_events<S, C, V>(camera: C, event_stream: S, view_events: V, window_size: Vec2<i32>) -> ArcballCamera<C>
where S: events::StreamExt<'static, window::Event>,
V: events::StreamExt<'static, ViewsEvent>,
C: CameraExt,
{
let event_stream = event_stream.rc();
let view_events = view_events.unique();
ArcballCamera{
prev_mouse: Pnt2::origin(),
mouse_pressed: false,
translating: false,
prev_camera: Node::identity(),
window_size: window_size,
window_size_iter: event_stream.clone().window().resized().try_iter(),
rolling: false,
up: *camera.up(),
do_roll: false,
events: event_stream.try_iter(),
camera_views: view_events.try_iter(),
camera,
}
}
pub fn from_camera<S, C>(camera: C, event_stream: S, window_size: Vec2<i32>) -> ArcballCamera<C>
where S: events::StreamExt<'static, window::Event>,
C: CameraExt,
{
Self::from_camera_view_events(camera, event_stream, events::Stream::never(), window_size)
}
pub fn clip_planes(mut self, znear: f32, zfar: f32) -> Builder{
self.znear_far = Some((znear, zfar));
self
}
pub fn up_axis(mut self, up: Unit<Vec3>) -> Builder{
self.up = up;
self
}
pub fn position(mut self, pos: Pnt3) -> Builder{
self.eye = pos;
self
}
pub fn look_at(mut self, target: Pnt3) -> Builder{
self.look_at = target;
self
}
pub fn fov(mut self, fov: Deg<f32>) -> Builder{
self.fov = fov;
self
}
pub fn aspect_ratio(mut self, aspect_ratio: f32) -> Builder{
self.aspect_ratio = aspect_ratio;
self
}
pub fn do_roll(mut self, do_roll: bool) -> Builder{
self.do_roll = do_roll;
self
}
pub fn view_events<S: StreamExt<'static, ViewsEvent>>(mut self, view_events: S) -> Builder{
self.camera_views = view_events.unique();
self
}
pub fn build(self) -> Result<ArcballCamera>{
let camera = if let Some((near, far)) = self.znear_far{
Camera::new_with_frustum(self.eye, self.look_at, self.up, self.fov, self.aspect_ratio, near, far)
}else{
Camera::new(self.eye, self.look_at, self.up, self.fov, self.aspect_ratio)
};
Ok(Self::from_camera_view_events(
camera?,
self.events_stream,
self.camera_views,
self.window_size
))
}
}
impl<C: CameraExt + NodeMut> ArcballCamera<C>{
pub fn target(&self) -> &Pnt3{
self.camera.target()
}
pub fn set_target(&mut self, target: Pnt3){
self.camera.set_target(target);
}
pub fn camera(&self) -> &C{
&self.camera
}
pub fn update(&mut self) -> bool {
self.poll_window_events();
self.camera.update()
}
fn poll_window_events<'a>(&'a mut self){
if let Some(window_size) = self.window_size_iter.by_ref().last(){
self.window_size = window_size;
}
if let Some(view) = self.camera_views.by_ref().last(){
if !self.mouse_pressed {
let target = *self.camera.target();
let position = self.camera.position();
let (dir, up) = match view{
ViewsEvent::Front => (-Vec3::y(), Vec3::z_axis()),
ViewsEvent::Back => ( Vec3::y(), Vec3::z_axis()),
ViewsEvent::Left => (-Vec3::x(), Vec3::z_axis()),
ViewsEvent::Right => ( Vec3::x(), Vec3::z_axis()),
ViewsEvent::Bottom => (-Vec3::z(), Vec3::y_axis()),
ViewsEvent::Top => ( Vec3::z(), Vec3::y_axis()),
ViewsEvent::OrbitUp(deg) => {
let curr_dir = (target - position).normalize();
let rot = UnitQuat::from_axis_angle(&self.camera.local_x_axis(), -deg.to_rad().value());
let dir = rot * curr_dir;
let up = self.camera.local_y_axis();
(dir, up)
}
ViewsEvent::OrbitDown(deg) => {
let curr_dir = (target - position).normalize();
let rot = UnitQuat::from_axis_angle(&self.camera.local_x_axis(), deg.to_rad().value());
let dir = rot * curr_dir;
let up = self.camera.local_y_axis();
(dir, up)
}
ViewsEvent::OrbitLeft(deg) => {
let curr_dir = (target - position).normalize();
let rot = UnitQuat::from_axis_angle(&self.camera.local_y_axis(), -deg.to_rad().value());
let dir = rot * curr_dir;
let up = self.camera.local_y_axis();
(dir, up)
}
ViewsEvent::OrbitRight(deg) => {
let curr_dir = (target - position).normalize();
let rot = UnitQuat::from_axis_angle(&self.camera.local_y_axis(), deg.to_rad().value());
let dir = rot * curr_dir;
let up = self.camera.local_y_axis();
(dir, up)
}
};
let dist = (target - position).norm();
let offset = dist * dir;
self.camera.set_position(target - offset);
let _ = self.camera.look_at(&target, &up);
}
}
let events: &mut events::TryIter<'a, window::Event> = unsafe{ mem::transmute(self.events.by_ref()) };
for event in events {
match event{
window::Event::MousePressed{pos,button,..} => self.mouse_pressed(&pos,button),
window::Event::MouseReleased{pos,button,..} => self.mouse_released(&pos,button),
window::Event::MouseMoved{pos} => self.mouse_moved(&pos),
window::Event::Scroll{scroll} => self.scroll(&scroll),
_ => {}
}
}
}
fn mouse_moved(&mut self, pos: &Pnt2<f64>){
if self.mouse_pressed{
let diff = *pos - self.prev_mouse;
let yaw = Rad(-diff.x as f32 * 0.005);
let pitch = Rad(-diff.y as f32 * 0.005);
let rot = if self.rolling{
let screen_coords = vec2((pos.x as f32 - self.window_size.x as f32*0.5)/self.window_size.y as f32 * 2.0,
pos.y as f32/self.window_size.y as f32 * 2.0 - 1.0);
let prev_screen_coords = vec2((self.prev_mouse.x as f32 - self.window_size.x as f32*0.5)/self.window_size.y as f32 * 2.0,
self.prev_mouse.y as f32/self.window_size.y as f32 * 2.0 - 1.0);
UnitQuat::from_axis_angle(&self.prev_camera.local_z_axis(), atan2(&prev_screen_coords, &screen_coords).value())
}else{
UnitQuat::from_axis_angle(&self.up, yaw.value()) * UnitQuat::from_axis_angle(&self.prev_camera.local_x_axis(), pitch.value())
};
let orbit_radius = self.prev_camera.position() - *self.camera.target();
let rotated = rot * orbit_radius;
let new_position = *self.camera.target() + rotated;
self.camera.node_mut().set_position(new_position);
self.camera.node_mut().set_orientation(rot * self.prev_camera.orientation());
if !self.rolling && pitch.abs().wrap() > Deg(90f32).to_rad(){
self.prev_mouse = *pos;
self.prev_camera = self.camera.node().clone();
}
}
if self.translating{
let new_pos = *pos - self.prev_mouse;
let axis_x = self.camera.local_x_axis().into_inner();
let axis_y = self.camera.local_y_axis().into_inner();
let ratio_x;
let ratio_y;
if self.camera.fov().is_some(){
let max_distance = (*self.camera.target() - self.camera.position()).norm();
ratio_x = max_distance/self.window_size.x as f32;
ratio_y = max_distance/self.window_size.y as f32;
}else{
let width = self.camera.width().unwrap();
let height = width / self.camera.aspect_ratio();
ratio_x = width / self.camera().scale().x / self.window_size.x as f32;
ratio_y = height / self.camera().scale().y / self.window_size.y as f32;
}
let translation = axis_x * -new_pos.x as f32 * ratio_x + axis_y * new_pos.y as f32 * ratio_y;
self.camera.translate(&translation);
self.prev_mouse = *pos;
}
}
fn mouse_pressed(&mut self, pos: &Pnt2<f64>, button: window::MouseButton){
match button{
window::MouseButton::Left => {
self.prev_mouse = *pos;
self.mouse_pressed = true;
self.prev_camera = self.camera.node().clone();
let screen_coords = vec2((pos.x as f32 - self.window_size.x as f32*0.5)/self.window_size.y as f32 * 2.0,
pos.y as f32/self.window_size.y as f32 * 2.0 - 1.0);
if self.do_roll && screen_coords.norm_squared() > 1.0{
self.rolling = true;
}else{
self.rolling = false;
}
}
window::MouseButton::Middle => {
self.prev_mouse = *pos;
self.translating = true;
}
_=>{}
}
}
fn mouse_released(&mut self, _pos: &Pnt2<f64>, button: window::MouseButton){
match button{
window::MouseButton::Left => {
self.mouse_pressed = false;
}
window::MouseButton::Middle => {
self.translating = false;
}
_=>{}
}
}
fn scroll(&mut self, scroll: &Vec2<f64>){
if self.camera.fov().is_some(){
let dist = (*self.camera.target() - self.camera.position()).norm();
let dir = dist * self.camera.local_z_axis().into_inner();
self.camera.node_mut().translate(&(dir * (scroll.y as f32 * 0.1)));
}else{
let scale = self.camera.scale();
let scale = scale + (scale * scroll.y as f32 * 0.1);
self.camera.set_scale(scale);
}
}
}
impl<C: CameraExt + NodeMut> CameraExt for ArcballCamera<C>{
fn projection(&self) -> Mat4{
self.camera.projection()
}
fn view(&self) -> Mat4{
self.camera.view()
}
fn projection_view(&self) -> Mat4{
self.camera.projection_view()
}
fn fov(&self) -> Option<Deg<f32>>{
self.camera.fov()
}
fn width(&self) -> Option<f32>{
self.camera.width()
}
fn near_far_clip(&self) -> (f32, Option<f32>){
self.camera.near_far_clip()
}
fn near_clip(&self) -> f32{
self.camera.near_clip()
}
fn far_clip(&self) -> Option<f32>{
self.camera.far_clip()
}
fn set_near(&mut self, near: f32){
self.camera.set_near(near);
}
fn set_far(&mut self, far: f32){
self.camera.set_far(far);
}
fn set_near_far(&mut self, near: f32, far: f32){
self.camera.set_near_far(near,far);
}
fn set_aspect_ratio(&mut self, aspect: f32){
self.camera.set_aspect_ratio(aspect);
}
fn aspect_ratio(&self) -> f32{
self.camera.aspect_ratio()
}
fn target(&self) -> &Pnt3{
self.camera.target()
}
fn set_target(&mut self, target: Pnt3){
self.camera.set_target(target)
}
fn up(&self) -> &Unit<Vec3>{
&self.up
}
fn enable_depth_clamp(&mut self){
self.camera.enable_depth_clamp();
}
fn disable_depth_clamp(&mut self){
self.camera.disable_depth_clamp();
}
fn depth_clamp(&self) -> bool{
self.camera.depth_clamp()
}
fn set_reversed_z(&mut self, reversed_z: bool){
self.camera.set_reversed_z(reversed_z);
}
fn reversed_z(&self) -> bool{
self.camera.reversed_z()
}
fn far_at_infinity(&self) -> bool{
self.camera.far_at_infinity()
}
fn hfov(&self) -> Option<Deg<f32>> {
self.camera.hfov()
}
fn focal_length(&self) -> Option<f32> {
self.camera.focal_length()
}
fn sensor_width_mm(&self) -> Option<f32> {
self.camera.sensor_width_mm()
}
fn update(&mut self) -> bool{
self.update()
}
}
impl<C: CameraPerspective + NodeMut> CameraPerspective for ArcballCamera<C>{
fn set_fov(&mut self, fov: Deg<f32>){
self.camera.set_fov(fov);
}
fn set_near_with_far_at_infinity(&mut self, near: f32){
self.camera.set_near_with_far_at_infinity(near)
}
}
impl<C: CameraOrthographic + NodeMut> CameraOrthographic for ArcballCamera<C>{
fn set_width(&mut self, width: f32){
self.camera.set_width(width)
}
}
impl<C: NodeRef> NodeRef for ArcballCamera<C>{
fn node(&self) -> &Node{
self.camera.node()
}
}
impl<C: NodeMut> NodeMut for ArcballCamera<C>{
fn node_mut(&mut self) -> &mut Node{
self.camera.node_mut()
}
fn update_with_parent_parts(
&mut self,
parent_loc: Option<&Node>,
parent_orientation: Option<&Node>,
parent_scale: Option<&Node>) -> bool
{
self.camera.update_with_parent_parts(parent_loc, parent_orientation, parent_scale)
}
fn update_with_parent(&mut self, parent: Option<&Node>) -> bool{
self.camera.update_with_parent_parts(parent, parent, parent)
}
fn look_at(&mut self, at: &Pnt3, up: &Vec3) -> Result<()>{
self.camera.look_at(at, up)
}
fn rotate(&mut self, angle: Rad<f32>, axis: &Unit<Vec3>){
self.camera.rotate(angle, axis)
}
fn append_orientation(&mut self, orientation: &UnitQuat){
self.camera.append_orientation(orientation)
}
fn tilt(&mut self, angle: Rad<f32>){
self.camera.tilt(angle)
}
fn pan(&mut self, angle: Rad<f32>){
self.camera.pan(angle)
}
fn roll(&mut self, angle: Rad<f32>){
self.camera.roll(angle)
}
fn set_scale(&mut self, _: Vec3){
}
fn translate(&mut self, t: &Vec3){
self.camera.translate(t)
}
fn set_position(&mut self, pos: Pnt3){
self.camera.set_position(pos)
}
fn set_angle_axis(&mut self, angle: Rad<f32>, axis: &Unit<Vec3>){
self.camera.set_angle_axis(angle, axis)
}
fn set_orientation(&mut self, orientation: UnitQuat){
self.camera.set_orientation(orientation)
}
}
}