A big commit

This commit is contained in:
Thomas Forgione 2018-04-11 17:03:32 +02:00
parent 6cb76e9986
commit 211f7fc5c5
No known key found for this signature in database
GPG Key ID: C75CD416BD1FFCE1
7 changed files with 129 additions and 30 deletions

View File

@ -171,10 +171,23 @@ impl Part {
let mut shape = vec![];
for face in &self.faces {
for &&v in &[&face.a, &face.b, &face.c] {
let vertex = vertices[v.vertex].into();
let tex_coord = if let Some(tex_index) = v.texture_coordinate {
tex_coords[tex_index].into()
} else {
[0.0, 0.0]
};
let normal = if let Some(normal_index) = v.normal {
normals[normal_index].into()
} else {
[0.0, 0.0, 0.0]
};
shape.push(Vertex {
vertex: vertices[v.vertex].into(),
tex_coords: tex_coords[v.texture_coordinate.unwrap()].into(),
normal: normals[v.normal.unwrap()].into(),
vertex: vertex,
tex_coords: tex_coord,
normal: normal,
});
}
}

View File

@ -4,7 +4,7 @@ pub mod obj;
pub mod mtl;
use std::fmt;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::{BufReader, Error};
use math::vector::{Vector2, Vector3};
@ -19,6 +19,9 @@ pub enum Element {
/// An empty element (correspond to an empty line for example).
None,
/// Declares the use of a material file.
MaterialLib(String),
/// Changes the material used for the next faces.
UseMaterial(String),
@ -48,6 +51,9 @@ pub enum Element {
/// An unknown material instruction that will be copied into the mtl file.
UnknownMaterialInstruction(String),
/// Declares multiple faces.
Faces(Vec<Face>),
}
#[derive(Debug)]
@ -225,6 +231,16 @@ impl<LP: LineParser> Parser for LP {
Element::TextureCoordinate(v) => model.texture_coordinates.push(v),
Element::Normal(v) => model.normals.push(v),
Element::MaterialLib(ref material_path) => {
// Append material_path to path
let mut path = PathBuf::from(path);
path.pop();
path.push(material_path);
if let Err(err) = parse_into_model(path.to_str().unwrap(), model) {
return Err(err);
}
},
Element::Face(f) => {
if let Err(ModelError::IndexError(index, size)) = model.add_face(f) {
return Err(ParserError::IndexOutOfBound(path.to_owned(), num, index, size));
@ -274,7 +290,16 @@ impl<LP: LineParser> Parser for LP {
}
current_material.unwrap().add_unknown_instruction(s);
},
Element::Faces(faces) => {
for f in faces {
if let Err(ModelError::IndexError(index, size)) = model.add_face(f) {
return Err(ParserError::IndexOutOfBound(path.to_owned(), num, index, size));
}
}
}
}
}

View File

@ -153,7 +153,6 @@ impl ObjParser {
if let Some(texture_coordinate_string) = texture_coordinate_string {
if texture_coordinate_string.len() != 0 {
let texture_coordinate_index = texture_coordinate_string.parse::<usize>();
if texture_coordinate_index.is_err() {
return Err(ParserError::ParseNumberError(
path.to_owned(),line_number, texture_coordinate_string.to_owned()
@ -185,10 +184,15 @@ impl ObjParser {
}
if face_vertices.len() != 3 {
Err(ParserError::TooManyVertices(path.to_owned(), line_number, face_vertices.len()))
} else {
if face_vertices.len() == 3 {
Ok(Element::Face(Face::new(face_vertices[0], face_vertices[1], face_vertices[2])))
} else if face_vertices.len() == 4 {
Ok(Element::Faces(vec![
Face::new(face_vertices[0], face_vertices[1], face_vertices[2]),
Face::new(face_vertices[0], face_vertices[2], face_vertices[3]),
]))
} else {
Err(ParserError::TooManyVertices(path.to_owned(), line_number, face_vertices.len()))
}
@ -203,12 +207,14 @@ impl LineParser for ObjParser {
if let Some(first) = split.nth(0) {
match first {
"mtllib" => Ok(Element::MaterialLib(split.nth(0).unwrap().to_owned())),
"v" => self.parse_vertex(line_number, line, path),
"vt" => self.parse_texture_coordinate(line_number, line, path),
"vn" => self.parse_normal(line_number, line, path),
"usemtl" => Ok(Element::UseMaterial(split.nth(0).unwrap().to_owned())),
"f" => self.parse_face(line_number, line, path),
"#" | "g" | "s" | "o" | "mtllib" => Ok(Element::None),
"#" | "g" | "s" | "o" => Ok(Element::None),
key if key.len() != 0 => Err(ParserError::UnexpectedKeyword(path.to_owned(), line_number, key.to_owned())),
_ => Ok(Element::None),
}

View File

@ -1,6 +1,9 @@
extern crate glium;
extern crate model_converter;
use std::env;
use std::process::exit;
use glium::Display;
use glium::glutin;
use glium::glutin::{
@ -14,15 +17,45 @@ use glium::glutin::VirtualKeyCode;
use model_converter::math::vector::Vector3;
use model_converter::parser::{parse, parse_into_model};
use model_converter::parser::parse_into_model;
use model_converter::renderer::Renderer;
use model_converter::renderer::controls::OrbitControls;
use model_converter::renderer::camera::Camera;
use model_converter::model::Model;
fn main() {
let mut model = parse("./assets/models/link/link.mtl").unwrap();
parse_into_model("./assets/models/link/link.obj", &mut model).unwrap();
let mut model = Model::new();
let mut inputs = vec![];
let mut iterator = env::args();
// Skip the name of the program
iterator.next();
while let Some(argument) = iterator.next() {
match argument.as_ref() {
"-i" | "--input" => {
if let Some(path) = iterator.next() {
inputs.push(path);
} else {
eprintln!("Expecting path after {}", argument);
exit(-1);
}
},
arg => {
eprintln!("Argument unkown: {}", arg);
exit(-1);
},
}
}
for input in inputs {
if let Err(e) = parse_into_model(&input, &mut model) {
eprintln!("Error while parsing file: {}", e);
exit(1);
}
}
let mut events_loop = EventsLoop::new();
let window = WindowBuilder::new();

View File

@ -11,24 +11,8 @@ pub trait RenderCamera {
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;
fn get_perspective_matrix(&self) -> [[f32; 4]; 4] ;
let fov = 3.141592 / 3.0;
let zfar = 1024.0;
let znear = 0.1;
use num::Float;
let f = 1.0 / (fov / 2.0).tan();
[
[f * aspect_ratio , 0.0, 0.0 , 0.0],
[ 0.0 , f , 0.0 , 0.0],
[ 0.0 , 0.0, (zfar+znear)/(zfar-znear) , 1.0],
[ 0.0 , 0.0, -(2.0*zfar*znear)/(zfar-znear), 0.0],
]
}
}
/// Creates a look at matrix from the center, the target pointed by the camera and the up vector.
@ -71,6 +55,21 @@ pub fn look_at_matrix(position: [f32; 3], target: [f32; 3], up: [f32; 3]) -> [[f
}
/// Creates a perspective matrix of a camera.
pub fn perspective_matrix(aspect_ratio: f32, z_near: f32, z_far: f32) -> [[f32; 4]; 4] {
let fov = 3.141592 / 3.0;
use num::Float;
let f = 1.0 / (fov / 2.0).tan();
[
[f / aspect_ratio , 0.0, 0.0 , 0.0],
[ 0.0 , f , 0.0 , 0.0],
[ 0.0 , 0.0, (z_far+z_near)/(z_far-z_near) , 1.0],
[ 0.0 , 0.0, -(2.0*z_far*z_near)/(z_far-z_near), 0.0],
]
}
/// A simple camera with its position, target and up vector.
pub struct Camera {
/// The position of the center of the camera.
@ -81,6 +80,16 @@ pub struct Camera {
/// The up vector of the camera.
pub up: Vector3<f32>,
/// The minimum depth for visible things.
pub z_near: f32,
/// The maximum depth for visible things.
pub z_far: f32,
/// The aspect ratio of the camera.
pub aspect_ratio: f32,
}
impl Camera {
@ -90,6 +99,9 @@ impl Camera {
position: position,
target: target,
up: up,
z_near: 0.01,
z_far: 1000.0,
aspect_ratio: 16.0 / 9.0
}
}
}
@ -98,5 +110,9 @@ impl RenderCamera for Camera {
fn get_view_matrix(&self) -> [[f32; 4]; 4] {
look_at_matrix(self.position.into(), self.target.into(), self.up.into())
}
fn get_perspective_matrix(&self) -> [[f32; 4]; 4] {
perspective_matrix(self.aspect_ratio, self.z_near, self.z_far)
}
}

View File

@ -99,6 +99,12 @@ impl Controls for OrbitControls {
self.pressed = state == ElementState::Pressed;
},
Event::WindowEvent {
event: WindowEvent::Resized(width, height), ..
} => {
camera.aspect_ratio = width as f32 / height as f32;
},
Event::WindowEvent {
event: WindowEvent::MouseWheel {
delta: MouseScrollDelta::LineDelta(_, y), ..

View File

@ -171,7 +171,7 @@ impl<'a, D: Drawer + Facade + Sized> Renderer<'a, D> {
for &(ref material, ref buffer) in buffers {
let perspective = camera.get_perspective_matrix(target.get_dimensions());
let perspective = camera.get_perspective_matrix();
let view = camera.get_view_matrix();
if let &Some(ref texture) = &material.texture {