#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ImportedMorph {
pub name: String,
pub offsets: Vec<[f32; 3]>,
pub vertex_count: usize,
}
#[allow(dead_code)]
pub fn parse_morph_csv(csv: &str) -> Option<ImportedMorph> {
let mut name = String::new();
let mut offsets: Vec<[f32; 3]> = Vec::new();
for line in csv.lines() {
let parts: Vec<&str> = line.splitn(5, ',').collect();
if parts.len() < 5 {
continue;
}
if name.is_empty() {
name = parts[0].trim().to_string();
}
let x = parts[2].trim().parse::<f32>().ok()?;
let y = parts[3].trim().parse::<f32>().ok()?;
let z = parts[4].trim().parse::<f32>().ok()?;
offsets.push([x, y, z]);
}
if name.is_empty() {
return None;
}
let vc = offsets.len();
Some(ImportedMorph { name, offsets, vertex_count: vc })
}
#[allow(dead_code)]
pub fn morph_from_offsets(name: &str, offsets: Vec<[f32; 3]>) -> ImportedMorph {
let vc = offsets.len();
ImportedMorph { name: name.to_string(), offsets, vertex_count: vc }
}
#[allow(dead_code)]
pub fn morph_max_offset(m: &ImportedMorph) -> f32 {
m.offsets
.iter()
.map(|o| (o[0] * o[0] + o[1] * o[1] + o[2] * o[2]).sqrt())
.fold(0.0f32, f32::max)
}
#[allow(dead_code)]
pub fn morph_vertex_count(m: &ImportedMorph) -> usize {
m.vertex_count
}
#[allow(dead_code)]
pub fn validate_morph(m: &ImportedMorph, mesh_verts: usize) -> bool {
m.vertex_count == mesh_verts
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn morph_from_offsets_sets_fields() {
let m = morph_from_offsets("test", vec![[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]);
assert_eq!(m.name, "test");
assert_eq!(m.vertex_count, 2);
}
#[test]
fn morph_vertex_count_matches() {
let m = morph_from_offsets("m", vec![[0.0; 3]; 5]);
assert_eq!(morph_vertex_count(&m), 5);
}
#[test]
fn morph_max_offset_zero() {
let m = morph_from_offsets("m", vec![[0.0; 3]; 3]);
assert!((morph_max_offset(&m)).abs() < 1e-6);
}
#[test]
fn morph_max_offset_nonzero() {
let m = morph_from_offsets("m", vec![[1.0, 0.0, 0.0], [0.0, 2.0, 0.0]]);
assert!((morph_max_offset(&m) - 2.0).abs() < 1e-5);
}
#[test]
fn validate_morph_correct() {
let m = morph_from_offsets("m", vec![[0.0; 3]; 4]);
assert!(validate_morph(&m, 4));
}
#[test]
fn validate_morph_wrong_count() {
let m = morph_from_offsets("m", vec![[0.0; 3]; 4]);
assert!(!validate_morph(&m, 3));
}
#[test]
fn parse_morph_csv_valid() {
let csv = "smile,0,0.1,0.2,0.3\nsmile,1,0.4,0.5,0.6";
let m = parse_morph_csv(csv).expect("should succeed");
assert_eq!(m.name, "smile");
assert_eq!(m.vertex_count, 2);
}
#[test]
fn parse_morph_csv_empty_returns_none() {
assert!(parse_morph_csv("").is_none());
}
#[test]
fn parse_morph_csv_bad_float_returns_none() {
let csv = "m,0,abc,0.0,0.0";
assert!(parse_morph_csv(csv).is_none());
}
#[test]
fn morph_from_offsets_empty() {
let m = morph_from_offsets("empty", vec![]);
assert_eq!(m.vertex_count, 0);
}
}