box3d_rust/shape/
geometry_set.rs1use super::lifecycle::{
9 compute_shape_margin, destroy_shape_allocation_for_shape_change, get_shape,
10};
11use super::mutators::reset_proxy;
12use super::ShapeGeometry;
13use crate::geometry::{Capsule, Sphere};
14use crate::hull::{is_valid_hull, HullData};
15use crate::id::ShapeId;
16use crate::math_functions::{is_valid_vec3, safe_scale, Vec3};
17use crate::mesh::{is_valid_mesh, MeshData};
18use crate::world::World;
19use std::rc::Rc;
20
21pub fn shape_get_sphere(world: &World, shape_id: ShapeId) -> Sphere {
23 let index = get_shape(world, shape_id);
24 match &world.shapes[index as usize].geometry {
25 ShapeGeometry::Sphere(sphere) => *sphere,
26 _ => {
27 debug_assert!(false, "shape is not a sphere");
28 Sphere::default()
29 }
30 }
31}
32
33pub fn shape_get_capsule(world: &World, shape_id: ShapeId) -> Capsule {
35 let index = get_shape(world, shape_id);
36 match &world.shapes[index as usize].geometry {
37 ShapeGeometry::Capsule(capsule) => *capsule,
38 _ => {
39 debug_assert!(false, "shape is not a capsule");
40 Capsule::default()
41 }
42 }
43}
44
45pub fn shape_set_sphere(world: &mut World, shape_id: ShapeId, sphere: &Sphere) {
47 crate::recording::with_recording(world, |rec| {
48 rec.write_shape_set_sphere(shape_id, *sphere);
49 });
50 debug_assert!(!world.locked);
51 if world.locked {
52 return;
53 }
54
55 world.locked = true;
56
57 let index = get_shape(world, shape_id);
58 destroy_shape_allocation_for_shape_change(world, index);
59
60 {
61 let shape = &mut world.shapes[index as usize];
62 shape.geometry = ShapeGeometry::Sphere(*sphere);
63 shape.aabb_margin = compute_shape_margin(shape);
64 }
65
66 let wake_bodies = true;
68 let destroy_proxy = true;
69 reset_proxy(world, index, wake_bodies, destroy_proxy);
70
71 world.locked = false;
72}
73
74pub fn shape_set_capsule(world: &mut World, shape_id: ShapeId, capsule: &Capsule) {
76 crate::recording::with_recording(world, |rec| {
77 rec.write_shape_set_capsule(shape_id, *capsule);
78 });
79 debug_assert!(!world.locked);
80 if world.locked {
81 return;
82 }
83
84 world.locked = true;
85
86 let index = get_shape(world, shape_id);
87 destroy_shape_allocation_for_shape_change(world, index);
88
89 {
90 let shape = &mut world.shapes[index as usize];
91 shape.geometry = ShapeGeometry::Capsule(*capsule);
92 shape.aabb_margin = compute_shape_margin(shape);
93 }
94
95 let wake_bodies = true;
96 let destroy_proxy = true;
97 reset_proxy(world, index, wake_bodies, destroy_proxy);
98
99 world.locked = false;
100}
101
102pub fn shape_set_mesh(world: &mut World, shape_id: ShapeId, mesh: &MeshData, scale: Vec3) {
110 debug_assert!(is_valid_vec3(scale));
111 debug_assert!(is_valid_mesh(Some(mesh)));
112 debug_assert!(mesh.hash != 0);
113
114 debug_assert!(!world.locked);
115 if world.locked {
116 return;
117 }
118
119 world.locked = true;
120
121 let index = get_shape(world, shape_id);
122 destroy_shape_allocation_for_shape_change(world, index);
123
124 {
125 let shape = &mut world.shapes[index as usize];
126 shape.geometry = ShapeGeometry::Mesh {
127 data: mesh.clone(),
128 scale: safe_scale(scale),
129 };
130 shape.aabb_margin = compute_shape_margin(shape);
131 }
132
133 let wake_bodies = true;
135 let destroy_proxy = true;
136 reset_proxy(world, index, wake_bodies, destroy_proxy);
137
138 world.locked = false;
139}
140
141pub fn shape_set_hull(world: &mut World, shape_id: ShapeId, hull: &HullData) {
146 debug_assert!(is_valid_hull(hull));
147 debug_assert!(hull.hash != 0);
148
149 debug_assert!(!world.locked);
150 if world.locked {
151 return;
152 }
153
154 world.locked = true;
155
156 let index = get_shape(world, shape_id);
157
158 let data = world.hull_database.add(hull);
161
162 if let ShapeGeometry::Hull(existing) = &world.shapes[index as usize].geometry {
164 if Rc::ptr_eq(existing, &data) {
165 drop(data);
167 world.locked = false;
168 return;
169 }
170 }
171
172 destroy_shape_allocation_for_shape_change(world, index);
173
174 {
175 let shape = &mut world.shapes[index as usize];
176 shape.geometry = ShapeGeometry::Hull(data);
177 shape.aabb_margin = compute_shape_margin(shape);
178 }
179
180 let wake_bodies = true;
181 let destroy_proxy = true;
182 reset_proxy(world, index, wake_bodies, destroy_proxy);
183
184 world.locked = false;
185}