dynamis-world 0.6.0

GPU-driven physics engine
Documentation
@group(0) @binding(0) var<uniform> params: StepParams;
@group(0) @binding(1) var<storage, read> aabbs: array<Aabb>;
@group(0) @binding(2) var<storage, read_write> entry_cells: array<u32>;
@group(0) @binding(3) var<storage, read_write> entry_colliders: array<u32>;
@group(0) @binding(4) var<storage, read_write> entry_count: array<atomic<u32>>;
@group(0) @binding(5) var<storage, read_write> large_bodies: array<u32>;
@group(0) @binding(6) var<storage, read_write> large_count: array<atomic<u32>>;
@group(0) @binding(7) var<storage, read_write> spillover: array<atomic<u32>>;

fn cell_hash(coord: vec3i) -> u32 {
    let x = u32(coord.x) * 0x9E3779B9u;
    let y = u32(coord.y) * 0x85EBCA77u;
    let z = u32(coord.z) * 0xC2B2AE3Du;
    return x ^ y ^ z ^ (x << 7u) ^ (y >> 3u) ^ (z << 11u);
}

@compute @workgroup_size(WORKGROUP_SIZE)
fn main(@builtin(global_invocation_id) gid: vec3u) {
    let index = gid.y * (WORKGROUPS_PER_ROW * WORKGROUP_SIZE) + gid.x;
    if (index >= params.body_count) {
        return;
    }
    let cell_size = params.grid_cell_size;
    for (var i = 0u; i < MAX_COLLIDERS_PER_BODY; i = i + 1u) {
        let collider_index = index * MAX_COLLIDERS_PER_BODY + i;
        let aabb = aabbs[collider_index];
        if (aabb.min.x > aabb.max.x) {
            continue;
        }
        let min_cell = vec3i(floor(aabb.min / cell_size));
        let max_cell = vec3i(floor(aabb.max / cell_size));
        let span = max_cell - min_cell + vec3i(1);
        let cell_count = span.x * span.y * span.z;
        if (cell_count > i32(params.max_cells_per_collider) || span.x > 8192 || span.y > 8192 || span.z > 8192) {
            let slot = atomicAdd(&large_count[0], 1u);
            if (slot < arrayLength(&large_bodies)) {
                large_bodies[slot] = collider_index;
            }
            continue;
        }
        for (var dx = min_cell.x; dx <= max_cell.x; dx = dx + 1) {
            for (var dy = min_cell.y; dy <= max_cell.y; dy = dy + 1) {
                for (var dz = min_cell.z; dz <= max_cell.z; dz = dz + 1) {
                    let slot = atomicAdd(&entry_count[0], 1u);
                    if (slot < arrayLength(&entry_cells)) {
                        entry_cells[slot] = cell_hash(vec3i(dx, dy, dz));
                        entry_colliders[slot] = collider_index;
                    } else {
                        atomicAdd(&spillover[0], 1u);
                    }
                }
            }
        }
    }
}