Skip to main content

oxiphysics_io/obj/
functions_2.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5#![allow(clippy::field_reassign_with_default)]
6
7#[allow(unused_imports)]
8use super::functions::*;
9#[allow(unused_imports)]
10use crate::obj::types::*;
11#[cfg(test)]
12mod tests_expanded {
13    use super::*;
14    #[test]
15    fn test_vertex_color_lerp() {
16        let c0 = ObjVertexColor::rgb(0.0, 0.0, 0.0);
17        let c1 = ObjVertexColor::rgb(1.0, 1.0, 1.0);
18        let mid = c0.lerp(c1, 0.5);
19        assert!((mid.r - 0.5).abs() < 1e-10);
20        assert!((mid.g - 0.5).abs() < 1e-10);
21        assert!((mid.b - 0.5).abs() < 1e-10);
22    }
23    #[test]
24    fn test_vertex_color_to_array() {
25        let c = ObjVertexColor::rgba(0.1, 0.2, 0.3, 0.4);
26        let arr = c.to_array();
27        assert!((arr[0] - 0.1).abs() < 1e-10);
28        assert!((arr[3] - 0.4).abs() < 1e-10);
29    }
30    #[test]
31    fn test_transform_identity() {
32        let t = MeshTransform::identity();
33        let p = [1.0_f64, 2.0, 3.0];
34        let out = t.apply(p);
35        assert!((out[0] - 1.0).abs() < 1e-10);
36        assert!((out[1] - 2.0).abs() < 1e-10);
37        assert!((out[2] - 3.0).abs() < 1e-10);
38    }
39    #[test]
40    fn test_transform_translation() {
41        let t = MeshTransform::from_translation(1.0, 2.0, 3.0);
42        let p = [0.0_f64, 0.0, 0.0];
43        let out = t.apply(p);
44        assert!((out[0] - 1.0).abs() < 1e-10);
45        assert!((out[1] - 2.0).abs() < 1e-10);
46        assert!((out[2] - 3.0).abs() < 1e-10);
47    }
48    #[test]
49    fn test_transform_scale() {
50        let t = MeshTransform {
51            translation: [0.0; 3],
52            scale: 2.0,
53            axis: [0.0, 0.0, 1.0],
54            angle: 0.0,
55        };
56        let p = [1.0_f64, 1.0, 1.0];
57        let out = t.apply(p);
58        assert!((out[0] - 2.0).abs() < 1e-10);
59        assert!((out[1] - 2.0).abs() < 1e-10);
60    }
61    #[test]
62    fn test_transform_rotation_z_90() {
63        let t = MeshTransform {
64            translation: [0.0; 3],
65            scale: 1.0,
66            axis: [0.0, 0.0, 1.0],
67            angle: std::f64::consts::FRAC_PI_2,
68        };
69        let p = [1.0_f64, 0.0, 0.0];
70        let out = t.apply(p);
71        assert!((out[0] - 0.0).abs() < 1e-10, "x={}", out[0]);
72        assert!((out[1] - 1.0).abs() < 1e-10, "y={}", out[1]);
73        assert!(out[2].abs() < 1e-10);
74    }
75    #[test]
76    fn test_weld_vertices_exact() {
77        let mut mesh = ObjMesh::default();
78        mesh.vertices = vec![[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [1.0, 0.0, 0.0]];
79        mesh.faces.push(ObjFace {
80            vertex_indices: vec![0, 1, 2],
81            normal_indices: None,
82            uv_indices: None,
83            smoothing_group: 0,
84            material: None,
85        });
86        let welded = weld_vertices(&mesh, 1e-9);
87        assert_eq!(welded.vertices.len(), 2, "should collapse duplicate vertex");
88    }
89    #[test]
90    fn test_weld_vertices_no_duplicates() {
91        let mut mesh = ObjMesh::default();
92        mesh.vertices = vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
93        mesh.faces.push(ObjFace {
94            vertex_indices: vec![0, 1, 2],
95            normal_indices: None,
96            uv_indices: None,
97            smoothing_group: 0,
98            material: None,
99        });
100        let welded = weld_vertices(&mesh, 1e-9);
101        assert_eq!(welded.vertices.len(), 3);
102    }
103    #[test]
104    fn test_weld_vertices_tolerance() {
105        let mut mesh = ObjMesh::default();
106        mesh.vertices = vec![[0.0, 0.0, 0.0], [0.0001, 0.0, 0.0], [1.0, 0.0, 0.0]];
107        mesh.faces.push(ObjFace {
108            vertex_indices: vec![0, 1, 2],
109            normal_indices: None,
110            uv_indices: None,
111            smoothing_group: 0,
112            material: None,
113        });
114        let welded = weld_vertices(&mesh, 0.001);
115        assert_eq!(welded.vertices.len(), 2);
116    }
117    #[test]
118    fn test_merge_obj_meshes_vertex_count() {
119        let mut a = ObjMesh::default();
120        a.vertices = vec![[0.0; 3]; 3];
121        a.faces.push(ObjFace {
122            vertex_indices: vec![0, 1, 2],
123            normal_indices: None,
124            uv_indices: None,
125            smoothing_group: 0,
126            material: None,
127        });
128        let mut b = ObjMesh::default();
129        b.vertices = vec![[1.0; 3]; 4];
130        b.faces.push(ObjFace {
131            vertex_indices: vec![0, 1, 2],
132            normal_indices: None,
133            uv_indices: None,
134            smoothing_group: 0,
135            material: None,
136        });
137        let merged = merge_obj_meshes(&a, &b);
138        assert_eq!(merged.vertices.len(), 7);
139        assert_eq!(merged.faces.len(), 2);
140        assert_eq!(merged.faces[1].vertex_indices[0], 3);
141    }
142    #[test]
143    fn test_merge_obj_meshes_empty_a() {
144        let a = ObjMesh::default();
145        let mut b = ObjMesh::default();
146        b.vertices = vec![[1.0, 2.0, 3.0]];
147        let merged = merge_obj_meshes(&a, &b);
148        assert_eq!(merged.vertices.len(), 1);
149    }
150    #[test]
151    fn test_recompute_normals_flat_triangle() {
152        let mut mesh = ObjMesh::default();
153        mesh.vertices = vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
154        mesh.faces.push(ObjFace {
155            vertex_indices: vec![0, 1, 2],
156            normal_indices: None,
157            uv_indices: None,
158            smoothing_group: 0,
159            material: None,
160        });
161        recompute_normals(&mut mesh);
162        assert_eq!(mesh.normals.len(), 3);
163        for n in &mesh.normals {
164            assert!(n[2] > 0.9, "normal should face +z: {:?}", n);
165        }
166    }
167    #[test]
168    fn test_recompute_normals_sets_face_indices() {
169        let mut mesh = ObjMesh::default();
170        mesh.vertices = vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
171        mesh.faces.push(ObjFace {
172            vertex_indices: vec![0, 1, 2],
173            normal_indices: None,
174            uv_indices: None,
175            smoothing_group: 0,
176            material: None,
177        });
178        recompute_normals(&mut mesh);
179        assert!(mesh.faces[0].normal_indices.is_some());
180        assert_eq!(mesh.faces[0].normal_indices.as_ref().unwrap(), &[0, 1, 2]);
181    }
182    #[test]
183    fn test_parse_mtl_basic() {
184        let data = "newmtl Mat1\nKd 1.0 0.0 0.0\nKs 0.5 0.5 0.5\nNs 32.0\nd 0.8\n";
185        let mats = parse_mtl(data);
186        assert_eq!(mats.len(), 1);
187        assert_eq!(mats[0].name, "Mat1");
188        assert!((mats[0].kd[0] - 1.0).abs() < 1e-10);
189        assert!((mats[0].ns - 32.0).abs() < 1e-10);
190        assert!((mats[0].dissolve - 0.8).abs() < 1e-10);
191    }
192    #[test]
193    fn test_parse_mtl_multiple_materials() {
194        let data = "newmtl A\nKd 1 0 0\nnewmtl B\nKd 0 1 0\n";
195        let mats = parse_mtl(data);
196        assert_eq!(mats.len(), 2);
197        assert_eq!(mats[0].name, "A");
198        assert_eq!(mats[1].name, "B");
199        assert!((mats[1].kd[1] - 1.0).abs() < 1e-10);
200    }
201    #[test]
202    fn test_parse_mtl_map_kd() {
203        let data = "newmtl Mat\nmap_Kd diffuse.png\n";
204        let mats = parse_mtl(data);
205        assert_eq!(mats[0].map_kd.as_deref(), Some("diffuse.png"));
206    }
207    #[test]
208    fn test_parse_mtl_transparency() {
209        let data = "newmtl Glass\nTr 0.5\n";
210        let mats = parse_mtl(data);
211        assert!((mats[0].dissolve - 0.5).abs() < 1e-10);
212    }
213    #[test]
214    fn test_parse_mtl_empty() {
215        let mats = parse_mtl("");
216        assert!(mats.is_empty());
217    }
218    #[test]
219    fn test_parse_mtl_comments() {
220        let data = "# This is a comment\nnewmtl MyMat\n# another comment\nKd 0.5 0.5 0.5\n";
221        let mats = parse_mtl(data);
222        assert_eq!(mats.len(), 1);
223        assert_eq!(mats[0].name, "MyMat");
224    }
225    #[test]
226    fn test_lod_select() {
227        let mut lod = ObjLod::new();
228        let m0 = ObjMesh::default();
229        let m1 = ObjMesh::default();
230        let m2 = ObjMesh::default();
231        lod.push(m0, 10.0);
232        lod.push(m1, 50.0);
233        lod.push(m2, 200.0);
234        assert_eq!(lod.num_levels(), 3);
235        assert!(lod.select(5.0).is_some());
236        assert!(lod.select(30.0).is_some());
237        assert!(lod.select(500.0).is_some());
238    }
239    #[test]
240    fn test_lod_decimate_keeps_target() {
241        let mut mesh = ObjMesh::default();
242        mesh.vertices = vec![[0.0; 3]; 6];
243        for i in 0..6 {
244            mesh.faces.push(ObjFace {
245                vertex_indices: vec![i % 3, (i + 1) % 3, (i + 2) % 3],
246                normal_indices: None,
247                uv_indices: None,
248                smoothing_group: 0,
249                material: None,
250            });
251        }
252        let dec = ObjLod::decimate(&mesh, 3);
253        assert!(dec.faces.len() <= 3 + 1, "decimated to roughly 3 faces");
254    }
255    #[test]
256    fn test_lod_decimate_no_change_if_under_target() {
257        let mut mesh = ObjMesh::default();
258        mesh.vertices = vec![[0.0; 3]; 3];
259        mesh.faces.push(ObjFace {
260            vertex_indices: vec![0, 1, 2],
261            normal_indices: None,
262            uv_indices: None,
263            smoothing_group: 0,
264            material: None,
265        });
266        let dec = ObjLod::decimate(&mesh, 100);
267        assert_eq!(
268            dec.faces.len(),
269            1,
270            "no decimation when already under target"
271        );
272    }
273    #[test]
274    fn test_scene_add_mesh() {
275        let mut scene = ObjScene::new();
276        let mut mesh = ObjMesh::default();
277        mesh.vertices = vec![[0.0; 3]; 3];
278        let idx = scene.add_mesh(mesh);
279        assert_eq!(idx, 0);
280        assert_eq!(scene.meshes.len(), 1);
281    }
282    #[test]
283    fn test_scene_total_vertices() {
284        let mut scene = ObjScene::new();
285        let mut m1 = ObjMesh::default();
286        m1.vertices = vec![[0.0; 3]; 4];
287        let mut m2 = ObjMesh::default();
288        m2.vertices = vec![[1.0; 3]; 6];
289        scene.add_mesh(m1);
290        scene.add_mesh(m2);
291        assert_eq!(scene.total_vertices(), 10);
292    }
293    #[test]
294    fn test_scene_flatten() {
295        let mut scene = ObjScene::new();
296        let mut mesh = ObjMesh::default();
297        mesh.vertices = vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
298        mesh.faces.push(ObjFace {
299            vertex_indices: vec![0, 1, 2],
300            normal_indices: None,
301            uv_indices: None,
302            smoothing_group: 0,
303            material: None,
304        });
305        let mi = scene.add_mesh(mesh);
306        let t = MeshTransform::from_translation(10.0, 0.0, 0.0);
307        scene.add_node("node1", Some(mi), t);
308        let flat = scene.flatten();
309        assert_eq!(flat.vertices.len(), 3);
310        assert!((flat.vertices[0][0] - 10.0).abs() < 1e-10);
311    }
312    #[test]
313    fn test_scene_add_child() {
314        let mut scene = ObjScene::new();
315        let ni0 = scene.add_node("parent", None, MeshTransform::identity());
316        let ni1 = scene.add_node("child", None, MeshTransform::identity());
317        scene.add_child(ni0, ni1);
318        assert_eq!(scene.nodes[ni0].children, vec![ni1]);
319    }
320    #[test]
321    fn test_compute_mesh_stats_basic() {
322        let mut mesh = ObjMesh::default();
323        mesh.vertices = vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
324        mesh.faces.push(ObjFace {
325            vertex_indices: vec![0, 1, 2],
326            normal_indices: None,
327            uv_indices: None,
328            smoothing_group: 0,
329            material: None,
330        });
331        let stats = compute_mesh_stats(&mesh);
332        assert_eq!(stats.vertex_count, 3);
333        assert_eq!(stats.face_count, 1);
334        assert_eq!(stats.triangle_count, 1);
335        assert!(stats.surface_area > 0.0);
336    }
337    #[test]
338    fn test_compute_mesh_stats_materials() {
339        let mut mesh = ObjMesh::default();
340        mesh.vertices = vec![[0.0; 3]; 4];
341        mesh.faces.push(ObjFace {
342            vertex_indices: vec![0, 1, 2],
343            normal_indices: None,
344            uv_indices: None,
345            smoothing_group: 0,
346            material: Some("Red".into()),
347        });
348        mesh.faces.push(ObjFace {
349            vertex_indices: vec![1, 3, 2],
350            normal_indices: None,
351            uv_indices: None,
352            smoothing_group: 0,
353            material: Some("Blue".into()),
354        });
355        let stats = compute_mesh_stats(&mesh);
356        assert_eq!(stats.material_count, 2);
357    }
358    #[test]
359    fn test_compute_mesh_stats_bbox() {
360        let mut mesh = ObjMesh::default();
361        mesh.vertices = vec![[-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]];
362        let stats = compute_mesh_stats(&mesh);
363        let (min, max) = stats.bbox.unwrap();
364        assert!((min[0] - (-1.0)).abs() < 1e-10);
365        assert!((max[0] - 1.0).abs() < 1e-10);
366    }
367    #[test]
368    fn test_vcmesh_parse_basic() {
369        let data = "v 0 0 0 1.0 0.0 0.0\nv 1 0 0 0.0 1.0 0.0\nv 0 1 0 0.0 0.0 1.0\nf 1 2 3\n";
370        let vcm = ObjVertexColorMesh::from_str(data).unwrap();
371        assert_eq!(vcm.mesh.vertices.len(), 3);
372        assert_eq!(vcm.colors.len(), 3);
373        assert!((vcm.colors[0].r - 1.0).abs() < 1e-10);
374        assert!((vcm.colors[1].g - 1.0).abs() < 1e-10);
375        assert!((vcm.colors[2].b - 1.0).abs() < 1e-10);
376    }
377    #[test]
378    fn test_vcmesh_roundtrip() {
379        let data = "v 0.0 0.0 0.0 0.5 0.5 0.5\nv 1.0 0.0 0.0 0.5 0.5 0.5\nv 0.0 1.0 0.0 0.5 0.5 0.5\nf 1 2 3\n";
380        let vcm = ObjVertexColorMesh::from_str(data).unwrap();
381        let s = vcm.to_obj_str();
382        let reparsed = ObjVertexColorMesh::from_str(&s).unwrap();
383        assert_eq!(reparsed.mesh.vertices.len(), 3);
384        assert_eq!(reparsed.mesh.faces.len(), 1);
385    }
386    #[test]
387    fn test_vcmesh_no_color_defaults_white() {
388        let data = "v 0 0 0\nv 1 0 0\nv 0 1 0\nf 1 2 3\n";
389        let vcm = ObjVertexColorMesh::from_str(data).unwrap();
390        assert_eq!(vcm.colors.len(), 3);
391        assert!((vcm.colors[0].r - 1.0).abs() < 1e-10);
392        assert!((vcm.colors[0].g - 1.0).abs() < 1e-10);
393        assert!((vcm.colors[0].b - 1.0).abs() < 1e-10);
394    }
395    #[test]
396    fn test_instantiate_mesh_translation() {
397        let mut mesh = ObjMesh::default();
398        mesh.vertices = vec![[0.0, 0.0, 0.0]];
399        let inst = MeshInstance {
400            name: "inst1".into(),
401            transform: MeshTransform::from_translation(5.0, 6.0, 7.0),
402        };
403        let out = instantiate_mesh(&mesh, &inst);
404        assert!((out.vertices[0][0] - 5.0).abs() < 1e-10);
405        assert!((out.vertices[0][1] - 6.0).abs() < 1e-10);
406        assert!((out.vertices[0][2] - 7.0).abs() < 1e-10);
407    }
408    #[test]
409    fn test_instantiate_mesh_preserves_face_count() {
410        let mut mesh = ObjMesh::default();
411        mesh.vertices = vec![[0.0; 3]; 3];
412        mesh.faces.push(ObjFace {
413            vertex_indices: vec![0, 1, 2],
414            normal_indices: None,
415            uv_indices: None,
416            smoothing_group: 0,
417            material: None,
418        });
419        let inst = MeshInstance {
420            name: "x".into(),
421            transform: MeshTransform::identity(),
422        };
423        let out = instantiate_mesh(&mesh, &inst);
424        assert_eq!(out.faces.len(), 1);
425    }
426}