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> body_states: array<BodyState>;
@group(0) @binding(2) var<storage, read> body_descs: array<BodyDescriptor>;
@group(0) @binding(3) var<storage, read> constraint_descs: array<ConstraintDescriptor>;
@group(0) @binding(4) var<storage, read> constraint_runtime: array<ConstraintRuntime>;
@group(0) @binding(5) var<storage, read_write> island_parents: array<atomic<u32>>;
@group(0) @binding(6) var<storage, read_write> wake_flags: array<atomic<u32>>;

fn load_body(slot: u32) -> Body {
    return Body(body_states[slot], body_descs[slot]);
}

fn island_link(a: u32, b: u32) {
    atomicMin(&island_parents[a], b);
    atomicMin(&island_parents[b], a);
}

@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.constraint_count) {
        return;
    }
    if (constraint_runtime[index].broken != 0u) {
        return;
    }
    let constraint = constraint_descs[index];
    let first = load_body(constraint.a);
    let second = load_body(constraint.b);
    let first_static = body_is_static(first);
    let second_static = body_is_static(second);
    if (first_static && atomicLoad(&wake_flags[constraint.a]) != 0u) {
        atomicOr(&wake_flags[constraint.b], 1u);
    }
    if (second_static && atomicLoad(&wake_flags[constraint.b]) != 0u) {
        atomicOr(&wake_flags[constraint.a], 1u);
    }
    if (!first_static && !second_static && body_is_dynamic(first) && body_is_dynamic(second)) {
        island_link(constraint.a, constraint.b);
    }
}