A big commit
This commit is contained in:
parent
6cb76e9986
commit
211f7fc5c5
19
src/model.rs
19
src/model.rs
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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), ..
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue