diff options
| author | Valentin Popov <valentin@popov.link> | 2026-02-19 13:09:18 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-02-19 13:09:18 +0300 |
| commit | bb827c3928ee6fc56c04e503be9f39ae70efee67 (patch) | |
| tree | 9d1af6595567517bcee3bddbcf7fefedce5dc5fe /crates/render-demo/src | |
| parent | efab61a45c8837d3c2aaec464d8f6243fecb7a38 (diff) | |
| download | fparkan-bb827c3928ee6fc56c04e503be9f39ae70efee67.tar.xz fparkan-bb827c3928ee6fc56c04e503be9f39ae70efee67.zip | |
feat: Refactor code structure and enhance functionality across multiple crates
Diffstat (limited to 'crates/render-demo/src')
| -rw-r--r-- | crates/render-demo/src/lib.rs | 15 | ||||
| -rw-r--r-- | crates/render-demo/src/main.rs | 49 |
2 files changed, 40 insertions, 24 deletions
diff --git a/crates/render-demo/src/lib.rs b/crates/render-demo/src/lib.rs index c82e055..9555151 100644 --- a/crates/render-demo/src/lib.rs +++ b/crates/render-demo/src/lib.rs @@ -435,23 +435,10 @@ fn decode_texture_entry(archive: &Archive, entry: EntryRef<'_>) -> Result<Loaded #[cfg(test)] mod tests { use super::*; + use common::collect_files_recursive; use std::fs; use std::path::{Path, PathBuf}; - fn collect_files_recursive(root: &Path, out: &mut Vec<PathBuf>) { - let Ok(entries) = fs::read_dir(root) else { - return; - }; - for entry in entries.flatten() { - let path = entry.path(); - if path.is_dir() { - collect_files_recursive(&path, out); - } else if path.is_file() { - out.push(path); - } - } - } - fn archive_with_msh() -> Option<PathBuf> { let root = Path::new(env!("CARGO_MANIFEST_DIR")) .join("..") diff --git a/crates/render-demo/src/main.rs b/crates/render-demo/src/main.rs index 8d309d1..70f2209 100644 --- a/crates/render-demo/src/main.rs +++ b/crates/render-demo/src/main.rs @@ -221,12 +221,17 @@ fn run(args: Args) -> Result<(), String> { ) })?; let mesh = build_render_mesh(&loaded_model.model, args.lod, args.group); - if mesh.vertices.is_empty() { + if mesh.indices.is_empty() { return Err(format!( "model has no renderable triangles for lod={} group={}", args.lod, args.group )); } + if mesh.index_overflow { + eprintln!( + "warning: mesh exceeds u16 index space and may be partially rendered on GLES2 targets" + ); + } let Some((bounds_min, bounds_max)) = compute_bounds_for_mesh(&mesh.vertices) else { return Err(String::from("failed to compute mesh bounds")); }; @@ -304,6 +309,7 @@ fn run(args: Args) -> Result<(), String> { vertex_data.push(vertex.uv0[1]); } let vertex_bytes = f32_slice_to_ne_bytes(&vertex_data); + let index_bytes = u16_slice_to_ne_bytes(&mesh.indices); let gl = unsafe { glow::Context::from_loader_function(|name| video.gl_get_proc_address(name) as *const _) @@ -319,9 +325,13 @@ fn run(args: Args) -> Result<(), String> { .ok_or_else(|| String::from("shader attribute a_uv is missing"))?; let vbo = unsafe { gl.create_buffer().map_err(|e| e.to_string())? }; + let ebo = unsafe { gl.create_buffer().map_err(|e| e.to_string())? }; unsafe { gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo)); gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, &vertex_bytes, glow::STATIC_DRAW); + gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ebo)); + gl.buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER, &index_bytes, glow::STATIC_DRAW); + gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None); gl.bind_buffer(glow::ARRAY_BUFFER, None); } @@ -341,8 +351,9 @@ fn run(args: Args) -> Result<(), String> { a_pos, a_uv, vbo, + ebo, gpu_texture.as_ref(), - mesh.vertices.len(), + mesh.indices.len(), &args, center, camera_distance, @@ -360,8 +371,9 @@ fn run(args: Args) -> Result<(), String> { a_pos, a_uv, vbo, + ebo, gpu_texture.as_ref(), - mesh.vertices.len(), + mesh.indices.len(), &args, center, camera_distance, @@ -372,6 +384,7 @@ fn run(args: Args) -> Result<(), String> { if let Some(texture) = gpu_texture { gl.delete_texture(texture.handle); } + gl.delete_buffer(ebo); gl.delete_buffer(vbo); gl.delete_program(program); } @@ -452,8 +465,9 @@ fn run_capture( a_pos: u32, a_uv: u32, vbo: glow::NativeBuffer, + ebo: glow::NativeBuffer, texture: Option<&GpuTexture>, - vertex_count: usize, + index_count: usize, args: &Args, center: [f32; 3], camera_distance: f32, @@ -478,8 +492,9 @@ fn run_capture( a_pos, a_uv, vbo, + ebo, texture, - vertex_count, + index_count, args.width, args.height, &mvp, @@ -504,8 +519,9 @@ fn run_interactive( a_pos: u32, a_uv: u32, vbo: glow::NativeBuffer, + ebo: glow::NativeBuffer, texture: Option<&GpuTexture>, - vertex_count: usize, + index_count: usize, args: &Args, center: [f32; 3], camera_distance: f32, @@ -543,8 +559,9 @@ fn run_interactive( a_pos, a_uv, vbo, + ebo, texture, - vertex_count, + index_count, w, h, &mvp, @@ -584,8 +601,9 @@ unsafe fn draw_frame( a_pos: u32, a_uv: u32, vbo: glow::NativeBuffer, + ebo: glow::NativeBuffer, texture: Option<&GpuTexture>, - vertex_count: usize, + index_count: usize, width: u32, height: u32, mvp: &[f32; 16], @@ -614,17 +632,20 @@ unsafe fn draw_frame( } gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo)); + gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ebo)); gl.enable_vertex_attrib_array(a_pos); gl.vertex_attrib_pointer_f32(a_pos, 3, glow::FLOAT, false, 20, 0); gl.enable_vertex_attrib_array(a_uv); gl.vertex_attrib_pointer_f32(a_uv, 2, glow::FLOAT, false, 20, 12); - gl.draw_arrays( + gl.draw_elements( glow::TRIANGLES, + index_count.min(i32::MAX as usize) as i32, + glow::UNSIGNED_SHORT, 0, - vertex_count.min(i32::MAX as usize) as i32, ); gl.disable_vertex_attrib_array(a_uv); gl.disable_vertex_attrib_array(a_pos); + gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None); gl.bind_buffer(glow::ARRAY_BUFFER, None); gl.bind_texture(glow::TEXTURE_2D, None); gl.use_program(None); @@ -758,6 +779,14 @@ fn f32_slice_to_ne_bytes(slice: &[f32]) -> Vec<u8> { out } +fn u16_slice_to_ne_bytes(slice: &[u16]) -> Vec<u8> { + let mut out = Vec::with_capacity(slice.len().saturating_mul(std::mem::size_of::<u16>())); + for &value in slice { + out.extend_from_slice(&value.to_ne_bytes()); + } + out +} + fn mat4_identity() -> [f32; 16] { [ 1.0, 0.0, 0.0, 0.0, // |
