added Model.rs

master
Milk.H 2023-02-23 15:02:13 +01:00
parent 5fa37d5f06
commit 19a8b30997
No known key found for this signature in database
GPG Key ID: 3D9DAE46AAC37BD8
18 changed files with 199870 additions and 107 deletions

View File

@ -8,8 +8,9 @@ edition = "2021"
[dependencies]
gl = "0.14.0"
glm = "0.2.3"
stb = { version = "0.3.2", default-features = false, features = ["stb_image"] }
field-offset = "0.3.4"
image = "0.24.5"
tobj = "3.2.4"
cgmath = "0.18.0"
[dependencies.glfw]
version = "*"

BIN
models/backpack/ao.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@ -0,0 +1,16 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Scene_-_Root
Ns 225.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.0 0.0 0.0
Ni 1.450000
d 1.000000
illum 2
map_Kd diffuse.jpg
map_Bump normal.png
map_Ks specular.jpg

199481
models/backpack/backpack.obj Normal file

File diff suppressed because it is too large Load Diff

BIN
models/backpack/diffuse.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 MiB

BIN
models/backpack/normal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

@ -0,0 +1,3 @@
Model by Berk Gedik, from: https://sketchfab.com/3d-models/survival-guitar-backpack-low-poly-799f8c4511f84fab8c3f12887f7e6b36
Modified material assignment (Joey de Vries) for easier load in OpenGL model loading chapter, and renamed albedo to diffuse and metallic to specular to match non-PBR lighting setup.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 MiB

View File

@ -0,0 +1,12 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D texture_diffuse1;
void main()
{
FragColor = texture(texture_diffuse1, TexCoords);
}

View File

@ -0,0 +1,17 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
TexCoords = aTexCoords;
gl_Position = projection * view * model * vec4(aPos, 1.0);
}

View File

@ -0,0 +1,6 @@
#version 330 core
out vec4 Color;
void main()
{
Color = vec4(0.9, 0.5, 0.2, 1.0);
}

View File

@ -0,0 +1,9 @@
#version 330 core
layout (location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
// gl_Position = vec4(position.xyz, 1.0);
// gl_Position = vec4(position.x, position.y, position.z, 1.0);
}

View File

@ -3,14 +3,15 @@ use std::convert::TryInto;
use glfw;
use glfw::{Action, Context, Key};
use gl;
use cgmath::{Matrix4, vec3, Point3, Deg, perspective};
const ScreenWidth: u32 = 480;
const ScreenHeight: u32 = 320;
const TITLE: &str = "GLFWtest";
mod shader;
mod mesh;
mod model;
use model::Model;
fn main() {
// initialize GLFW
@ -37,11 +38,13 @@ fn main() {
unsafe {
gl::Viewport(0, 0, screen_width, screen_height);
gl::ClearColor(1.0, 1.0, 1.0, 1.0);
gl::Enable(gl::DEPTH_TEST);
}
// put biggie thingies here
let test_Shader = shader::shader::new("basic");
let model_Shader = shader::shader::new("model");
let ourModel = Model::new("backpack/backpack.obj");
// NOTE window loop
while !window.should_close() {
@ -50,13 +53,17 @@ fn main() {
glfw_handle_event(&mut window, event);
}
clear_color(0.1, 0.1, 0.1, -0.0);
model_Shader.Use();
// view/projection transformations
//let projection:;
unsafe {
gl::Clear(gl::COLOR_BUFFER_BIT);
}
};
test_Shader.Use();
window.swap_buffers();
}

View File

@ -1,98 +0,0 @@
use field_offset::offset_of;
pub struct Vertex {
Position: glm::Vec3,
Normal: glm::Vec2,
TexCoords: glm::Vec2,
Tangent: glm::Vec3,
Bitangent: glm::Vec3,
m_BoneIDs: [i32; 4],
m_Weights: [f32; 4],
}
pub struct Texture {
id: u32,
Type: String,
path: String,
}
struct Mesh {
pub vertices: Vec<Vertex>,
pub indices: Vec<u32>,
pub textures: Vec<Texture>,
pub VAO: Option<u32>,
VBO: Option<u32>,
EBO: Option<u32>,
}
impl Mesh{
pub fn new(vertices: Vec<Vertex>, indices: Vec<u32>, textures: Vec<Texture>)
{
let mut temp = Mesh {
vertices,
indices,
textures,
VAO: None,
VBO: None,
EBO: None,
};
}
fn setupMesh(mut temp: Mesh)
{
// create buffers/arrays
unsafe {
gl::GenVertexArrays(1, temp.VAO.as_mut().unwrap());
gl::GenBuffers(1, temp.VBO.as_mut().unwrap());
gl::GenBuffers(1, temp.EBO.as_mut().unwrap());
gl::BindVertexArray(temp.VAO.unwrap());
// NOTE, i am not sure if this one will work
gl::BindBuffer(gl::ARRAY_BUFFER, temp.VBO.unwrap());
gl::BufferData(gl::ARRAY_BUFFER, std::mem::size_of_val(&temp.vertices) as isize, temp.vertices.as_ptr().cast(), gl::STATIC_DRAW);
// the vertex attribPointers
// vert pox
gl::EnableVertexAttribArray(0);
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, 0 as *const _);
// vertex normals
gl::EnableVertexAttribArray(1);
gl::VertexAttribPointer(1, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => Normal).get_byte_offset() as *const _);
// vertex texture coords
gl::EnableVertexAttribArray(2);
gl::VertexAttribPointer(2, 2, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => TexCoords).get_byte_offset() as *const _);
//vertex tangent
gl::EnableVertexAttribArray(3);
gl::VertexAttribPointer(3, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => Tangent).get_byte_offset() as *const _);
// vertex Bitangent
gl::EnableVertexAttribArray(4);
gl::VertexAttribPointer(4, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => Bitangent).get_byte_offset() as *const _);
// ids
gl::EnableVertexAttribArray(5);
gl::VertexAttribIPointer(5, 4, gl::INT, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => m_BoneIDs).get_byte_offset() as *const _);
// weights
gl::EnableVertexAttribArray(6);
gl::VertexAttribPointer(6, 4, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => m_Weights).get_byte_offset() as *const _);
}
}
}

