This commit is contained in:
Thomas Forgione 2018-04-10 15:25:01 +02:00
parent c8c9e12ea9
commit 73b73f7bf3
No known key found for this signature in database
GPG Key ID: C75CD416BD1FFCE1
5 changed files with 39 additions and 34 deletions

View File

@ -1,3 +1,5 @@
//! This crate contains classes and binaries to visualize and convert 3D models.
#![warn(missing_docs)]
extern crate num;

View File

@ -9,6 +9,7 @@ use math::vector::{Vector2, Vector3};
use math::bounding_box::BoundingBox3;
#[derive(Copy, Clone, Debug, PartialEq)]
/// A raw vertex, with its 3D coordinates, texture coordinates and normals.
pub struct Vertex {
vertex: [f64; 3],
tex_coords: [f64; 2],
@ -164,6 +165,7 @@ impl Part {
self.faces.push(f);
}
/// Creates a shape that can be rendered.
pub fn build_shape(&self, vertices: &Vec<Vector3<f64>>, tex_coords: &Vec<Vector2<f64>>, normals: &Vec<Vector3<f64>>) -> Vec<Vertex> {
let mut shape = vec![];

View File

@ -1,7 +1,16 @@
//! This module contains everything to deal with cameras.
use math::vector::Vector3;
/// The trait that a render camera should implement.
///
/// It allows the renderer to use it.
pub trait RenderCamera {
/// Returns the view matrix of the camera.
fn get_view_matrix(&self) -> [[f32; 4]; 4];
/// Returns the perspective matrix of the camera.
fn get_perspective_matrix(&self, dimensions: (u32, u32)) -> [[f32; 4]; 4] {
let (width, height) = dimensions;
let aspect_ratio = height as f32 / width as f32;
@ -22,6 +31,7 @@ pub trait RenderCamera {
}
}
/// Creates a look at matrix from the center, the target pointed by the camera and the up vector.
pub fn look_at_matrix(position: [f32; 3], target: [f32; 3], up: [f32; 3]) -> [[f32; 4]; 4] {
let f = {
let f = [
@ -61,13 +71,20 @@ pub fn look_at_matrix(position: [f32; 3], target: [f32; 3], up: [f32; 3]) -> [[f
}
/// A simple camera with its position, target and up vector.
pub struct Camera {
/// The position of the center of the camera.
pub position: Vector3<f32>,
/// The 3D point the camera is targetting.
pub target: Vector3<f32>,
/// The up vector of the camera.
pub up: Vector3<f32>,
}
impl Camera {
/// Creates a new camera from its attributes.
pub fn new(position: Vector3<f32>, target: Vector3<f32>, up: Vector3<f32>) -> Camera {
Camera {
position: position,
@ -83,35 +100,3 @@ impl RenderCamera for Camera {
}
}
pub struct RotatingCamera {
distance: f32,
theta: f32,
}
impl RotatingCamera {
pub fn new(distance: f32) -> RotatingCamera {
RotatingCamera {
distance: distance,
theta: 0.0,
}
}
pub fn increase_theta(&mut self, dt: f32) {
self.theta += dt;
}
}
impl RenderCamera for RotatingCamera {
fn get_view_matrix(&self) -> [[f32; 4]; 4] {
let position = Vector3::new(
self.distance * self.theta.cos(),
0.0,
self.distance * self.theta.sin(),
);
let target = Vector3::new(0.0, 0.0, 0.0);
let up = Vector3::new(0.0, 1.0, 0.0);
look_at_matrix(position.into(), target.into(), up.into())
}
}

View File

@ -1,3 +1,5 @@
//! This models contains structs that help move the camera in a user-friendly way.
const EPSILON: f32 = 0.001;
use glium::glutin::{

View File

@ -1,3 +1,5 @@
//! This module contains everything related to rendering.
pub mod camera;
pub mod controls;
@ -23,19 +25,24 @@ use image;
use model::{Model, Vertex};
use renderer::camera::RenderCamera;
/// A material that can be bound to OpenGL.
///
/// Only textures are supported for now.
pub struct RenderMaterial {
texture: Option<SrgbTexture2d>,
}
impl RenderMaterial {
/// Creates a new material with no texture.
pub fn new() -> RenderMaterial {
RenderMaterial {
texture: None
}
}
pub fn from_texture_name(path: &str, display: &Display) -> RenderMaterial {
/// Creates a material from a path to an image file.
pub fn from_texture_path(path: &str, display: &Display) -> RenderMaterial {
let image = image::open(path);
if let Ok(image) = image {
@ -53,6 +60,7 @@ impl RenderMaterial {
}
}
/// A renderer. It contains a display, shaders, and a vector of models it can render.
pub struct Renderer<'a> {
display: Display,
program: Program,
@ -60,6 +68,9 @@ pub struct Renderer<'a> {
}
impl<'a> Renderer<'a> {
/// Creates a new renderer from a display.
///
/// Is uses the default shaders and creates an empty vec of models.
pub fn new(display: Display) -> Renderer<'a> {
let program = Program::from_source(
@ -76,6 +87,7 @@ impl<'a> Renderer<'a> {
}
}
/// Adds a model to the renderer, and compute the corresponding buffers for rendering.
pub fn add_model(&mut self, model: &'a Model) {
let mut buffers = vec![];
@ -84,7 +96,7 @@ impl<'a> Renderer<'a> {
let material = if let Some(ref material_name) = part.material_name {
if let Some(material) = model.materials.get(material_name) {
if let Some(path) = material.textures.get("map_Kd") {
RenderMaterial::from_texture_name(path, &self.display)
RenderMaterial::from_texture_path(path, &self.display)
} else {
RenderMaterial::new()
}
@ -102,10 +114,12 @@ impl<'a> Renderer<'a> {
self.models.push((model, buffers));
}
/// Creates a frame from the display.
pub fn draw(&self) -> Frame {
self.display.draw()
}
/// Renders the result of the models from the camera and paint it on the target.
pub fn render<C: RenderCamera>(&self, camera: &C, target: &mut Frame) {
use glium::Surface;
target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);