use std::borrow::Borrow;
use crate::*;
use super::*;
use crate::ui::*;
use crate::rs_math3d::*;
use crate::renderer::*;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum NavigationMode {
Pan,
Orbit,
}
pub struct View3D {
camera : Camera,
fov : f32,
nav_mode : NavigationMode,
dimension : Dimensioni,
scroll : f32,
bounds : Box3f,
pvm : Mat4f,
pointer_state : pointer::State,
}
impl View3D {
pub fn new(camera: Camera, dimension: Dimensioni, bounds: Box3f) -> Self {
let scroll = camera.distance();
Self {
fov : camera.fov(),
camera : camera,
nav_mode : NavigationMode::Orbit,
dimension : dimension,
scroll,
bounds : bounds,
pvm : camera.projection_matrix() * camera.view_matrix(),
pointer_state : pointer::State::new(),
}
}
fn update(&mut self) -> UpdateResult {
let far_plane = self.bounds.extent().length() * 100.0;
self.camera = self.camera.with_far_plane(far_plane);
let handled =
match (&self.nav_mode, self.pointer_state.event()) {
(NavigationMode::Orbit, pointer::Event::Drag(prev, _, curr, _)) => {
let p = Vec2f::new(prev.x, prev.y);
let c = Vec2f::new(curr.x, curr.y);
self.camera = self.camera.tracball_rotate(self.dimension, &p, &c);
UpdateResult::Handled
},
(NavigationMode::Pan, pointer::Event::Drag(prev, _, curr, _)) => {
let p = Vec2f::new(prev.x, prev.y);
let c = Vec2f::new(curr.x, curr.y);
self.camera = self.camera.pan(self.dimension, &p, &c);
UpdateResult::Handled
},
(_, pointer::Event::Scroll(v)) => {
self.scroll += v;
self.scroll = f32::max(0.5, self.scroll);
let distance = self.scroll;
let aspect = (self.dimension.width as f32) / (self.dimension.height as f32);
self.camera = Camera::new(self.camera.target(), distance, self.camera.rotation(), self.camera.fov(), aspect, self.camera.near_plane(), self.camera.far_plane());
UpdateResult::Handled
}
_ => UpdateResult::Unhandled
};
self.pvm = self.camera.projection_matrix() * self.camera.view_matrix();
handled
}
pub fn set_pointer(&mut self, pos: Vec2f, st: pointer::ButtonState) -> UpdateResult {
self.pointer_state.update(pos, st);
self.update()
}
pub fn set_dimension(&mut self, dimension: Dimensioni) {
self.dimension = dimension;
let aspect = (self.dimension.width as f32) / (self.dimension.height as f32);
self.camera = self.camera.with_aspect(aspect);
self.update();
}
pub fn get_navigation_mode(&self) -> NavigationMode { self.nav_mode }
pub fn set_navigation_mode(&mut self, nav_mode: NavigationMode) {
if nav_mode != self.nav_mode {
self.nav_mode = nav_mode;
self.pointer_state = pointer::State::new();
self.update(); }
}
pub fn pointer_event(&self) -> pointer::Event { self.pointer_state.event() }
pub fn pvm(&self) -> Mat4f { self.pvm }
pub fn projection_matrix(&self) -> Mat4f {
self.camera.projection_matrix()
}
pub fn view_matrix(&self) -> Mat4f {
self.camera.view_matrix()
}
}