Added support for Kd
This commit is contained in:
parent
f6dd2a34ad
commit
a487822790
|
@ -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;
|
||||
|
|
|
@ -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![],
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue