158 lines
4.8 KiB
Rust
158 lines
4.8 KiB
Rust
|
|
use image::GenericImage;
|
|
use std::path::Path;
|
|
use crate::shader::shader;
|
|
mod mesh;
|
|
use tobj;
|
|
use cgmath::{vec2, vec3};
|
|
|
|
#[derive(Default)]
|
|
pub struct Model
|
|
{
|
|
pub textures_loaded: Vec<mesh::Texture>,
|
|
pub meshes: Vec<mesh::Mesh>,
|
|
directory: String,
|
|
}
|
|
|
|
impl Model {
|
|
pub fn new(path: &str) -> Model {
|
|
let mut model = Model::default();
|
|
model.loadModel(path);
|
|
model
|
|
}
|
|
|
|
|
|
pub fn Draw(&self, shader: &shader) {
|
|
for mesh in &self.meshes {
|
|
unsafe { mesh.Draw(&shader); }
|
|
}
|
|
}
|
|
|
|
fn loadModel(&mut self, path: &str) {
|
|
|
|
let tempPath: String = format!("{}/model.obj", path);
|
|
let path = Path::new(path);
|
|
let modelPath = Path::new(&tempPath);
|
|
|
|
|
|
self.directory = path.parent().unwrap_or_else(|| Path::new("")).to_str().unwrap().into();
|
|
let obj = tobj::load_obj(modelPath);
|
|
|
|
let (models, materials) = obj.unwrap();
|
|
for model in models {
|
|
let mesh = &model.mesh;
|
|
let num_vertices = mesh.positions.len() / 3;
|
|
|
|
|
|
let mut vertices: Vec<mesh::Vertex> = Vec::with_capacity(num_vertices);
|
|
let indices: Vec<u32> = mesh.indices.clone();
|
|
|
|
let (p, n, t) = (&mesh.positions, &mesh.normals, &mesh.texcoords);
|
|
for i in 0..num_vertices {
|
|
vertices.push(mesh::Vertex {
|
|
Position: vec3(p[i*3], p[i*3+1], p[i*3+2]),
|
|
Normal: vec3(n[i*3], n[i*3+1], n[i*3+2]),
|
|
TexCoords: vec2(t[i*2], t[i*2+1]),
|
|
..mesh::Vertex::default()
|
|
})
|
|
}
|
|
|
|
// process
|
|
let mut textures = Vec::new();
|
|
if let Some(material_id) = mesh.material_id {
|
|
let material = &materials[material_id];
|
|
// 1. diffuse map
|
|
//
|
|
if !material.diffuse_texture.is_empty() {
|
|
let texture = self.loadMaterialTexture( &path.join(&material.diffuse_texture).display().to_string(), "texture_diffuse");
|
|
textures.push(texture);
|
|
}
|
|
// 2.specular map
|
|
if !material.specular_texture.is_empty() {
|
|
let texture = self.loadMaterialTexture(&path.join(&material.specular_texture).display().to_string(), "texture_specular");
|
|
textures.push(texture);
|
|
}
|
|
|
|
// 3.normal
|
|
//
|
|
if !material.normal_texture.is_empty() {
|
|
let texture = self.loadMaterialTexture(&path.join(&material.normal_texture).display().to_string(), "texture_normal");
|
|
textures.push(texture);
|
|
|
|
}
|
|
}
|
|
self.meshes.push(mesh::Mesh::new(vertices,indices, textures));
|
|
|
|
|
|
}
|
|
}
|
|
|
|
fn loadMaterialTexture(&mut self, path: &str, typeName: &str) -> mesh::Texture {
|
|
{
|
|
let texture = self.textures_loaded.iter().find(|t| t.path == path);
|
|
if let Some(texture) = texture {
|
|
return texture.clone();
|
|
}
|
|
}
|
|
let texture = mesh::Texture {
|
|
id: TextureFromFile(path),
|
|
type_: typeName.into(),
|
|
path: path.into()
|
|
};
|
|
self.textures_loaded.push(texture.clone());
|
|
texture
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn TextureFromFile(path: &str) -> u32
|
|
{
|
|
let filename = path;
|
|
|
|
let mut textureID = 0;
|
|
|
|
unsafe {
|
|
// NOTE might become a problem later on
|
|
gl::GenTextures(1, textureID as *mut u32);
|
|
gl::BindTexture(gl::TEXTURE_2D, textureID);
|
|
|
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
|
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
|
|
|
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
|
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
|
|
|
|
let img = image::open(Path::new(&filename))
|
|
.expect("failed to load texture");
|
|
img.flipv();
|
|
let format = match img {
|
|
image::DynamicImage::ImageLuma8(_) => gl::RED,
|
|
image::DynamicImage::ImageLumaA8(_) => gl::RG,
|
|
image::DynamicImage::ImageRgb8(_) => gl::RGB,
|
|
image::DynamicImage::ImageRgba8(_) => gl::RGBA,
|
|
_ => panic!("What is this image u gave me big man?")
|
|
};
|
|
let data = img.as_bytes();
|
|
|
|
gl::TexImage2D(gl::TEXTURE_2D,
|
|
0,
|
|
format as i32,
|
|
img.width() as i32,
|
|
img.height() as i32,
|
|
0,
|
|
format,
|
|
gl::UNSIGNED_BYTE,
|
|
&data[0] as *const u8 as *const std::os::raw::c_void);
|
|
gl::GenerateMipmap(gl::TEXTURE_2D);
|
|
}
|
|
|
|
textureID
|
|
|
|
|
|
|
|
}
|