diff --git a/lyra-resource/src/loader/model.rs b/lyra-resource/src/loader/model.rs index 731e115..a1cb9e0 100644 --- a/lyra-resource/src/loader/model.rs +++ b/lyra-resource/src/loader/model.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use base64::Engine; -use crate::{ResourceLoader, LoaderError, Mesh, Model, MeshVertexAttribute, VertexAttributeData, Resource, Material, ResHandle}; +use crate::{ResourceLoader, LoaderError, Mesh, Model, MeshVertexAttribute, VertexAttributeData, Resource, Material, MeshIndices}; use tracing::debug; @@ -67,10 +67,11 @@ impl ModelLoader { // read the indices if let Some(indices) = reader.read_indices() { - let indices: Vec = match indices { - gltf::mesh::util::ReadIndices::U8(i) => i.map(|i| i as u32).collect(), - gltf::mesh::util::ReadIndices::U16(i) => i.map(|i| i as u32).collect(), - gltf::mesh::util::ReadIndices::U32(i) => i.collect(), + let indices: MeshIndices = match indices { + // wpgu doesn't support u8 indices, so those must be converted to u16 + gltf::mesh::util::ReadIndices::U8(i) => MeshIndices::U16(i.map(|i| i as u16).collect()), + gltf::mesh::util::ReadIndices::U16(i) => MeshIndices::U16(i.collect()), + gltf::mesh::util::ReadIndices::U32(i) => MeshIndices::U32(i.collect()), }; new_mesh.indices = Some(indices); diff --git a/lyra-resource/src/model.rs b/lyra-resource/src/model.rs index e83fe3d..652cef2 100644 --- a/lyra-resource/src/model.rs +++ b/lyra-resource/src/model.rs @@ -1,6 +1,32 @@ use std::collections::HashMap; -use crate::{Material, ResHandle}; +use crate::Material; + +#[repr(C)] +#[derive(Clone, Debug, PartialEq)] +pub enum MeshIndices { + //U8(Vec), + U16(Vec), + U32(Vec), +} + +/* impl From> for MeshIndices { + fn from(value: Vec) -> Self { + MeshIndices::U8(value) + } +} */ + +impl From> for MeshIndices { + fn from(value: Vec) -> Self { + MeshIndices::U16(value) + } +} + +impl From> for MeshIndices { + fn from(value: Vec) -> Self { + MeshIndices::U32(value) + } +} #[repr(C)] #[derive(Clone, Debug, PartialEq)] @@ -45,7 +71,7 @@ pub enum MeshVertexAttribute { #[derive(Clone, Default, edict::Component)] pub struct Mesh { pub attributes: HashMap, - pub indices: Option>, + pub indices: Option, material: Option, } diff --git a/src/render/render_pipeline.rs b/src/render/render_pipeline.rs index d1a7f20..87f876f 100755 --- a/src/render/render_pipeline.rs +++ b/src/render/render_pipeline.rs @@ -1,8 +1,8 @@ -use std::{ops::Range, cell::Ref}; +use std::ops::Range; use wgpu::{PipelineLayout, RenderPipeline, RenderPass, VertexBufferLayout, BindGroupLayout}; -use super::{render_job::RenderJob, vertex::Vertex, desc_buf_lay::DescVertexBufferLayout, texture::RenderTexture}; +use super::{render_job::RenderJob, texture::RenderTexture}; pub struct FullRenderPipeline { layout: PipelineLayout, diff --git a/src/render/renderer.rs b/src/render/renderer.rs index 0478f5d..f51bde1 100755 --- a/src/render/renderer.rs +++ b/src/render/renderer.rs @@ -36,7 +36,7 @@ pub trait Renderer { struct RenderBufferStorage { buffer_vertex: BufferStorage, - buffer_indices: Option, + buffer_indices: Option<(wgpu::IndexFormat, BufferStorage)>, render_texture: Option, texture_bindgroup: Option, @@ -404,14 +404,6 @@ impl BasicRenderer { s } - fn find_next_multiple(n: u32, mul: u32) -> u32 { - if n % mul == 0 { - n - } else { - n + (mul - n % mul) - } - } - fn update_mesh_buffers(&mut self, entity: EntityId, mesh: &Mesh) { if let Some(buffers) = self.buffer_storage.get_mut(&entity) { // check if the buffer sizes dont match. If they dont, completely remake the buffers @@ -438,16 +430,19 @@ impl BasicRenderer { // update the indices if they're given if let Some(index_buffer) = buffers.buffer_indices.as_ref() { - let index_buffer = index_buffer.buffer(); - let indices = mesh.indices.as_ref().unwrap().as_slice(); - let (_, indices, _) = bytemuck::pod_align_to::(indices); // TODO: Don't force indicies into u32 - - self.queue.write_buffer(index_buffer, 0, bytemuck::cast_slice(&indices)); + let aligned_indices = match mesh.indices.as_ref().unwrap() { + // U16 indices need to be aligned to u32, for wpgu, which are 4-bytes in size. + lyra_resource::MeshIndices::U16(v) => bytemuck::pod_align_to::(v).1, + lyra_resource::MeshIndices::U32(v) => bytemuck::pod_align_to::(v).1, + }; + + let index_buffer = index_buffer.1.buffer(); + self.queue.write_buffer(index_buffer, 0, bytemuck::cast_slice(&aligned_indices)); } } } - fn create_vertex_index_buffers(&mut self, mesh: &Mesh) -> (BufferStorage, Option) { + fn create_vertex_index_buffers(&mut self, mesh: &Mesh) -> (BufferStorage, Option<(wgpu::IndexFormat, BufferStorage)>) { let vertices = mesh.position().unwrap(); let vertex_buffer = self.device.create_buffer_init( &wgpu::util::BufferInitDescriptor { @@ -458,26 +453,31 @@ impl BasicRenderer { ); let vertex_buffer = BufferStorage::new(vertex_buffer, 0, vertices.len()); - let buffer_indices = match mesh.indices.as_ref() { + let indices = match mesh.indices.as_ref() { Some(indices) => { + let (idx_type, len, contents) = match indices { + lyra_resource::MeshIndices::U16(v) => (wgpu::IndexFormat::Uint16, v.len(), bytemuck::cast_slice(&v)), + lyra_resource::MeshIndices::U32(v) => (wgpu::IndexFormat::Uint32, v.len(), bytemuck::cast_slice(&v)), + }; + let index_buffer = self.device.create_buffer_init( &wgpu::util::BufferInitDescriptor { label: Some("Index Buffer"), - contents: bytemuck::cast_slice(&indices), + contents, usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages:: COPY_DST, } ); - let buffer_indices = BufferStorage::new(index_buffer, 0, indices.len()); + let buffer_indices = BufferStorage::new(index_buffer, 0, len); - Some(buffer_indices) + Some((idx_type, buffer_indices)) }, None => { None } }; - ( vertex_buffer, buffer_indices ) + ( vertex_buffer, indices ) } fn create_mesh_buffers(&mut self, mesh: &Mesh, transform_indices: TransformBufferIndices) -> RenderBufferStorage { @@ -676,11 +676,11 @@ impl Renderer for BasicRenderer { render_pass.set_bind_group(2, &self.camera_bind_group, &[]); // if this mesh uses indices, use them to draw the mesh - if let Some(indices) = buffers.buffer_indices.as_ref() { + if let Some((idx_type, indices)) = buffers.buffer_indices.as_ref() { let indices_len = indices.count() as u32; render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..)); - render_pass.set_index_buffer(indices.buffer().slice(..), wgpu::IndexFormat::Uint32); + render_pass.set_index_buffer(indices.buffer().slice(..), idx_type.clone()); render_pass.draw_indexed(0..indices_len, 0, 0..1); } else { let vertices = mesh.position().unwrap();