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![];
|
let mut shape = vec![];
|
||||||
for face in &self.faces {
|
for face in &self.faces {
|
||||||
for &&v in &[&face.a, &face.b, &face.c] {
|
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 {
|
shape.push(Vertex {
|
||||||
vertex: vertices[v.vertex].into(),
|
vertex: vertex,
|
||||||
tex_coords: tex_coords[v.texture_coordinate.unwrap()].into(),
|
tex_coords: tex_coord,
|
||||||
normal: normals[v.normal.unwrap()].into(),
|
normal: normal,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ pub mod obj;
|
|||||||
pub mod mtl;
|
pub mod mtl;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufReader, Error};
|
use std::io::{BufReader, Error};
|
||||||
use math::vector::{Vector2, Vector3};
|
use math::vector::{Vector2, Vector3};
|
||||||
@ -19,6 +19,9 @@ pub enum Element {
|
|||||||
/// An empty element (correspond to an empty line for example).
|
/// An empty element (correspond to an empty line for example).
|
||||||
None,
|
None,
|
||||||
|
|
||||||
|
/// Declares the use of a material file.
|
||||||
|
MaterialLib(String),
|
||||||
|
|
||||||
/// Changes the material used for the next faces.
|
/// Changes the material used for the next faces.
|
||||||
UseMaterial(String),
|
UseMaterial(String),
|
||||||
|
|
||||||
@ -48,6 +51,9 @@ pub enum Element {
|
|||||||
|
|
||||||
/// An unknown material instruction that will be copied into the mtl file.
|
/// An unknown material instruction that will be copied into the mtl file.
|
||||||
UnknownMaterialInstruction(String),
|
UnknownMaterialInstruction(String),
|
||||||
|
|
||||||
|
/// Declares multiple faces.
|
||||||
|
Faces(Vec<Face>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -225,6 +231,16 @@ impl<LP: LineParser> Parser for LP {
|
|||||||
Element::TextureCoordinate(v) => model.texture_coordinates.push(v),
|
Element::TextureCoordinate(v) => model.texture_coordinates.push(v),
|
||||||
Element::Normal(v) => model.normals.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) => {
|
Element::Face(f) => {
|
||||||
if let Err(ModelError::IndexError(index, size)) = model.add_face(f) {
|
if let Err(ModelError::IndexError(index, size)) = model.add_face(f) {
|
||||||
return Err(ParserError::IndexOutOfBound(path.to_owned(), num, index, size));
|
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);
|
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 let Some(texture_coordinate_string) = texture_coordinate_string {
|
||||||
if texture_coordinate_string.len() != 0 {
|
if texture_coordinate_string.len() != 0 {
|
||||||
let texture_coordinate_index = texture_coordinate_string.parse::<usize>();
|
let texture_coordinate_index = texture_coordinate_string.parse::<usize>();
|
||||||
|
|
||||||
if texture_coordinate_index.is_err() {
|
if texture_coordinate_index.is_err() {
|
||||||
return Err(ParserError::ParseNumberError(
|
return Err(ParserError::ParseNumberError(
|
||||||
path.to_owned(),line_number, texture_coordinate_string.to_owned()
|
path.to_owned(),line_number, texture_coordinate_string.to_owned()
|
||||||
@ -185,10 +184,15 @@ impl ObjParser {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if face_vertices.len() != 3 {
|
if face_vertices.len() == 3 {
|
||||||
Err(ParserError::TooManyVertices(path.to_owned(), line_number, face_vertices.len()))
|
|
||||||
} else {
|
|
||||||
Ok(Element::Face(Face::new(face_vertices[0], face_vertices[1], face_vertices[2])))
|
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) {
|
if let Some(first) = split.nth(0) {
|
||||||
match first {
|
match first {
|
||||||
|
|
||||||
|
"mtllib" => Ok(Element::MaterialLib(split.nth(0).unwrap().to_owned())),
|
||||||
"v" => self.parse_vertex(line_number, line, path),
|
"v" => self.parse_vertex(line_number, line, path),
|
||||||
"vt" => self.parse_texture_coordinate(line_number, line, path),
|
"vt" => self.parse_texture_coordinate(line_number, line, path),
|
||||||
"vn" => self.parse_normal(line_number, line, path),
|
"vn" => self.parse_normal(line_number, line, path),
|
||||||
"usemtl" => Ok(Element::UseMaterial(split.nth(0).unwrap().to_owned())),
|
"usemtl" => Ok(Element::UseMaterial(split.nth(0).unwrap().to_owned())),
|
||||||
"f" => self.parse_face(line_number, line, path),
|
"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())),
|
key if key.len() != 0 => Err(ParserError::UnexpectedKeyword(path.to_owned(), line_number, key.to_owned())),
|
||||||
_ => Ok(Element::None),
|
_ => Ok(Element::None),
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
extern crate glium;
|
extern crate glium;
|
||||||
extern crate model_converter;
|
extern crate model_converter;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::process::exit;
|
||||||
|
|
||||||
use glium::Display;
|
use glium::Display;
|
||||||
use glium::glutin;
|
use glium::glutin;
|
||||||
use glium::glutin::{
|
use glium::glutin::{
|
||||||
@ -14,15 +17,45 @@ use glium::glutin::VirtualKeyCode;
|
|||||||
|
|
||||||
|
|
||||||
use model_converter::math::vector::Vector3;
|
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::Renderer;
|
||||||
use model_converter::renderer::controls::OrbitControls;
|
use model_converter::renderer::controls::OrbitControls;
|
||||||
use model_converter::renderer::camera::Camera;
|
use model_converter::renderer::camera::Camera;
|
||||||
|
use model_converter::model::Model;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
let mut model = parse("./assets/models/link/link.mtl").unwrap();
|
let mut model = Model::new();
|
||||||
parse_into_model("./assets/models/link/link.obj", &mut model).unwrap();
|
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 mut events_loop = EventsLoop::new();
|
||||||
let window = WindowBuilder::new();
|
let window = WindowBuilder::new();
|
||||||
|
@ -11,24 +11,8 @@ pub trait RenderCamera {
|
|||||||
fn get_view_matrix(&self) -> [[f32; 4]; 4];
|
fn get_view_matrix(&self) -> [[f32; 4]; 4];
|
||||||
|
|
||||||
/// Returns the perspective matrix of the camera.
|
/// Returns the perspective matrix of the camera.
|
||||||
fn get_perspective_matrix(&self, dimensions: (u32, u32)) -> [[f32; 4]; 4] {
|
fn get_perspective_matrix(&self) -> [[f32; 4]; 4] ;
|
||||||
let (width, height) = dimensions;
|
|
||||||
let aspect_ratio = height as f32 / width as f32;
|
|
||||||
|
|
||||||
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.
|
/// 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.
|
/// A simple camera with its position, target and up vector.
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
/// The position of the center of the camera.
|
/// The position of the center of the camera.
|
||||||
@ -81,6 +80,16 @@ pub struct Camera {
|
|||||||
|
|
||||||
/// The up vector of the camera.
|
/// The up vector of the camera.
|
||||||
pub up: Vector3<f32>,
|
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 {
|
impl Camera {
|
||||||
@ -90,6 +99,9 @@ impl Camera {
|
|||||||
position: position,
|
position: position,
|
||||||
target: target,
|
target: target,
|
||||||
up: up,
|
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] {
|
fn get_view_matrix(&self) -> [[f32; 4]; 4] {
|
||||||
look_at_matrix(self.position.into(), self.target.into(), self.up.into())
|
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;
|
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 {
|
||||||
event: WindowEvent::MouseWheel {
|
event: WindowEvent::MouseWheel {
|
||||||
delta: MouseScrollDelta::LineDelta(_, y), ..
|
delta: MouseScrollDelta::LineDelta(_, y), ..
|
||||||
|
@ -171,7 +171,7 @@ impl<'a, D: Drawer + Facade + Sized> Renderer<'a, D> {
|
|||||||
|
|
||||||
for &(ref material, ref buffer) in buffers {
|
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();
|
let view = camera.get_view_matrix();
|
||||||
|
|
||||||
if let &Some(ref texture) = &material.texture {
|
if let &Some(ref texture) = &material.texture {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user