schematic_mesher/export/
raw.rs

1//! Raw mesh data export for custom rendering.
2
3use crate::mesher::MesherOutput;
4
5/// Raw mesh data for custom use.
6#[derive(Debug)]
7pub struct RawMeshData {
8    /// Vertex positions (3 floats per vertex).
9    pub positions: Vec<[f32; 3]>,
10    /// Vertex normals (3 floats per vertex).
11    pub normals: Vec<[f32; 3]>,
12    /// Texture coordinates (2 floats per vertex).
13    pub uvs: Vec<[f32; 2]>,
14    /// Vertex colors (4 floats per vertex, RGBA).
15    pub colors: Vec<[f32; 4]>,
16    /// Triangle indices (3 per triangle).
17    pub indices: Vec<u32>,
18    /// Texture atlas RGBA data.
19    pub texture_rgba: Vec<u8>,
20    /// Texture atlas width.
21    pub texture_width: u32,
22    /// Texture atlas height.
23    pub texture_height: u32,
24}
25
26/// Export mesh as raw data.
27/// Note: This combines opaque and transparent meshes. For separate handling,
28/// access output.opaque_mesh and output.transparent_mesh directly.
29pub fn export_raw(output: &MesherOutput) -> RawMeshData {
30    // Combine opaque and transparent meshes
31    let mesh = output.mesh();
32    let atlas = &output.atlas;
33
34    RawMeshData {
35        positions: mesh.vertices.iter().map(|v| v.position).collect(),
36        normals: mesh.vertices.iter().map(|v| v.normal).collect(),
37        uvs: mesh.vertices.iter().map(|v| v.uv).collect(),
38        colors: mesh.vertices.iter().map(|v| v.color).collect(),
39        indices: mesh.indices.clone(),
40        texture_rgba: atlas.pixels.clone(),
41        texture_width: atlas.width,
42        texture_height: atlas.height,
43    }
44}
45
46impl RawMeshData {
47    /// Get positions as a flat array.
48    pub fn positions_flat(&self) -> Vec<f32> {
49        self.positions.iter().flat_map(|p| p.iter().copied()).collect()
50    }
51
52    /// Get normals as a flat array.
53    pub fn normals_flat(&self) -> Vec<f32> {
54        self.normals.iter().flat_map(|n| n.iter().copied()).collect()
55    }
56
57    /// Get UVs as a flat array.
58    pub fn uvs_flat(&self) -> Vec<f32> {
59        self.uvs.iter().flat_map(|uv| uv.iter().copied()).collect()
60    }
61
62    /// Get colors as a flat array.
63    pub fn colors_flat(&self) -> Vec<f32> {
64        self.colors.iter().flat_map(|c| c.iter().copied()).collect()
65    }
66
67    /// Get the number of vertices.
68    pub fn vertex_count(&self) -> usize {
69        self.positions.len()
70    }
71
72    /// Get the number of triangles.
73    pub fn triangle_count(&self) -> usize {
74        self.indices.len() / 3
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use crate::atlas::TextureAtlas;
82    use crate::mesher::geometry::{Mesh, Vertex};
83    use crate::types::BoundingBox;
84
85    #[test]
86    fn test_export_raw() {
87        let mut mesh = Mesh::new();
88        mesh.add_vertex(Vertex::new([0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0]));
89        mesh.add_vertex(Vertex::new([1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 0.0]));
90        mesh.add_vertex(Vertex::new([0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [0.0, 1.0]));
91        mesh.add_triangle(0, 1, 2);
92
93        let output = MesherOutput {
94            opaque_mesh: mesh,
95            transparent_mesh: Mesh::new(),
96            atlas: TextureAtlas::empty(),
97            bounds: BoundingBox::new([0.0, 0.0, 0.0], [1.0, 0.0, 1.0]),
98        };
99
100        let raw = export_raw(&output);
101
102        assert_eq!(raw.vertex_count(), 3);
103        assert_eq!(raw.triangle_count(), 1);
104        assert_eq!(raw.positions.len(), 3);
105        assert_eq!(raw.indices.len(), 3);
106    }
107}