#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Default)]
pub struct FaceVertexExport {
pub positions: Vec<[f32; 3]>,
pub normals: Vec<[f32; 3]>,
pub uvs: Vec<[f32; 2]>,
pub face_vertex_indices: Vec<u32>,
pub face_sizes: Vec<usize>,
}
#[allow(dead_code)]
pub fn new_face_vertex_export() -> FaceVertexExport {
FaceVertexExport::default()
}
#[allow(dead_code)]
pub fn fv_add_vertex(export: &mut FaceVertexExport, pos: [f32; 3], normal: [f32; 3], uv: [f32; 2]) {
export.positions.push(pos);
export.normals.push(normal);
export.uvs.push(uv);
}
#[allow(dead_code)]
pub fn fv_add_face(export: &mut FaceVertexExport, indices: &[u32]) {
export.face_vertex_indices.extend_from_slice(indices);
export.face_sizes.push(indices.len());
}
#[allow(dead_code)]
pub fn fv_vertex_count(export: &FaceVertexExport) -> usize {
export.positions.len()
}
#[allow(dead_code)]
pub fn fv_face_count(export: &FaceVertexExport) -> usize {
export.face_sizes.len()
}
#[allow(dead_code)]
pub fn fv_avg_face_size(export: &FaceVertexExport) -> f32 {
if export.face_sizes.is_empty() {
return 0.0;
}
export.face_sizes.iter().sum::<usize>() as f32 / export.face_sizes.len() as f32
}
#[allow(dead_code)]
pub fn fv_indices_valid(export: &FaceVertexExport) -> bool {
let n = export.positions.len() as u32;
export.face_vertex_indices.iter().all(|&i| i < n)
}
#[allow(dead_code)]
pub fn fv_normals_unit(export: &FaceVertexExport) -> bool {
export.normals.iter().all(|n| {
let len = (n[0] * n[0] + n[1] * n[1] + n[2] * n[2]).sqrt();
(len - 1.0).abs() < 1e-3
})
}
#[allow(dead_code)]
pub fn face_vertex_to_json(export: &FaceVertexExport) -> String {
format!(
r#"{{"vertices":{},"faces":{}}}"#,
export.positions.len(),
export.face_sizes.len()
)
}
#[allow(dead_code)]
pub fn fv_to_triangles(export: &FaceVertexExport) -> Vec<u32> {
let mut tris = Vec::new();
let mut offset = 0;
for &size in &export.face_sizes {
if size >= 3 {
let base = export.face_vertex_indices[offset];
for i in 1..(size - 1) {
tris.push(base);
tris.push(export.face_vertex_indices[offset + i]);
tris.push(export.face_vertex_indices[offset + i + 1]);
}
}
offset += size;
}
tris
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_vertex_count() {
let mut e = new_face_vertex_export();
fv_add_vertex(&mut e, [0.0; 3], [0.0, 1.0, 0.0], [0.0; 2]);
assert_eq!(fv_vertex_count(&e), 1);
}
#[test]
fn add_face_count() {
let mut e = new_face_vertex_export();
for _ in 0..3 {
fv_add_vertex(&mut e, [0.0; 3], [0.0, 1.0, 0.0], [0.0; 2]);
}
fv_add_face(&mut e, &[0, 1, 2]);
assert_eq!(fv_face_count(&e), 1);
}
#[test]
fn avg_face_size_triangle() {
let mut e = new_face_vertex_export();
for _ in 0..3 {
fv_add_vertex(&mut e, [0.0; 3], [0.0, 1.0, 0.0], [0.0; 2]);
}
fv_add_face(&mut e, &[0, 1, 2]);
assert!((fv_avg_face_size(&e) - 3.0).abs() < 1e-5);
}
#[test]
fn indices_valid() {
let mut e = new_face_vertex_export();
for _ in 0..3 {
fv_add_vertex(&mut e, [0.0; 3], [0.0, 1.0, 0.0], [0.0; 2]);
}
fv_add_face(&mut e, &[0, 1, 2]);
assert!(fv_indices_valid(&e));
}
#[test]
fn to_triangles_count() {
let mut e = new_face_vertex_export();
for _ in 0..4 {
fv_add_vertex(&mut e, [0.0; 3], [0.0, 1.0, 0.0], [0.0; 2]);
}
fv_add_face(&mut e, &[0, 1, 2, 3]); let tris = fv_to_triangles(&e);
assert_eq!(tris.len(), 6);
}
#[test]
fn json_has_vertices() {
let e = new_face_vertex_export();
let j = face_vertex_to_json(&e);
assert!(j.contains("\"vertices\":0"));
}
#[test]
fn empty_avg_size() {
let e = new_face_vertex_export();
assert!((fv_avg_face_size(&e) - 0.0).abs() < 1e-6);
}
#[test]
fn normals_unit_check() {
let mut e = new_face_vertex_export();
fv_add_vertex(&mut e, [0.0; 3], [0.0, 1.0, 0.0], [0.0; 2]);
assert!(fv_normals_unit(&e));
}
#[test]
fn normals_not_unit() {
let mut e = new_face_vertex_export();
fv_add_vertex(&mut e, [0.0; 3], [0.0, 0.0, 0.0], [0.0; 2]);
assert!(!fv_normals_unit(&e));
}
#[test]
fn tris_divisible_by_3() {
let mut e = new_face_vertex_export();
for _ in 0..3 {
fv_add_vertex(&mut e, [0.0; 3], [0.0, 1.0, 0.0], [0.0; 2]);
}
fv_add_face(&mut e, &[0, 1, 2]);
let tris = fv_to_triangles(&e);
assert_eq!(tris.len() % 3, 0);
}
}