Files
OneCAD-Draft/src/io/stl.rs
T
Hakan SevenandClaude Opus 4.7 ef1f9a08d6 chore: rename H7CAD to Open CAD Studio
Joining the OpenAEC Foundation (open-aec.com). Crate/struct become
OpenCADStudio, user-facing strings use the spaced "Open CAD Studio"
form, repo URLs point to HakanSeven12/open-cad-studio. Logo (window
icon + assets/logo.svg) redrawn with OCS initials. Drop examples/
binaries — unused.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 17:16:15 +03:00

94 lines
2.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// STL binary export — converts all tessellated MeshModels in the scene to a
// single binary STL file.
//
// Binary STL format:
// 80-byte header
// 4-byte triangle count (u32 LE)
// Per triangle (50 bytes):
// 3 × f32 normal
// 3 × 3 × f32 vertices
// 2-byte attribute (0)
use std::io::Write;
use crate::scene::mesh_model::MeshModel;
/// Build a binary STL byte buffer from a slice of mesh models.
/// Returns `None` if there are no triangles to export.
pub fn build_stl(meshes: &[&MeshModel]) -> Option<Vec<u8>> {
// Collect all triangles.
struct Tri {
normal: [f32; 3],
v: [[f32; 3]; 3],
}
let mut tris: Vec<Tri> = Vec::new();
for mesh in meshes {
let verts = &mesh.verts;
let idx = &mesh.indices;
let n_tri = idx.len() / 3;
for t in 0..n_tri {
let i0 = idx[t * 3] as usize;
let i1 = idx[t * 3 + 1] as usize;
let i2 = idx[t * 3 + 2] as usize;
if i0 >= verts.len() || i1 >= verts.len() || i2 >= verts.len() {
continue;
}
let a = verts[i0];
let b = verts[i1];
let c = verts[i2];
// Compute face normal.
let normal = if !mesh.normals.is_empty() && i0 < mesh.normals.len() {
mesh.normals[i0]
} else {
let ab = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];
let ac = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];
let nx = ab[1] * ac[2] - ab[2] * ac[1];
let ny = ab[2] * ac[0] - ab[0] * ac[2];
let nz = ab[0] * ac[1] - ab[1] * ac[0];
let len = (nx * nx + ny * ny + nz * nz).sqrt().max(f32::EPSILON);
[nx / len, ny / len, nz / len]
};
tris.push(Tri {
normal,
v: [a, b, c],
});
}
}
if tris.is_empty() {
return None;
}
let mut buf: Vec<u8> = Vec::with_capacity(84 + tris.len() * 50);
// 80-byte header.
let mut header = [0u8; 80];
let title = b"Open CAD Studio STL export";
header[..title.len()].copy_from_slice(title);
buf.extend_from_slice(&header);
// Triangle count.
buf.extend_from_slice(&(tris.len() as u32).to_le_bytes());
for tri in &tris {
// Normal.
for &f in &tri.normal {
buf.write_all(&f.to_le_bytes()).ok()?;
}
// Vertices.
for v in &tri.v {
for &f in v {
buf.write_all(&f.to_le_bytes()).ok()?;
}
}
// Attribute byte count = 0.
buf.extend_from_slice(&0u16.to_le_bytes());
}
Some(buf)
}