152
src/model.rs Normal file
View File

@ -0,0 +1,152 @@
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 path = Path::new(path);
self.directory = path.parent().unwrap_or_else(|| Path::new("")).to_str().unwrap().into();
let obj = tobj::load_obj(path, &tobj::LoadOptions::default());
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.as_ref().unwrap()[material_id];
// 1. diffuse map
//
if !material.diffuse_texture.is_empty() {
let texture = self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse");
textures.push(texture);
}
// 2.specular map
if !material.specular_texture.is_empty() {
let texture = self.loadMaterialTexture(&material.specular_texture, "texture_specular");
textures.push(texture);
}
// 3.normal
//
if !material.normal_texture.is_empty() {
let texture = self.loadMaterialTexture(&material.normal_texture, "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 = format!("resources/models/{}", 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
}

157
src/model/mesh.rs Normal file
View File

@ -0,0 +1,157 @@
#![allow(non_snake_case)]
#![allow(dead_code)]
use field_offset::offset_of;
use cgmath::{Vector3, Vector2};
use cgmath::prelude::*;
pub struct Vertex {
pub Position: Vector3<f32>,
pub Normal: Vector3<f32>,
pub TexCoords: Vector2<f32>,
pub Tangent: Vector3<f32>,
pub Bitangent: Vector3<f32>,
}
impl Default for Vertex {
fn default () -> Self {
Vertex {
Position: Vector3::zero(),
Normal: Vector3::zero(),
TexCoords: Vector2::zero(),
Tangent: Vector3::zero(),
Bitangent: Vector3::zero(),
}
}
}
#[derive(Clone)]
pub struct Texture {
pub id: u32,
pub type_: String,
pub path: String,
}
#[derive(Default)]
pub struct Mesh {
pub vertices: Vec<Vertex>,
pub indices: Vec<u32>,
pub textures: Vec<Texture>,
pub VAO: u32,
VBO: u32,
EBO: u32,
}
impl Mesh{
pub fn new(vertices: Vec<Vertex>, indices: Vec<u32>, textures: Vec<Texture>) -> Mesh
{
let mut temp = Mesh {
vertices,
indices,
textures,
VAO: 0,
VBO: 0,
EBO: 0,
};
temp.setupMesh();
temp
}
fn setupMesh(&mut self)
{
// create buffers/arrays
unsafe {
gl::GenVertexArrays(1, &mut self.VAO);
gl::GenBuffers(1, &mut self.VBO);
gl::GenBuffers(1, &mut self.EBO);
gl::BindVertexArray(self.VAO);
let size = (self.vertices.len() * std::mem::size_of::<Vertex>()) as isize;
// NOTE, i am not sure if this one will work
gl::BindBuffer(gl::ARRAY_BUFFER, self.VBO);
gl::BufferData(gl::ARRAY_BUFFER, size, self.vertices.as_ptr().cast(), gl::STATIC_DRAW);
// the vertex attribPointers
// vert pox
gl::EnableVertexAttribArray(0);
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, 0 as *const _);
// vertex normals
gl::EnableVertexAttribArray(1);
gl::VertexAttribPointer(1, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => Normal).get_byte_offset() as *const std::os::raw::c_void);
// vertex texture coords
gl::EnableVertexAttribArray(2);
gl::VertexAttribPointer(2, 2, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => TexCoords).get_byte_offset() as *const std::os::raw::c_void);
//vertex tangent
gl::EnableVertexAttribArray(3);
gl::VertexAttribPointer(3, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => Tangent).get_byte_offset() as *const std::os::raw::c_void);
// vertex Bitangent
gl::EnableVertexAttribArray(4);
gl::VertexAttribPointer(4, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, offset_of!(Vertex => Bitangent).get_byte_offset() as *const std::os::raw::c_void);
gl::BindVertexArray(0);
}
}
// TODO this
pub fn Draw(&self, shader: &crate::shader::shader)
{
let mut diffuseNr = 0;
let mut specularNr = 0;
let mut normalNr = 0;
let mut heightNr = 0;
for (i, texture) in self.textures.iter().enumerate() {
unsafe {gl::ActiveTexture(gl::TEXTURE0 + i as u32)};
let name = &texture.type_;
let number = match name.as_str() {
"texture_diffuse" => {
diffuseNr +=1;
diffuseNr
},
"texture_specular" => {
specularNr += 1;
specularNr
},
"texture_normal" => {
normalNr += 1;
normalNr
},
"texture_height" => {
heightNr += 1;
heightNr
}
_ => panic!("unknown texture type")
};
// set the sampler to the correct texture unit
let sampler = format!("{}{}", name, number);
unsafe{
shader.setInt( &(sampler as String), i as u32 );
gl::BindTexture(gl::TEXTURE_2D, texture.id);
}
}
}
}

View File

@ -93,7 +93,7 @@ use glm;
unsafe {gl::UseProgram(self.ID);}
}
// TODO write tests for these
// BOILERPLATE JUMPSCARE
pub fn setBool(&self, name: &str, value: bool )
{unsafe {gl::Uniform1i(gl::GetUniformLocation(self.ID, name.as_ptr() as *const gl::types::GLchar), value as i32);}}