Modules and stuff
This commit is contained in:
158
src/vulkan/mesh.rs
Normal file
158
src/vulkan/mesh.rs
Normal file
@@ -0,0 +1,158 @@
|
||||
use std::time::SystemTime;
|
||||
|
||||
use gltf::Error;
|
||||
use gltf::mesh::util::{ReadJoints, ReadNormals, ReadPositions, ReadTangents, ReadTexCoords, ReadWeights};
|
||||
|
||||
use crate::vulkan::mesh::LoadError::{GltfError, MeshDataMissing, NoIndices};
|
||||
use crate::vulkan::Vertex;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LoadError {
|
||||
GltfError(gltf::Error),
|
||||
MeshDataMissing(String),
|
||||
NoIndices
|
||||
}
|
||||
|
||||
impl From<gltf::Error> for LoadError {
|
||||
fn from(e: Error) -> Self {
|
||||
GltfError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for LoadError {
|
||||
fn from(e: String) -> Self {
|
||||
MeshDataMissing(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CPUMesh {
|
||||
pub vertices: Vec<Vertex>,
|
||||
pub indices: Vec<u32>,
|
||||
pub local_texture_index: Option<usize>,
|
||||
pub local_normal_map_index: Option<usize>,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
pub fn load_mesh(mesh_path: &str, print_status: bool) -> Result<(Vec<CPUMesh>, Vec<gltf::image::Data>), LoadError> {
|
||||
let mut start_time = None;
|
||||
let mut total_vertices = 0;
|
||||
let mut total_indices = 0;
|
||||
|
||||
if print_status {
|
||||
start_time = Some(SystemTime::now());
|
||||
println!("Loading mesh file {}", mesh_path);
|
||||
}
|
||||
let (document, buffers, textures) = gltf::import(mesh_path)?;
|
||||
let mut meshes = vec![];
|
||||
|
||||
if print_status { println!("Mesh file loaded after {} seconds, processing...", start_time.unwrap().elapsed().unwrap().as_secs()); }
|
||||
|
||||
for mesh in document.meshes() {
|
||||
for primitive in mesh.primitives() {
|
||||
let texture_index = primitive.material().pbr_metallic_roughness().base_color_texture().map(|tex_info| tex_info.texture().index());
|
||||
let normal_map_index = primitive.material().normal_texture().map(|tex_info| tex_info.texture().index());
|
||||
|
||||
|
||||
let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()]));
|
||||
let indices = reader.read_indices().ok_or(NoIndices)?;
|
||||
let vertices_result = create_vertices(
|
||||
reader.read_positions(),
|
||||
reader.read_tex_coords(0),
|
||||
reader.read_normals(),
|
||||
reader.read_tangents(),
|
||||
reader.read_joints(0),
|
||||
reader.read_weights(0));
|
||||
let vertices = vertices_result?;
|
||||
let cpu_mesh = CPUMesh {
|
||||
vertices,
|
||||
indices: indices.into_u32().collect(),
|
||||
local_texture_index: texture_index,
|
||||
local_normal_map_index: normal_map_index,
|
||||
name: mesh.name().map(|n| n.to_owned()),
|
||||
};
|
||||
if print_status {
|
||||
let vert_count = cpu_mesh.vertices.len();
|
||||
let index_count = cpu_mesh.indices.len();
|
||||
|
||||
println!("Loaded mesh {} after {} seconds: {} Vertices, {} Indices",
|
||||
mesh.name().unwrap_or(""),
|
||||
start_time.unwrap().elapsed().unwrap().as_secs(),
|
||||
vert_count,
|
||||
index_count);
|
||||
|
||||
total_vertices += vert_count;
|
||||
total_indices += index_count;
|
||||
}
|
||||
meshes.push(cpu_mesh);
|
||||
}
|
||||
}
|
||||
|
||||
if print_status {
|
||||
println!("Finished loading file, total vertices: {}, total indices: {}", total_vertices, total_indices);
|
||||
}
|
||||
|
||||
Ok((meshes, textures))
|
||||
}
|
||||
|
||||
fn create_vertices(positions: Option<ReadPositions>,
|
||||
tex_coords: Option<ReadTexCoords>,
|
||||
normals: Option<ReadNormals>,
|
||||
tangents: Option<ReadTangents>,
|
||||
joints: Option<ReadJoints>,
|
||||
weights: Option<ReadWeights>)
|
||||
-> Result<Vec<Vertex>, String> {
|
||||
match (positions, tex_coords, normals, tangents, joints, weights) {
|
||||
(Some(positions),
|
||||
Some(tex_coords),
|
||||
Some(normals),
|
||||
Some(tangents),
|
||||
Some(joints),
|
||||
Some(weights)) => {
|
||||
Ok(positions
|
||||
.zip(tex_coords.into_f32())
|
||||
.zip(normals)
|
||||
.zip(tangents)
|
||||
.zip(joints.into_u16().map(|arr| {
|
||||
let mut casted_joints: [i32; 4] = [0; 4];
|
||||
for i in 0..4 {
|
||||
casted_joints[i] = arr[i] as i32;
|
||||
}
|
||||
casted_joints
|
||||
}))
|
||||
.zip(weights.into_f32())
|
||||
.map(|(((((p, t), n), ta), i), w)| Vertex {
|
||||
position: p,
|
||||
uv: t,
|
||||
normal: n,
|
||||
tangent: ta,
|
||||
bone_index: i,
|
||||
bone_weight: w
|
||||
}).collect())
|
||||
},
|
||||
(Some(positions),
|
||||
Some(tex_coords),
|
||||
Some(normals),
|
||||
Some(tangents),
|
||||
None, None) => {
|
||||
Ok(positions
|
||||
.zip(tex_coords.into_f32())
|
||||
.zip(normals)
|
||||
.zip(tangents)
|
||||
.map(|(((p, t), n), ta)| Vertex {
|
||||
position: p,
|
||||
uv: t,
|
||||
normal: n,
|
||||
tangent: ta,
|
||||
bone_index: [-1; 4],
|
||||
bone_weight: [0.0; 4]
|
||||
}).collect())
|
||||
},
|
||||
(None, _, _, _, _, _) => Err("Vertex positions missing!".to_string()),
|
||||
(_, None, _, _, _, _) => Err("Tex coords missing!".to_string()),
|
||||
(_, _, None, _, _, _) => Err("Normals missing!".to_string()),
|
||||
(_, _, _, None, _, _) => Err("Tangents missing!".to_string()),
|
||||
(_, _, _, _, Some(_), None) => Err("Bone indices exist, but bone weights are missing!".to_string()),
|
||||
(_, _, _, _, None, Some(_)) => Err("Bone weights exist, but bone incides are missing!".to_string()),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user