aboutsummaryrefslogtreecommitdiff
path: root/crates/render-core/src/lib.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-02-19 13:09:18 +0300
committerValentin Popov <valentin@popov.link>2026-02-19 13:09:18 +0300
commitbb827c3928ee6fc56c04e503be9f39ae70efee67 (patch)
tree9d1af6595567517bcee3bddbcf7fefedce5dc5fe /crates/render-core/src/lib.rs
parentefab61a45c8837d3c2aaec464d8f6243fecb7a38 (diff)
downloadfparkan-bb827c3928ee6fc56c04e503be9f39ae70efee67.tar.xz
fparkan-bb827c3928ee6fc56c04e503be9f39ae70efee67.zip
feat: Refactor code structure and enhance functionality across multiple crates
Diffstat (limited to 'crates/render-core/src/lib.rs')
-rw-r--r--crates/render-core/src/lib.rs70
1 files changed, 50 insertions, 20 deletions
diff --git a/crates/render-core/src/lib.rs b/crates/render-core/src/lib.rs
index d06761a..c7a69d6 100644
--- a/crates/render-core/src/lib.rs
+++ b/crates/render-core/src/lib.rs
@@ -1,4 +1,5 @@
use msh_core::Model;
+use std::collections::HashMap;
pub const DEFAULT_UV_SCALE: f32 = 1024.0;
@@ -11,21 +12,24 @@ pub struct RenderVertex {
#[derive(Clone, Debug)]
pub struct RenderMesh {
pub vertices: Vec<RenderVertex>,
+ pub indices: Vec<u16>,
pub batch_count: usize,
+ pub index_overflow: bool,
}
impl RenderMesh {
pub fn triangle_count(&self) -> usize {
- self.vertices.len() / 3
+ self.indices.len() / 3
}
}
-/// Builds an expanded triangle list for a specific LOD/group pair.
-///
-/// The output is suitable for simple `glDrawArrays(GL_TRIANGLES, ...)` paths.
+/// Builds an indexed triangle mesh for a specific LOD/group pair.
pub fn build_render_mesh(model: &Model, lod: usize, group: usize) -> RenderMesh {
let mut vertices = Vec::new();
+ let mut indices = Vec::new();
+ let mut index_remap: HashMap<usize, u16> = HashMap::new();
let mut batch_count = 0usize;
+ let mut index_overflow = false;
let uv0 = model.uv0.as_ref();
for node_index in 0..model.node_count {
@@ -49,36 +53,62 @@ pub fn build_render_mesh(model: &Model, lod: usize, group: usize) -> RenderMesh
continue;
}
+ let batch_out_start = indices.len();
+ let mut batch_valid = true;
for &idx in &model.indices[index_start..index_end] {
let final_idx_u64 = u64::from(batch.base_vertex).saturating_add(u64::from(idx));
let Ok(final_idx) = usize::try_from(final_idx_u64) else {
- continue;
+ batch_valid = false;
+ break;
};
let Some(pos) = model.positions.get(final_idx) else {
- continue;
+ batch_valid = false;
+ break;
};
- let uv = uv0
- .and_then(|uvs| uvs.get(final_idx))
- .copied()
- .map(|packed| {
- [
- packed[0] as f32 / DEFAULT_UV_SCALE,
- packed[1] as f32 / DEFAULT_UV_SCALE,
- ]
- })
- .unwrap_or([0.0, 0.0]);
- vertices.push(RenderVertex {
- position: *pos,
- uv0: uv,
- });
+
+ let local_index = if let Some(&mapped) = index_remap.get(&final_idx) {
+ mapped
+ } else {
+ let Ok(mapped) = u16::try_from(vertices.len()) else {
+ index_overflow = true;
+ batch_valid = false;
+ break;
+ };
+ let uv = uv0
+ .and_then(|uvs| uvs.get(final_idx))
+ .copied()
+ .map(|packed| {
+ [
+ packed[0] as f32 / DEFAULT_UV_SCALE,
+ packed[1] as f32 / DEFAULT_UV_SCALE,
+ ]
+ })
+ .unwrap_or([0.0, 0.0]);
+ vertices.push(RenderVertex {
+ position: *pos,
+ uv0: uv,
+ });
+ index_remap.insert(final_idx, mapped);
+ mapped
+ };
+
+ indices.push(local_index);
}
+
+ if !batch_valid {
+ indices.truncate(batch_out_start);
+ continue;
+ }
+
batch_count += 1;
}
}
RenderMesh {
vertices,
+ indices,
batch_count,
+ index_overflow,
}
}