Added support for Kd

This commit is contained in:
Thomas Forgione 2018-06-15 17:36:51 +02:00
parent f6dd2a34ad
commit a487822790
No known key found for this signature in database
GPG Key ID: 203DAEA747F48F41
6 changed files with 84 additions and 42 deletions

View File

@ -1,6 +1,7 @@
#version 140
uniform sampler2D tex;
uniform vec3 diffuse;
in vec3 v_normal;
in vec2 v_tex_coords;
@ -18,7 +19,7 @@ void main() {
vec4 factor = vec4(ambientLight + lambertComponent, 1.0);
color = factor * texture(tex, v_tex_coords);
color = factor * vec4(diffuse, 1.0) * texture(tex, v_tex_coords);
if (color.a < 0.05) {
discard;

View File

@ -1,6 +1,7 @@
//! This module contains everything related to materials.
use std::collections::HashMap;
use math::vector::Vector3;
/// A 3D material.
#[derive(Clone)]
@ -9,6 +10,9 @@ pub struct Material {
/// The name of the material.
pub name: String,
/// The diffuse color of the material.
pub diffuse: Vector3<f32>,
/// Map linking each texture map to its file path.
pub textures: HashMap<String, String>,
@ -24,6 +28,7 @@ impl Material {
pub fn new(name: &str) -> Material {
Material {
name: name.to_owned(),
diffuse: Vector3::new(1.0, 1.0, 1.0),
textures: HashMap::new(),
unknown_instructions: vec![],
}

View File

@ -49,7 +49,7 @@ pub enum Element {
Texture(String, String),
/// Change the main color of the current material.
Color(Vector3<f64>),
Diffuse(Vector3<f32>),
/// An unknown material instruction that will be copied into the mtl file.
UnknownMaterialInstruction(String),
@ -102,11 +102,10 @@ pub enum ParserError {
/// String is the name of the material that is already defined.
MaterialAlreadyExists(String, usize, String),
/// Texture arrived before creating a material.
/// Some material information arrived before creating a material.
///
/// usize is the line.
/// String is the path to the texture.
NoMaterialExist(String, usize, String),
NoMaterialExist(String, usize),
/// Something weird happened
OtherError(String),
@ -174,8 +173,8 @@ impl fmt::Display for ParserError {
write!(f, "Index out of bound in {}:{}:\n\tsize is {} but got {}", p, l, i, s),
ParserError::MaterialAlreadyExists(ref p, l, ref n) =>
write!(f, "Redecralation of material in {}:{}:\n\t{} already exists", p, n, l),
ParserError::NoMaterialExist(ref p, l, ref n) =>
write!(f, "Missing material in {}:{}\n\tNo material were defined, can't set {} as textuure", p, l, n),
ParserError::NoMaterialExist(ref p, l) =>
write!(f, "Missing material in {}:{}\n\tNo material were defined, can't set attribute", p, l),
ParserError::OtherError(ref p) =>
write!(f, "Something weird happened in {}...", p),
}
@ -268,7 +267,7 @@ impl<LP: LineParser> Parser for LP {
Element::Texture(texture_name, texture_path) => {
if current_material_name.is_none() {
return Err(ParserError::NoMaterialExist(path.to_owned(), num, texture_path));
return Err(ParserError::NoMaterialExist(path.to_owned(), num));
}
let material_name = current_material_name.as_ref().unwrap().clone();
@ -276,18 +275,16 @@ impl<LP: LineParser> Parser for LP {
let current_material = model.materials.get_mut(&material_name);
if current_material.is_none() {
return Err(ParserError::NoMaterialExist(path.to_owned(), num, texture_path))
return Err(ParserError::NoMaterialExist(path.to_owned(), num))
}
let current_material = current_material.unwrap();
current_material.textures.insert(texture_name, texture_path);
},
Element::Color(_) => (),
Element::UnknownMaterialInstruction(s) => {
Element::Diffuse(v) => {
if current_material_name.is_none() {
return Err(ParserError::NoMaterialExist(path.to_owned(), num, s));
return Err(ParserError::NoMaterialExist(path.to_owned(), num));
}
let material_name = current_material_name.as_ref().unwrap().clone();
@ -295,7 +292,25 @@ impl<LP: LineParser> Parser for LP {
let current_material = model.materials.get_mut(&material_name);
if current_material.is_none() {
return Err(ParserError::NoMaterialExist(path.to_owned(), num, s))
return Err(ParserError::NoMaterialExist(path.to_owned(), num));
}
let current_material = current_material.unwrap();
current_material.diffuse = v;
},
Element::UnknownMaterialInstruction(s) => {
if current_material_name.is_none() {
return Err(ParserError::NoMaterialExist(path.to_owned(), num));
}
let material_name = current_material_name.as_ref().unwrap().clone();
let current_material = model.materials.get_mut(&material_name);
if current_material.is_none() {
return Err(ParserError::NoMaterialExist(path.to_owned(), num))
}
current_material.unwrap().add_unknown_instruction(s);

View File

@ -3,6 +3,9 @@
use std::path::PathBuf;
use parser::{Element, ParserError, LineParser};
use parser::obj::parse_values;
use math::vector::Vector3;
/// Wavefront material file format parser.
pub struct MtlParser {
@ -21,7 +24,7 @@ impl MtlParser {
}
impl LineParser for MtlParser {
fn parse_line(&mut self, _line_number: usize, line: &str, path: &str) -> Result<Element, ParserError> {
fn parse_line(&mut self, line_number: usize, line: &str, path: &str) -> Result<Element, ParserError> {
let mut root = PathBuf::from(path);
root.pop();
@ -40,6 +43,15 @@ impl LineParser for MtlParser {
// Starts a new material
"newmtl" => Ok(Element::NewMaterial(split.nth(0).unwrap().to_owned())),
"Kd" => {
let values = parse_values(line_number, line, path, 3)?;
Ok(Element::Diffuse(Vector3::new(
values[0] as f32,
values[1] as f32,
values[2] as f32,
)))
},
map if map.starts_with("map_") => {
let mut full_path = root.clone();

View File

@ -4,6 +4,31 @@ use parser::{Element, ParserError, LineParser};
use math::vector::{Vector2, Vector3};
use model::face::{FaceVertex, Face};
/// Parses a certain number of value in a line, and returns a Vec containing the values.
///
/// Will return an error if the number of values expected is incorrect.
pub fn parse_values(line_number: usize, line: &str, path: &str, number_of_values: usize) -> Result<Vec<f64>, ParserError> {
let mut split = line.split_whitespace();
split.next();
let mut ret = vec![];
for elt in split {
if let Ok(value) = elt.parse::<f64>() {
ret.push(value);
} else {
return Err(ParserError::ParseNumberError(path.to_owned(), line_number, elt.to_owned()));
}
}
if ret.len() == number_of_values {
Ok(ret)
} else {
Err(ParserError::IncorrectNumberOfParameters(path.to_owned(), line_number, number_of_values, ret.len()))
}
}
/// The wavefront OBJ format parser.
pub struct ObjParser {
@ -18,30 +43,6 @@ impl ObjParser {
}
}
/// Parses a certain number of value in a line, and returns a Vec containing the values.
///
/// Will return an error if the number of values expected is incorrect.
fn parse_values(&self, line_number: usize, line: &str, path: &str, number_of_values: usize) -> Result<Vec<f64>, ParserError> {
let mut split = line.split_whitespace();
split.next();
let mut ret = vec![];
for elt in split {
if let Ok(value) = elt.parse::<f64>() {
ret.push(value);
} else {
return Err(ParserError::ParseNumberError(path.to_owned(), line_number, elt.to_owned()));
}
}
if ret.len() == number_of_values {
Ok(ret)
} else {
Err(ParserError::IncorrectNumberOfParameters(path.to_owned(), line_number, number_of_values, ret.len()))
}
}
/// Parses an obj vertex line.
///
/// ```
@ -54,7 +55,7 @@ impl ObjParser {
/// ```
pub fn parse_vertex(&self, line_number: usize, line: &str, path: &str) -> Result<Element, ParserError> {
let values = self.parse_values(line_number, line, path, 3)?;
let values = parse_values(line_number, line, path, 3)?;
Ok(Element::Vertex(Vector3::<f64>::new(
values[0],
values[1],
@ -74,7 +75,7 @@ impl ObjParser {
/// ```
pub fn parse_texture_coordinate(&self, line_number: usize, line: &str, path: &str) -> Result<Element, ParserError> {
let values = self.parse_values(line_number, line, path, 2)?;
let values = parse_values(line_number, line, path, 2)?;
Ok(Element::TextureCoordinate(Vector2::<f64>::new(
values[0],
values[1],
@ -93,7 +94,7 @@ impl ObjParser {
/// ```
pub fn parse_normal(&self, line_number: usize, line: &str, path: &str) -> Result<Element, ParserError> {
let values = self.parse_values(line_number, line, path, 3)?;
let values = parse_values(line_number, line, path, 3)?;
Ok(Element::Normal(Vector3::<f64>::new(
values[0],
values[1],

View File

@ -19,6 +19,7 @@ use scene::Scene;
use camera::RenderCamera;
use model::{Vertex, Part, Model};
use math::vector::Vector3;
/// Image data stored as RGBA.
pub struct RgbaImageData {
@ -142,6 +143,12 @@ impl Renderer {
if let &Some(ref buffer) = part.vertex_buffer() {
let diffuse = if let Some(ref name) = part.material_name {
model.materials.get(name).unwrap().diffuse
} else {
Vector3::new(1.0, 1.0, 1.0)
};
let texture = self.get_texture_of_part(&model, part);
let texture = if let Some(texture) = texture {
@ -155,6 +162,7 @@ impl Renderer {
NoIndices(PrimitiveType::TrianglesList),
&self.program,
&uniform!(
diffuse: Into::<[f32; 3]>::into(diffuse),
tex: texture,
perspective: Into::<[[f32; 4]; 4]>::into(perspective),
view: Into::<[[f32; 4]; 4]>::into(view),