1use crate::ColliderRecord;
2use crate::constant::{
3 COLLIDER_EVENT_BEGIN_END, COLLIDER_EVENT_PERSIST, COLLIDER_SENSOR, NO_COLLISION_FILTER,
4 SHAPE_CAPSULE, SHAPE_CUBOID, SHAPE_CYLINDER, SHAPE_HEIGHTFIELD, SHAPE_HULL, SHAPE_MESH,
5 SHAPE_NONE, SHAPE_PLANE, SHAPE_SPHERE,
6};
7use dynamis_model::{ColliderDesc, ContactEventMode, Shape};
8
9impl ColliderRecord {
10 pub const fn cleared() -> Self {
11 Self {
12 slot: 0,
13 kind: SHAPE_NONE,
14 flags: 0,
15 radius: 0.0,
16 half_height: 0.0,
17 _wgsl_pad0: [0; 12],
18 half_extents: [0.0; 3],
19 collision_group: NO_COLLISION_FILTER,
20 local_offset: [0.0; 3],
21 collision_mask: NO_COLLISION_FILTER,
22 local_rotation: [0.0, 0.0, 0.0, 1.0],
23 friction: 0.0,
24 restitution: 0.0,
25 source: 0,
26 rolling_friction: 0.0,
27 scale: [1.0; 3],
28 spin_friction: 0.0,
29 }
30 }
31
32 pub fn build(collider: &ColliderDesc, source: u32, slot: u32) -> Self {
33 let kind = shape_kind(&collider.shape);
34 let uniform =
35 collider.scale[0] == collider.scale[1] && collider.scale[1] == collider.scale[2];
36 let mut flags = if collider.sensor { COLLIDER_SENSOR } else { 0 };
37 match collider.events {
38 ContactEventMode::None => {}
39 ContactEventMode::BeginEnd => flags |= COLLIDER_EVENT_BEGIN_END,
40 ContactEventMode::Persist => {
41 flags |= COLLIDER_EVENT_BEGIN_END | COLLIDER_EVENT_PERSIST;
42 }
43 }
44 Self {
45 slot,
46 kind,
47 flags,
48 radius: match collider.shape {
49 Shape::Sphere { radius } => {
50 if uniform {
51 radius * collider.scale[0]
52 } else {
53 radius
54 }
55 }
56 Shape::Capsule { radius, .. } | Shape::Cylinder { radius, .. } => {
57 if uniform {
58 radius * collider.scale[0]
59 } else {
60 radius
61 }
62 }
63 _ => 0.0,
64 },
65 half_height: match collider.shape {
66 Shape::Capsule { half_height, .. } | Shape::Cylinder { half_height, .. } => {
67 if uniform {
68 half_height * collider.scale[0]
69 } else {
70 half_height
71 }
72 }
73 _ => 0.0,
74 },
75 _wgsl_pad0: [0; 12],
76 half_extents: match collider.shape {
77 Shape::Cuboid { half_extents } => [
78 half_extents[0] * collider.scale[0],
79 half_extents[1] * collider.scale[1],
80 half_extents[2] * collider.scale[2],
81 ],
82 _ => [0.0; 3],
83 },
84 collision_group: collider.collision_group.unwrap_or(NO_COLLISION_FILTER),
85 local_offset: collider.offset,
86 collision_mask: collider.collision_mask.unwrap_or(NO_COLLISION_FILTER),
87 local_rotation: collider.rotation,
88 friction: collider.friction,
89 restitution: collider.restitution,
90 source,
91 rolling_friction: collider.rolling_friction,
92 scale: baked_scale(collider, uniform),
93 spin_friction: collider.spin_friction,
94 }
95 }
96}
97
98fn baked_scale(collider: &ColliderDesc, uniform: bool) -> [f32; 3] {
99 match collider.shape {
100 Shape::Cuboid { .. } | Shape::Plane => [1.0; 3],
101 Shape::Hull(_) | Shape::Mesh(_) | Shape::HeightField(_) => collider.scale,
102 _ if uniform => [1.0; 3],
103 _ => collider.scale,
104 }
105}
106
107fn shape_kind(shape: &Shape) -> u32 {
108 match shape {
109 Shape::Sphere { .. } => SHAPE_SPHERE,
110 Shape::Cuboid { .. } => SHAPE_CUBOID,
111 Shape::Capsule { .. } => SHAPE_CAPSULE,
112 Shape::Cylinder { .. } => SHAPE_CYLINDER,
113 Shape::Hull(_) => SHAPE_HULL,
114 Shape::Mesh(_) => SHAPE_MESH,
115 Shape::HeightField(_) => SHAPE_HEIGHTFIELD,
116 Shape::Plane => SHAPE_PLANE,
117 }
118}