oxihuman_export/
collision_shape_export.rs1#![allow(dead_code)]
4
5use std::f32::consts::PI;
8
9#[allow(dead_code)]
11#[derive(Debug, Clone, PartialEq)]
12pub enum CollisionShapeType {
13 Sphere,
14 Box,
15 Capsule,
16 ConvexHull,
17 Mesh,
18}
19
20#[allow(dead_code)]
22#[derive(Debug, Clone)]
23pub struct CollisionShapeExport {
24 pub shape_type: CollisionShapeType,
25 pub name: String,
26 pub position: [f32; 3],
27 pub rotation: [f32; 4],
28 pub scale: [f32; 3],
29 pub params: [f32; 4],
30}
31
32#[allow(dead_code)]
34#[derive(Debug, Clone)]
35pub struct CollisionShapeBundle {
36 pub shapes: Vec<CollisionShapeExport>,
37}
38
39#[allow(dead_code)]
41pub fn sphere_collision(name: &str, center: [f32; 3], radius: f32) -> CollisionShapeExport {
42 CollisionShapeExport {
43 shape_type: CollisionShapeType::Sphere,
44 name: name.to_string(),
45 position: center,
46 rotation: [0.0, 0.0, 0.0, 1.0],
47 scale: [1.0; 3],
48 params: [radius, 0.0, 0.0, 0.0],
49 }
50}
51
52#[allow(dead_code)]
54pub fn box_collision(name: &str, center: [f32; 3], half_extents: [f32; 3]) -> CollisionShapeExport {
55 CollisionShapeExport {
56 shape_type: CollisionShapeType::Box,
57 name: name.to_string(),
58 position: center,
59 rotation: [0.0, 0.0, 0.0, 1.0],
60 scale: [1.0; 3],
61 params: [half_extents[0], half_extents[1], half_extents[2], 0.0],
62 }
63}
64
65#[allow(dead_code)]
67pub fn new_collision_bundle() -> CollisionShapeBundle {
68 CollisionShapeBundle { shapes: Vec::new() }
69}
70
71#[allow(dead_code)]
73pub fn add_collision_shape(bundle: &mut CollisionShapeBundle, shape: CollisionShapeExport) {
74 bundle.shapes.push(shape);
75}
76
77#[allow(dead_code)]
79pub fn collision_shape_count(bundle: &CollisionShapeBundle) -> usize {
80 bundle.shapes.len()
81}
82
83#[allow(dead_code)]
85pub fn shape_volume(shape: &CollisionShapeExport) -> f32 {
86 match shape.shape_type {
87 CollisionShapeType::Sphere => (4.0 / 3.0) * PI * shape.params[0].powi(3),
88 CollisionShapeType::Box => 8.0 * shape.params[0] * shape.params[1] * shape.params[2],
89 _ => 0.0,
90 }
91}
92
93#[allow(dead_code)]
95pub fn validate_collision_bundle(bundle: &CollisionShapeBundle) -> bool {
96 bundle.shapes.iter().all(|s| !s.name.is_empty())
97}
98
99#[allow(dead_code)]
101pub fn collision_bundle_to_json(bundle: &CollisionShapeBundle) -> String {
102 format!("{{\"shape_count\":{}}}", collision_shape_count(bundle))
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn test_sphere_collision() {
111 let s = sphere_collision("sphere0", [0.0; 3], 1.0);
112 assert_eq!(s.shape_type, CollisionShapeType::Sphere);
113 }
114
115 #[test]
116 fn test_box_collision() {
117 let b = box_collision("box0", [0.0; 3], [1.0, 1.0, 1.0]);
118 assert_eq!(b.shape_type, CollisionShapeType::Box);
119 }
120
121 #[test]
122 fn test_add_collision_shape() {
123 let mut bundle = new_collision_bundle();
124 add_collision_shape(&mut bundle, sphere_collision("s", [0.0; 3], 1.0));
125 assert_eq!(collision_shape_count(&bundle), 1);
126 }
127
128 #[test]
129 fn test_sphere_volume() {
130 let s = sphere_collision("s", [0.0; 3], 1.0);
131 let vol = shape_volume(&s);
132 assert!((vol - 4.0 * PI / 3.0).abs() < 1e-4);
133 }
134
135 #[test]
136 fn test_box_volume() {
137 let b = box_collision("b", [0.0; 3], [1.0, 2.0, 3.0]);
138 let vol = shape_volume(&b);
139 assert!((vol - 48.0).abs() < 1e-4);
140 }
141
142 #[test]
143 fn test_validate_bundle_valid() {
144 let mut bundle = new_collision_bundle();
145 add_collision_shape(&mut bundle, sphere_collision("s", [0.0; 3], 1.0));
146 assert!(validate_collision_bundle(&bundle));
147 }
148
149 #[test]
150 fn test_validate_bundle_empty_name() {
151 let mut bundle = new_collision_bundle();
152 add_collision_shape(&mut bundle, sphere_collision("", [0.0; 3], 1.0));
153 assert!(!validate_collision_bundle(&bundle));
154 }
155
156 #[test]
157 fn test_collision_bundle_to_json() {
158 let bundle = new_collision_bundle();
159 let j = collision_bundle_to_json(&bundle);
160 assert!(j.contains("\"shape_count\":0"));
161 }
162
163 #[test]
164 fn test_empty_bundle() {
165 let bundle = new_collision_bundle();
166 assert_eq!(collision_shape_count(&bundle), 0);
167 }
168
169 #[test]
170 fn test_pi_usage() {
171 let s = sphere_collision("s", [0.0; 3], 1.0);
173 let vol = shape_volume(&s);
174 assert!(vol > 4.0);
175 }
176}