Skip to main content

oxihuman_export/
three_js_export.rs

1#![allow(dead_code)]
2// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
3// SPDX-License-Identifier: Apache-2.0
4
5//! Export Three.js scene format.
6
7#[allow(dead_code)]
8pub struct ThreeJsGeometry {
9    pub uuid: String,
10    pub vertices: Vec<f32>,
11    pub faces: Vec<u32>,
12}
13
14#[allow(dead_code)]
15pub struct ThreeJsObject {
16    pub name: String,
17    pub geometry_uuid: String,
18    pub position: [f32; 3],
19}
20
21#[allow(dead_code)]
22pub struct ThreeJsScene {
23    pub objects: Vec<ThreeJsObject>,
24    pub geometries: Vec<ThreeJsGeometry>,
25}
26
27#[allow(dead_code)]
28pub fn new_three_js_scene() -> ThreeJsScene {
29    ThreeJsScene {
30        objects: Vec::new(),
31        geometries: Vec::new(),
32    }
33}
34
35#[allow(dead_code)]
36pub fn add_geometry(scene: &mut ThreeJsScene, uuid: &str, verts: Vec<f32>, faces: Vec<u32>) {
37    scene.geometries.push(ThreeJsGeometry {
38        uuid: uuid.to_string(),
39        vertices: verts,
40        faces,
41    });
42}
43
44#[allow(dead_code)]
45pub fn add_object(scene: &mut ThreeJsScene, name: &str, geo_uuid: &str, pos: [f32; 3]) {
46    scene.objects.push(ThreeJsObject {
47        name: name.to_string(),
48        geometry_uuid: geo_uuid.to_string(),
49        position: pos,
50    });
51}
52
53#[allow(dead_code)]
54pub fn export_threejs_to_json(scene: &ThreeJsScene) -> String {
55    let mut s = "{\"geometries\":[".to_string();
56    for (i, g) in scene.geometries.iter().enumerate() {
57        if i > 0 {
58            s.push(',');
59        }
60        s.push_str(&format!(
61            "{{\"uuid\":\"{}\",\"vertex_count\":{},\"face_count\":{}}}",
62            g.uuid,
63            g.vertices.len(),
64            g.faces.len()
65        ));
66    }
67    s.push_str("],\"objects\":[");
68    for (i, o) in scene.objects.iter().enumerate() {
69        if i > 0 {
70            s.push(',');
71        }
72        s.push_str(&format!(
73            "{{\"name\":\"{}\",\"geometry\":\"{}\",\"position\":[{},{},{}]}}",
74            o.name, o.geometry_uuid, o.position[0], o.position[1], o.position[2]
75        ));
76    }
77    s.push_str("]}");
78    s
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn new_scene_empty() {
87        let s = new_three_js_scene();
88        assert!(s.objects.is_empty());
89        assert!(s.geometries.is_empty());
90    }
91
92    #[test]
93    fn add_geometry_stored() {
94        let mut s = new_three_js_scene();
95        add_geometry(&mut s, "uuid-1", vec![0.0, 0.0, 0.0], vec![0, 1, 2]);
96        assert_eq!(s.geometries.len(), 1);
97    }
98
99    #[test]
100    fn geometry_uuid_stored() {
101        let mut s = new_three_js_scene();
102        add_geometry(&mut s, "my-uuid", vec![], vec![]);
103        assert_eq!(s.geometries[0].uuid, "my-uuid");
104    }
105
106    #[test]
107    fn add_object_stored() {
108        let mut s = new_three_js_scene();
109        add_object(&mut s, "mesh1", "uuid-1", [0.0, 0.0, 0.0]);
110        assert_eq!(s.objects.len(), 1);
111    }
112
113    #[test]
114    fn object_position_stored() {
115        let mut s = new_three_js_scene();
116        add_object(&mut s, "o", "u", [1.0, 2.0, 3.0]);
117        assert!((s.objects[0].position[2] - 3.0).abs() < 1e-6);
118    }
119
120    #[test]
121    fn export_json_contains_uuid() {
122        let mut s = new_three_js_scene();
123        add_geometry(&mut s, "test-geo-uuid", vec![], vec![]);
124        let j = export_threejs_to_json(&s);
125        assert!(j.contains("test-geo-uuid"));
126    }
127
128    #[test]
129    fn export_json_contains_object_name() {
130        let mut s = new_three_js_scene();
131        add_object(&mut s, "MyMesh", "u", [0.0, 0.0, 0.0]);
132        let j = export_threejs_to_json(&s);
133        assert!(j.contains("MyMesh"));
134    }
135
136    #[test]
137    fn geometry_vertices_stored() {
138        let mut s = new_three_js_scene();
139        add_geometry(&mut s, "u", vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], vec![]);
140        assert_eq!(s.geometries[0].vertices.len(), 6);
141    }
142
143    #[test]
144    fn geometry_faces_stored() {
145        let mut s = new_three_js_scene();
146        add_geometry(&mut s, "u", vec![], vec![0, 1, 2]);
147        assert_eq!(s.geometries[0].faces.len(), 3);
148    }
149}