1use crate::dynamic_tree::{DynamicTree, DYNAMIC_TREE_VERSION};
10use crate::geometry::{Capsule, ShapeType, Sphere, SurfaceMaterial};
11use crate::hull::{HullData, HULL_VERSION};
12use crate::math_functions::{Transform, Vec3, TRANSFORM_IDENTITY, VEC3_ONE};
13use crate::mesh::{Mesh, MeshData, MESH_VERSION};
14
15pub const COMPOUND_VERSION: u64 =
18 0x8307_78DB_0708_6EB4u64 ^ DYNAMIC_TREE_VERSION ^ MESH_VERSION ^ HULL_VERSION;
19
20pub const MAX_COMPOUND_MESH_MATERIALS: usize = 4;
23
24pub const COMPOUND_DATA_SIZE: usize = 144;
26
27pub const DYNAMIC_TREE_SIZE: usize = 80;
29
30pub const TREE_NODE_SIZE: usize = 48;
32
33pub const HULL_INSTANCE_SIZE: usize = 36;
35
36pub const MESH_INSTANCE_SIZE: usize = 60;
38
39pub const COMPOUND_CONVEX_SIZE: usize = 32;
41
42#[derive(Debug, Clone, Copy)]
44pub struct CompoundCapsuleDef {
45 pub capsule: Capsule,
46 pub material: SurfaceMaterial,
47}
48
49#[derive(Debug, Clone, Copy)]
51pub struct CompoundHullDef<'a> {
52 pub hull: &'a HullData,
53 pub transform: Transform,
54 pub material: SurfaceMaterial,
55}
56
57#[derive(Debug, Clone, Copy)]
59pub struct CompoundMeshDef<'a> {
60 pub mesh_data: &'a MeshData,
61 pub transform: Transform,
62 pub scale: Vec3,
63 pub materials: &'a [SurfaceMaterial],
64}
65
66#[derive(Debug, Clone, Copy)]
68pub struct CompoundSphereDef {
69 pub sphere: Sphere,
70 pub material: SurfaceMaterial,
71}
72
73#[derive(Debug, Clone, Default)]
75pub struct CompoundDef<'a> {
76 pub capsules: &'a [CompoundCapsuleDef],
77 pub hulls: &'a [CompoundHullDef<'a>],
78 pub meshes: &'a [CompoundMeshDef<'a>],
79 pub spheres: &'a [CompoundSphereDef],
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Default)]
84pub struct CompoundCapsule {
85 pub capsule: Capsule,
86 pub material_index: i32,
87}
88
89#[derive(Debug, Clone, Copy)]
91pub struct CompoundHull<'a> {
92 pub hull: &'a HullData,
93 pub transform: Transform,
94 pub material_index: i32,
95}
96
97#[derive(Debug, Clone, Copy)]
99pub struct CompoundMesh<'a> {
100 pub mesh_data: &'a MeshData,
101 pub transform: Transform,
102 pub scale: Vec3,
103 pub material_indices: [i32; MAX_COMPOUND_MESH_MATERIALS],
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Default)]
108pub struct CompoundSphere {
109 pub sphere: Sphere,
110 pub material_index: i32,
111}
112
113#[derive(Debug, Clone, Copy)]
115pub(crate) struct HullInstance {
116 pub transform: Transform,
117 pub shared_index: u32,
119 pub material_index: u32,
120 pub hull_offset: u32,
122}
123
124#[derive(Debug, Clone, Copy)]
126pub(crate) struct MeshInstance {
127 pub transform: Transform,
128 pub scale: Vec3,
129 pub shared_index: u32,
131 pub material_indices: [u32; MAX_COMPOUND_MESH_MATERIALS],
132 pub mesh_offset: u32,
134}
135
136#[derive(Debug, Clone, Copy)]
138pub enum ChildGeometry<'a> {
139 Capsule(Capsule),
140 Hull(&'a HullData),
141 Mesh(Mesh<'a>),
142 Sphere(Sphere),
143}
144
145#[derive(Debug, Clone, Copy)]
147pub struct ChildShape<'a> {
148 pub geometry: ChildGeometry<'a>,
149 pub transform: Transform,
150 pub material_indices: [i32; MAX_COMPOUND_MESH_MATERIALS],
151 pub shape_type: ShapeType,
152}
153
154#[derive(Debug, Clone)]
160pub struct CompoundData {
161 pub version: u64,
162 pub byte_count: i32,
163 pub node_offset: i32,
164 pub tree: DynamicTree,
165 pub material_offset: i32,
166 pub material_count: i32,
167 pub capsule_offset: i32,
168 pub capsule_count: i32,
169 pub hull_offset: i32,
170 pub hull_count: i32,
171 pub shared_hull_count: i32,
172 pub mesh_offset: i32,
173 pub mesh_count: i32,
174 pub shared_mesh_count: i32,
175 pub sphere_offset: i32,
176 pub sphere_count: i32,
177 pub materials: Vec<SurfaceMaterial>,
178 pub capsules: Vec<CompoundCapsule>,
179 pub(crate) hull_instances: Vec<HullInstance>,
180 pub shared_hulls: Vec<HullData>,
181 pub(crate) mesh_instances: Vec<MeshInstance>,
182 pub shared_meshes: Vec<MeshData>,
183 pub spheres: Vec<CompoundSphere>,
184}
185
186impl Default for CompoundData {
187 fn default() -> Self {
188 Self {
189 version: COMPOUND_VERSION,
190 byte_count: 0,
191 node_offset: 0,
192 tree: DynamicTree::new(0),
193 material_offset: 0,
194 material_count: 0,
195 capsule_offset: 0,
196 capsule_count: 0,
197 hull_offset: 0,
198 hull_count: 0,
199 shared_hull_count: 0,
200 mesh_offset: 0,
201 mesh_count: 0,
202 shared_mesh_count: 0,
203 sphere_offset: 0,
204 sphere_count: 0,
205 materials: Vec::new(),
206 capsules: Vec::new(),
207 hull_instances: Vec::new(),
208 shared_hulls: Vec::new(),
209 mesh_instances: Vec::new(),
210 shared_meshes: Vec::new(),
211 spheres: Vec::new(),
212 }
213 }
214}
215
216pub fn get_compound_materials(compound: &CompoundData) -> &[SurfaceMaterial] {
218 if compound.material_offset == 0 {
219 return &[];
220 }
221 &compound.materials
222}
223
224pub fn get_compound_capsule(compound: &CompoundData, index: i32) -> CompoundCapsule {
226 debug_assert!(0 <= index && index < compound.capsule_count && compound.capsule_offset > 0);
227 if compound.capsule_offset == 0 {
228 return CompoundCapsule::default();
229 }
230 compound.capsules[index as usize]
231}
232
233pub fn get_compound_hull(compound: &CompoundData, index: i32) -> CompoundHull<'_> {
235 debug_assert!(0 <= index && index < compound.hull_count && compound.hull_offset > 0);
236 if compound.hull_offset == 0 {
237 return CompoundHull {
238 hull: &compound.shared_hulls[0],
239 transform: TRANSFORM_IDENTITY,
240 material_index: 0,
241 };
242 }
243 let inst = &compound.hull_instances[index as usize];
244 CompoundHull {
245 hull: &compound.shared_hulls[inst.shared_index as usize],
246 transform: inst.transform,
247 material_index: inst.material_index as i32,
248 }
249}
250
251pub fn get_compound_mesh(compound: &CompoundData, index: i32) -> CompoundMesh<'_> {
253 debug_assert!(0 <= index && index < compound.mesh_count && compound.mesh_offset > 0);
254 if compound.mesh_offset == 0 {
255 return CompoundMesh {
256 mesh_data: &compound.shared_meshes[0],
257 transform: TRANSFORM_IDENTITY,
258 scale: VEC3_ONE,
259 material_indices: [0; MAX_COMPOUND_MESH_MATERIALS],
260 };
261 }
262 let inst = &compound.mesh_instances[index as usize];
263 let mut material_indices = [0i32; MAX_COMPOUND_MESH_MATERIALS];
264 for i in 0..MAX_COMPOUND_MESH_MATERIALS {
265 material_indices[i] = inst.material_indices[i] as i32;
266 }
267 CompoundMesh {
268 mesh_data: &compound.shared_meshes[inst.shared_index as usize],
269 transform: inst.transform,
270 scale: inst.scale,
271 material_indices,
272 }
273}
274
275pub fn get_compound_sphere(compound: &CompoundData, index: i32) -> CompoundSphere {
277 debug_assert!(0 <= index && index < compound.sphere_count && compound.sphere_offset > 0);
278 if compound.sphere_offset == 0 {
279 return CompoundSphere::default();
280 }
281 compound.spheres[index as usize]
282}
283
284pub fn get_compound_child(compound: &CompoundData, mut child_index: i32) -> ChildShape<'_> {
287 if 0 <= child_index && child_index < compound.capsule_count {
289 let compound_capsule = get_compound_capsule(compound, child_index);
290 return ChildShape {
291 geometry: ChildGeometry::Capsule(compound_capsule.capsule),
292 transform: TRANSFORM_IDENTITY,
293 material_indices: [compound_capsule.material_index, 0, 0, 0],
294 shape_type: ShapeType::Capsule,
295 };
296 }
297 child_index -= compound.capsule_count;
298
299 if 0 <= child_index && child_index < compound.hull_count {
301 let compound_hull = get_compound_hull(compound, child_index);
302 return ChildShape {
303 geometry: ChildGeometry::Hull(compound_hull.hull),
304 transform: compound_hull.transform,
305 material_indices: [compound_hull.material_index, 0, 0, 0],
306 shape_type: ShapeType::Hull,
307 };
308 }
309 child_index -= compound.hull_count;
310
311 if 0 <= child_index && child_index < compound.mesh_count {
313 let compound_mesh = get_compound_mesh(compound, child_index);
314 debug_assert_eq!(MAX_COMPOUND_MESH_MATERIALS, 4);
315 return ChildShape {
316 geometry: ChildGeometry::Mesh(Mesh {
317 data: compound_mesh.mesh_data,
318 scale: compound_mesh.scale,
319 }),
320 transform: compound_mesh.transform,
321 material_indices: compound_mesh.material_indices,
322 shape_type: ShapeType::Mesh,
323 };
324 }
325 child_index -= compound.mesh_count;
326
327 debug_assert!(0 <= child_index && child_index < compound.sphere_count);
328
329 let compound_sphere = get_compound_sphere(compound, child_index);
330 ChildShape {
331 geometry: ChildGeometry::Sphere(compound_sphere.sphere),
332 transform: TRANSFORM_IDENTITY,
333 material_indices: [compound_sphere.material_index, 0, 0, 0],
334 shape_type: ShapeType::Sphere,
335 }
336}