Some improvments on UI

This commit is contained in:
Thomas Forgione 2018-04-11 14:13:49 +02:00
parent 73b73f7bf3
commit 6cb76e9986
No known key found for this signature in database
GPG Key ID: C75CD416BD1FFCE1
3 changed files with 85 additions and 21 deletions

View File

@ -21,8 +21,8 @@ use model_converter::renderer::camera::Camera;
fn main() { fn main() {
let mut model = parse("./assets/models/cube/cube.mtl").unwrap(); let mut model = parse("./assets/models/link/link.mtl").unwrap();
parse_into_model("./assets/models/cube/cube.obj", &mut model).unwrap(); parse_into_model("./assets/models/link/link.obj", &mut model).unwrap();
let mut events_loop = EventsLoop::new(); let mut events_loop = EventsLoop::new();
let window = WindowBuilder::new(); let window = WindowBuilder::new();
@ -40,7 +40,7 @@ fn main() {
Vector3::new( 0.0, 1.0, 0.0), Vector3::new( 0.0, 1.0, 0.0),
); );
let mut controls = OrbitControls::new(&mut camera); let mut controls = OrbitControls::around(&model, &mut camera);
while !closed { while !closed {

View File

@ -10,8 +10,9 @@ use glium::glutin::{
MouseScrollDelta, MouseScrollDelta,
}; };
use math::vector::Vector2; use math::vector::{Vector2, Vector3};
use renderer::camera::Camera; use renderer::camera::Camera;
use model::Model;
/// The trait that all controls should implement. /// The trait that all controls should implement.
pub trait Controls { pub trait Controls {
@ -41,26 +42,48 @@ pub struct OrbitControls {
/// The sensitiviy of the rotation of the mouse. /// The sensitiviy of the rotation of the mouse.
sensitivity: f32, sensitivity: f32,
/// The center of the object.
center: Vector3<f32>,
} }
impl OrbitControls { impl OrbitControls {
/// Creates a new orbit controls, and initializes the camera. /// Creates a new orbit controls, and initializes the camera.
pub fn new(camera: &mut Camera) -> OrbitControls { pub fn new(center: Vector3<f32>, distance: f32, camera: &mut Camera) -> OrbitControls {
let controls = OrbitControls { let controls = OrbitControls {
mouse_position: Vector2::new(0.0, 0.0), mouse_position: Vector2::new(0.0, 0.0),
pressed: false, pressed: false,
theta: 0.0, theta: 0.0,
phi: 0.0, phi: 0.0,
distance: 5.0, distance: distance,
sensitivity: 200.0, sensitivity: 200.0,
center: center,
}; };
*camera.position.x_mut() = controls.distance * controls.theta.cos(); *camera.position.x_mut() = controls.distance * controls.theta.cos();
*camera.position.y_mut() = 0.0; *camera.position.y_mut() = 0.0;
*camera.position.z_mut() = controls.distance * controls.phi.sin(); *camera.position.z_mut() = controls.distance * controls.phi.sin();
camera.position += controls.center;
camera.target = controls.center;
controls controls
} }
/// Creates orbit controls that are mode to rotate around a model.
pub fn around(model: &Model, camera: &mut Camera) -> OrbitControls {
// Compute bounding box
let bounding_box = model.bounding_box();
let center = (bounding_box.min() + bounding_box.max()) / 2.0;
let distance = (bounding_box.max() - bounding_box.min()).norm();
OrbitControls::new(
Vector3::new(center.x() as f32, center.y() as f32, center.z() as f32),
distance as f32,
camera
)
}
} }
impl Controls for OrbitControls { impl Controls for OrbitControls {
@ -86,6 +109,9 @@ impl Controls for OrbitControls {
*camera.position.x_mut() = self.distance * self.phi.cos() * self.theta.cos(); *camera.position.x_mut() = self.distance * self.phi.cos() * self.theta.cos();
*camera.position.y_mut() = self.distance * self.phi.sin(); *camera.position.y_mut() = self.distance * self.phi.sin();
*camera.position.z_mut() = self.distance * self.phi.cos() * self.theta.sin(); *camera.position.z_mut() = self.distance * self.phi.cos() * self.theta.sin();
camera.position += self.center;
camera.target = self.center;
}, },
Event::WindowEvent{ Event::WindowEvent{
@ -109,6 +135,9 @@ impl Controls for OrbitControls {
*camera.position.y_mut() = self.distance * self.phi.sin(); *camera.position.y_mut() = self.distance * self.phi.sin();
*camera.position.z_mut() = self.distance * self.phi.cos() * self.theta.sin(); *camera.position.z_mut() = self.distance * self.phi.cos() * self.theta.sin();
camera.position += self.center;
camera.target = self.center;
} }
// Record new position // Record new position

View File

@ -20,11 +20,33 @@ use glium::{
DrawParameters, DrawParameters,
Depth, Depth,
}; };
use glium::backend::Facade;
use glium::backend::glutin::headless::Headless;
use image; use image;
use model::{Model, Vertex}; use model::{Model, Vertex};
use renderer::camera::RenderCamera; use renderer::camera::RenderCamera;
/// Anything on which you can call draw to get a frame.
pub trait Drawer {
/// Get a frame from the drawer.
fn draw(&self) -> Frame;
}
impl Drawer for Display {
fn draw(&self) -> Frame {
Display::draw(self)
}
}
impl Drawer for Headless {
fn draw(&self) -> Frame {
Headless::draw(self)
}
}
/// A material that can be bound to OpenGL. /// A material that can be bound to OpenGL.
/// ///
/// Only textures are supported for now. /// Only textures are supported for now.
@ -42,7 +64,7 @@ impl RenderMaterial {
} }
/// Creates a material from a path to an image file. /// Creates a material from a path to an image file.
pub fn from_texture_path(path: &str, display: &Display) -> RenderMaterial { pub fn from_texture_path<D: Drawer + Facade + Sized>(path: &str, drawer: &D) -> RenderMaterial {
let image = image::open(path); let image = image::open(path);
if let Ok(image) = image { if let Ok(image) = image {
@ -50,7 +72,7 @@ impl RenderMaterial {
let dim = image.dimensions(); let dim = image.dimensions();
let image = RawImage2d::from_raw_rgba_reversed(&image.into_raw(), dim); let image = RawImage2d::from_raw_rgba_reversed(&image.into_raw(), dim);
RenderMaterial { RenderMaterial {
texture: SrgbTexture2d::new(display, image).ok() texture: SrgbTexture2d::new(drawer, image).ok()
} }
} else { } else {
RenderMaterial { RenderMaterial {
@ -61,30 +83,37 @@ impl RenderMaterial {
} }
/// A renderer. It contains a display, shaders, and a vector of models it can render. /// A renderer. It contains a display, shaders, and a vector of models it can render.
pub struct Renderer<'a> { pub struct Renderer<'a, D: Drawer + Facade> {
display: Display, drawer: D,
program: Program, program: Program,
models: Vec<(&'a Model, Vec<(RenderMaterial, VertexBuffer<Vertex>)>)>, models: Vec<(&'a Model, Vec<(RenderMaterial, VertexBuffer<Vertex>)>)>,
} }
impl<'a> Renderer<'a> { impl<'a, D: Drawer + Facade + Sized> Renderer<'a, D> {
/// Creates a new renderer from a display. /// Creates a new renderer from a display.
/// ///
/// Is uses the default shaders and creates an empty vec of models. /// Is uses the default shaders and creates an empty vec of models.
pub fn new(display: Display) -> Renderer<'a> { pub fn new(drawer: D) -> Renderer<'a, D> {
let program = Program::from_source( let program = Program::from_source(
&display, &drawer,
include_str!("../../assets/shaders/shader.vert"), include_str!("../../assets/shaders/shader.vert"),
include_str!("../../assets/shaders/shader.frag"), include_str!("../../assets/shaders/shader.frag"),
None None
).unwrap(); );
Renderer { if let Ok(program) = program {
display: display, Renderer {
program: program, drawer: drawer,
models: vec![], program: program,
models: vec![],
}
} else {
println!("{:?}", program.err().unwrap());
panic!()
} }
} }
/// Adds a model to the renderer, and compute the corresponding buffers for rendering. /// Adds a model to the renderer, and compute the corresponding buffers for rendering.
@ -96,7 +125,7 @@ impl<'a> Renderer<'a> {
let material = if let Some(ref material_name) = part.material_name { let material = if let Some(ref material_name) = part.material_name {
if let Some(material) = model.materials.get(material_name) { if let Some(material) = model.materials.get(material_name) {
if let Some(path) = material.textures.get("map_Kd") { if let Some(path) = material.textures.get("map_Kd") {
RenderMaterial::from_texture_path(path, &self.display) RenderMaterial::from_texture_path(path, &self.drawer)
} else { } else {
RenderMaterial::new() RenderMaterial::new()
} }
@ -108,15 +137,20 @@ impl<'a> Renderer<'a> {
}; };
let shape = part.build_shape(&model.vertices, &model.texture_coordinates, &model.normals); let shape = part.build_shape(&model.vertices, &model.texture_coordinates, &model.normals);
buffers.push((material, VertexBuffer::new(&self.display, &shape).unwrap())); buffers.push((material, VertexBuffer::new(&self.drawer, &shape).unwrap()));
} }
self.models.push((model, buffers)); self.models.push((model, buffers));
} }
/// Returns the reference to the drawer used for this renderer.
pub fn facade(&self) -> &D {
&self.drawer
}
/// Creates a frame from the display. /// Creates a frame from the display.
pub fn draw(&self) -> Frame { pub fn draw(&self) -> Frame {
self.display.draw() self.drawer.draw()
} }
/// Renders the result of the models from the camera and paint it on the target. /// Renders the result of the models from the camera and paint it on the target.
@ -166,5 +200,6 @@ impl<'a> Renderer<'a> {
}; };
} }
} }
} }
} }