diff options
| author | LLLL Colonq <llll@colonq> | 2026-05-24 21:39:09 -0400 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2026-05-24 21:39:09 -0400 |
| commit | df6dde704893e98c1899dc8f47fbbb87b7551fca (patch) | |
| tree | 45f70cb6f343357b08a10664b9d7a4a651bb32eb /crates | |
| parent | 9847f348d1acc9591a6c397fc60c7110e091bb3f (diff) | |
Reupload meshes
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/teleia/src/mesh.rs | 127 | ||||
| -rw-r--r-- | crates/teleia/src/scene.rs | 4 | ||||
| -rw-r--r-- | crates/teleia_macros/src/lib.rs | 27 |
3 files changed, 120 insertions, 38 deletions
diff --git a/crates/teleia/src/mesh.rs b/crates/teleia/src/mesh.rs index 16a4380..536058d 100644 --- a/crates/teleia/src/mesh.rs +++ b/crates/teleia/src/mesh.rs @@ -11,6 +11,10 @@ pub const ATTRIB_COLOR: u32 = 5; pub struct Mesh { pub vao: glow::VertexArray, + pub vbo_vertex: glow::NativeBuffer, + pub vbo_index: glow::NativeBuffer, + pub vbo_normal: Option<glow::NativeBuffer>, + pub vbo_texcoord: Option<glow::NativeBuffer>, pub mode: u32, // glow::TRIANGLES, etc. pub index_count: usize, pub index_type: u32, // glow::BYTE, glow::FLOAT, etc. @@ -18,19 +22,58 @@ pub struct Mesh { } impl Mesh { - pub fn build( + pub fn new_empty(ctx: &context::Context, normals: bool, texcoords: bool) -> Self { + unsafe { + let vao = ctx.gl.create_vertex_array().expect("failed to initialize vao"); + ctx.gl.bind_vertex_array(Some(vao)); + + let vbo_vertex = ctx.gl.create_buffer().expect("failed to create buffer object"); + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_vertex)); + ctx.gl.vertex_attrib_pointer_f32(ATTRIB_VERTEX, 3, glow::FLOAT, false, 0, 0); + ctx.gl.enable_vertex_attrib_array(ATTRIB_VERTEX); + + let vbo_index = ctx.gl.create_buffer().expect("failed to create buffer object"); + ctx.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(vbo_index)); + + let vbo_normal = if normals { + let vbo_normal = ctx.gl.create_buffer().expect("failed to create buffer object"); + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_normal)); + ctx.gl.vertex_attrib_pointer_f32(ATTRIB_NORMAL, 3, glow::FLOAT, false, 0, 0); + ctx.gl.enable_vertex_attrib_array(ATTRIB_NORMAL); + Some(vbo_normal) + } else { None }; + + let vbo_texcoord = if texcoords { + let vbo_texcoord = ctx.gl.create_buffer().expect("failed to create buffer object"); + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_texcoord)); + ctx.gl.vertex_attrib_pointer_f32(ATTRIB_TEXCOORD, 2, glow::FLOAT, false, 0, 0); + ctx.gl.enable_vertex_attrib_array(ATTRIB_TEXCOORD); + Some(vbo_texcoord) + } else { None }; + + Self { + vao, + vbo_vertex, + vbo_index, + vbo_normal, + vbo_texcoord, + mode: glow::TRIANGLES, + index_count: 0, + index_type: glow::UNSIGNED_INT, + index_offset: 0, + } + } + } + pub fn upload( + &mut self, ctx: &context::Context, vertices: &[f32], indices: &[u32], snormals: Option<&[f32]>, stexcoords: Option<&[f32]>, - ) -> Self { + ) { unsafe { - let vao = ctx.gl.create_vertex_array().expect("failed to initialize vao"); - ctx.gl.bind_vertex_array(Some(vao)); - - let buf = ctx.gl.create_buffer().expect("failed to create buffer object"); - ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(buf)); + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vbo_vertex)); ctx.gl.buffer_data_u8_slice( glow::ARRAY_BUFFER, std::slice::from_raw_parts( @@ -39,11 +82,7 @@ impl Mesh { ), glow::STATIC_DRAW, ); - ctx.gl.vertex_attrib_pointer_f32(ATTRIB_VERTEX, 3, glow::FLOAT, false, 0, 0); - ctx.gl.enable_vertex_attrib_array(ATTRIB_VERTEX); - - let indices_vbo = ctx.gl.create_buffer().expect("failed to create buffer object"); - ctx.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(indices_vbo)); + ctx.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.vbo_index)); ctx.gl.buffer_data_u8_slice( glow::ELEMENT_ARRAY_BUFFER, std::slice::from_raw_parts( @@ -53,9 +92,8 @@ impl Mesh { glow::STATIC_DRAW, ); - if let Some(normals) = snormals { - let normals_vbo = ctx.gl.create_buffer().expect("failed to create buffer object"); - ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(normals_vbo)); + if let Some(vbo_normal) = self.vbo_normal && let Some(normals) = snormals { + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_normal)); ctx.gl.buffer_data_u8_slice( glow::ARRAY_BUFFER, std::slice::from_raw_parts( @@ -64,13 +102,11 @@ impl Mesh { ), glow::STATIC_DRAW, ); - ctx.gl.vertex_attrib_pointer_f32(ATTRIB_NORMAL, 3, glow::FLOAT, false, 0, 0); - ctx.gl.enable_vertex_attrib_array(ATTRIB_NORMAL); - } + Some(vbo_normal) + } else { None }; - if let Some(texcoords) = stexcoords { - let texcoords_vbo = ctx.gl.create_buffer().expect("failed to create buffer object"); - ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(texcoords_vbo)); + if let Some(vbo_texcoord) = self.vbo_texcoord && let Some(texcoords) = stexcoords { + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_texcoord)); ctx.gl.buffer_data_u8_slice( glow::ARRAY_BUFFER, std::slice::from_raw_parts( @@ -79,20 +115,47 @@ impl Mesh { ), glow::STATIC_DRAW, ); - ctx.gl.vertex_attrib_pointer_f32(ATTRIB_TEXCOORD, 2, glow::FLOAT, false, 0, 0); - ctx.gl.enable_vertex_attrib_array(ATTRIB_TEXCOORD); - } - - Self { - vao, - mode: glow::TRIANGLES, - index_count: indices.len(), - index_type: glow::UNSIGNED_INT, - index_offset: 0, - } + Some(vbo_texcoord) + } else { None }; + self.index_count = indices.len(); } } + pub fn build( + ctx: &context::Context, + vertices: &[f32], + indices: &[u32], + snormals: Option<&[f32]>, + stexcoords: Option<&[f32]>, + ) -> Self { + let mut ret = Self::new_empty(ctx, snormals.is_some(), stexcoords.is_some()); + ret.upload(ctx, vertices, indices, snormals, stexcoords); + ret + } + + pub fn upload_obj(&mut self, ctx: &context::Context, mut bytes: &[u8]) { + let lopts = tobj::LoadOptions { + triangulate: true, + single_index: true, + ..Default::default() + }; + let (meshes, _materials) = tobj::load_obj_buf( + &mut bytes, + &lopts, + |_| Err(tobj::LoadError::GenericFailure) + ).expect("failed to load mesh"); + let mesh = meshes.into_iter().next() + .expect("failed to load mesh") + .mesh; + self.upload( + ctx, + &mesh.positions, + &mesh.indices, + Some(&mesh.normals), + Some(&mesh.texcoords), + ) + } + pub fn from_obj(ctx: &context::Context, mut bytes: &[u8]) -> Self { let lopts = tobj::LoadOptions { triangulate: true, diff --git a/crates/teleia/src/scene.rs b/crates/teleia/src/scene.rs index 0c1c25e..d00f098 100644 --- a/crates/teleia/src/scene.rs +++ b/crates/teleia/src/scene.rs @@ -199,6 +199,10 @@ impl Scene { Primitive { mesh: mesh::Mesh { vao, + vbo_vertex: vertices_buf, + vbo_index: indices_buf, + vbo_normal: None, + vbo_texcoord: None, mode, index_count: indices.len(), index_type: glow::UNSIGNED_INT, diff --git a/crates/teleia_macros/src/lib.rs b/crates/teleia_macros/src/lib.rs index d8ee109..c780154 100644 --- a/crates/teleia_macros/src/lib.rs +++ b/crates/teleia_macros/src/lib.rs @@ -6,10 +6,11 @@ use heck::ToUpperCamelCase; #[derive(Debug, Hash, PartialEq, Eq)] struct Designator { + path: String, parts: Vec<String>, } impl Designator { - fn new(fbase: &str, path: &Path, shorten: bool) -> Self { + fn new(fbase: &str, mut path: &Path, shorten: bool) -> Self { let mut parts: Vec<_> = path.strip_prefix(fbase).unwrap().with_extension("").components() .filter_map(|c| match c { std::path::Component::Normal(o) => Some(o.to_str().unwrap().to_owned()), @@ -18,13 +19,27 @@ impl Designator { .collect(); if shorten { parts.pop(); + path = path.parent().expect("path has no parent"); } Self { + path: path.to_str().expect("path is not a string").to_owned(), parts } } - fn enum_entry(&self, _fnm: &str) -> String { - self.parts.join(" ").to_upper_camel_case().to_string() + fn enum_entry(&self, fnm: &str) -> String { + let singular = match fnm { + "meshes" => "mesh", + "textures" => "texture", + "materials" => "material", + "shaders" => "shader", + _ => fnm, + }; + let mut ret = format!("\n#[doc=\"newton-{}: {}\"]\n", singular, self.path); + ret += &self.parts.join(" ").to_upper_camel_case(); + ret + } + fn enum_element(&self, _fnm: &str) -> String { + self.parts.join(" ").to_upper_camel_case() } fn load_expr(&self, fnm: &str) -> Option<String> { let i = format!("assets/{}/{}", fnm, self.parts.join("/")); @@ -71,7 +86,7 @@ impl Field { let mut ents = Vec::new(); for d in self.entries.iter() { if let Some(exp) = d.load_expr(&self.nm) { - ents.push((d.enum_entry(&self.nm), exp)); + ents.push((d.enum_entry(&self.nm), d.enum_element(&self.nm), exp)); } } let (enm, ty) = match self.nm.as_str() { @@ -81,11 +96,11 @@ impl Field { "shaders" => ("Shader", "teleia::shader::Shader"), _ => return None, }; - let enums: Vec<_> = ents.iter().map(|(e, _)| e.clone()).collect(); + let enums: Vec<_> = ents.iter().map(|(e, _, _)| e.clone()).collect(); let edecl = format!("#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, enum_map::Enum)] pub enum {} {{ {} }}", enm, enums.join(", ")); let decl = format!("pub {}: enum_map::EnumMap<{}, {}>", self.nm, enm, ty); - let inits: Vec<_> = ents.into_iter().map(|(e, exp)| format!("{}::{} => {}", enm, e, exp)).collect(); + let inits: Vec<_> = ents.into_iter().map(|(_, e, exp)| format!("{}::{} => {}", enm, e, exp)).collect(); let init = format!("{}: enum_map::enum_map!({})", self.nm, inits.join(", ")); Some((edecl, decl, init)) } |
