dynamis-abi 0.7.0

Host to device record layouts, counters, and step parameters shared with WGSL
Documentation
use crate::ColliderRecord;
use crate::constant::{
    COLLIDER_EVENT_BEGIN_END, COLLIDER_EVENT_PERSIST, COLLIDER_SENSOR, NO_COLLISION_FILTER,
    SHAPE_CAPSULE, SHAPE_CUBOID, SHAPE_CYLINDER, SHAPE_HEIGHTFIELD, SHAPE_HULL, SHAPE_MESH,
    SHAPE_NONE, SHAPE_PLANE, SHAPE_SPHERE,
};
use dynamis_model::{ColliderDesc, ContactEventMode, Shape};

impl ColliderRecord {
    pub const fn cleared() -> Self {
        Self {
            slot: 0,
            kind: SHAPE_NONE,
            flags: 0,
            radius: 0.0,
            half_height: 0.0,
            _wgsl_pad0: [0; 12],
            half_extents: [0.0; 3],
            collision_group: NO_COLLISION_FILTER,
            local_offset: [0.0; 3],
            collision_mask: NO_COLLISION_FILTER,
            local_rotation: [0.0, 0.0, 0.0, 1.0],
            friction: 0.0,
            restitution: 0.0,
            source: 0,
            rolling_friction: 0.0,
            scale: [1.0; 3],
            spin_friction: 0.0,
        }
    }

    pub fn build(collider: &ColliderDesc, source: u32, slot: u32) -> Self {
        let kind = shape_kind(&collider.shape);
        let uniform =
            collider.scale[0] == collider.scale[1] && collider.scale[1] == collider.scale[2];
        let mut flags = if collider.sensor { COLLIDER_SENSOR } else { 0 };
        match collider.events {
            ContactEventMode::None => {}
            ContactEventMode::BeginEnd => flags |= COLLIDER_EVENT_BEGIN_END,
            ContactEventMode::Persist => {
                flags |= COLLIDER_EVENT_BEGIN_END | COLLIDER_EVENT_PERSIST;
            }
        }
        Self {
            slot,
            kind,
            flags,
            radius: match collider.shape {
                Shape::Sphere { radius } => {
                    if uniform {
                        radius * collider.scale[0]
                    } else {
                        radius
                    }
                }
                Shape::Capsule { radius, .. } | Shape::Cylinder { radius, .. } => {
                    if uniform {
                        radius * collider.scale[0]
                    } else {
                        radius
                    }
                }
                _ => 0.0,
            },
            half_height: match collider.shape {
                Shape::Capsule { half_height, .. } | Shape::Cylinder { half_height, .. } => {
                    if uniform {
                        half_height * collider.scale[0]
                    } else {
                        half_height
                    }
                }
                _ => 0.0,
            },
            _wgsl_pad0: [0; 12],
            half_extents: match collider.shape {
                Shape::Cuboid { half_extents } => [
                    half_extents[0] * collider.scale[0],
                    half_extents[1] * collider.scale[1],
                    half_extents[2] * collider.scale[2],
                ],
                _ => [0.0; 3],
            },
            collision_group: collider.collision_group.unwrap_or(NO_COLLISION_FILTER),
            local_offset: collider.offset,
            collision_mask: collider.collision_mask.unwrap_or(NO_COLLISION_FILTER),
            local_rotation: collider.rotation,
            friction: collider.friction,
            restitution: collider.restitution,
            source,
            rolling_friction: collider.rolling_friction,
            scale: baked_scale(collider, uniform),
            spin_friction: collider.spin_friction,
        }
    }
}

fn baked_scale(collider: &ColliderDesc, uniform: bool) -> [f32; 3] {
    match collider.shape {
        Shape::Cuboid { .. } | Shape::Plane => [1.0; 3],
        Shape::Hull(_) | Shape::Mesh(_) | Shape::HeightField(_) => collider.scale,
        _ if uniform => [1.0; 3],
        _ => collider.scale,
    }
}

fn shape_kind(shape: &Shape) -> u32 {
    match shape {
        Shape::Sphere { .. } => SHAPE_SPHERE,
        Shape::Cuboid { .. } => SHAPE_CUBOID,
        Shape::Capsule { .. } => SHAPE_CAPSULE,
        Shape::Cylinder { .. } => SHAPE_CYLINDER,
        Shape::Hull(_) => SHAPE_HULL,
        Shape::Mesh(_) => SHAPE_MESH,
        Shape::HeightField(_) => SHAPE_HEIGHTFIELD,
        Shape::Plane => SHAPE_PLANE,
    }
}