aboutsummaryrefslogtreecommitdiff
path: root/crates/render-core/src/tests.rs
blob: 9c5eb5d3462b21de1c9284b3f7af1699c7cf1b9b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use super::*;
use msh_core::parse_model_payload;
use nres::Archive;
use std::fs;
use std::path::{Path, PathBuf};

fn collect_files_recursive(root: &Path, out: &mut Vec<PathBuf>) {
    let Ok(entries) = fs::read_dir(root) else {
        return;
    };
    for entry in entries.flatten() {
        let path = entry.path();
        if path.is_dir() {
            collect_files_recursive(&path, out);
        } else if path.is_file() {
            out.push(path);
        }
    }
}

fn nres_test_files() -> Vec<PathBuf> {
    let root = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("..")
        .join("..")
        .join("testdata");
    let mut files = Vec::new();
    collect_files_recursive(&root, &mut files);
    files.sort();
    files
        .into_iter()
        .filter(|path| {
            fs::read(path)
                .map(|bytes| bytes.get(0..4) == Some(b"NRes"))
                .unwrap_or(false)
        })
        .collect()
}

#[test]
fn build_render_mesh_for_real_models() {
    let archives = nres_test_files();
    if archives.is_empty() {
        eprintln!("skipping build_render_mesh_for_real_models: no NRes files in testdata");
        return;
    }

    let mut models_checked = 0usize;
    let mut meshes_non_empty = 0usize;
    let mut bounds_non_empty = 0usize;

    for archive_path in archives {
        let archive = Archive::open_path(&archive_path)
            .unwrap_or_else(|err| panic!("failed to open {}: {err}", archive_path.display()));
        for entry in archive.entries() {
            if !entry.meta.name.to_ascii_lowercase().ends_with(".msh") {
                continue;
            }
            models_checked += 1;
            let payload = archive.read(entry.id).unwrap_or_else(|err| {
                panic!(
                    "failed to read model '{}' from {}: {err}",
                    entry.meta.name,
                    archive_path.display()
                )
            });
            let model = parse_model_payload(payload.as_slice()).unwrap_or_else(|err| {
                panic!(
                    "failed to parse model '{}' from {}: {err}",
                    entry.meta.name,
                    archive_path.display()
                )
            });
            let mesh = build_render_mesh(&model, 0, 0);
            if !mesh.vertices.is_empty() {
                meshes_non_empty += 1;
            }
            if compute_bounds(&mesh.vertices).is_some() {
                bounds_non_empty += 1;
            }
        }
    }

    assert!(models_checked > 0, "no MSH models found");
    assert!(
        meshes_non_empty > 0,
        "all generated render meshes are empty"
    );
    assert_eq!(
        meshes_non_empty, bounds_non_empty,
        "bounds must be available for every non-empty mesh"
    );
}

#[test]
fn compute_bounds_handles_empty_and_non_empty() {
    assert!(compute_bounds(&[]).is_none());
    let bounds = compute_bounds(&[[1.0, 2.0, 3.0], [-2.0, 5.0, 0.5], [0.0, -1.0, 9.0]])
        .expect("bounds expected");
    assert_eq!(bounds.0, [-2.0, -1.0, 0.5]);
    assert_eq!(bounds.1, [1.0, 5.0, 9.0]);
}