Skip to main content

dynamis_abi/
collider.rs

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}