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_write> body_states: array<BodyState>;
@group(0) @binding(2) var<storage, read> body_descs: array<BodyDescriptor>;
@group(0) @binding(3) var<storage, read_write> contacts: array<Contact>;
@group(0) @binding(4) var<storage, read> constraint_descs: array<ConstraintDescriptor>;
@group(0) @binding(5) var<storage, read_write> constraint_runtime: array<ConstraintRuntime>;
@group(0) @binding(6) var<storage, read_write> wake_flags: array<atomic<u32>>;
@group(0) @binding(7) var<storage, read> segments: array<u32>;
@group(0) @binding(8) var<storage, read> a_payload: array<u32>;
@group(0) @binding(9) var<storage, read_write> block_deltas: array<vec4f>;
@group(0) @binding(10) var<storage, read> block_counts: array<u32>;

struct BlockPair {
    first: Body,
    second: Body,
    split_first: Body,
    split_second: Body,
}

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

fn body_split(body: Body, scale: f32) -> Body {
    var split = body;
    split.desc.inverse_mass = body.desc.inverse_mass * scale;
    var inertia = body.desc.inverse_inertia;
    for (var index = 0u; index < 6u; index = index + 1u) {
        inertia[index] = inertia[index] * scale;
    }
    split.desc.inverse_inertia = inertia;
    return split;
}

fn block_scale(slot: u32) -> f32 {
    return f32(max(block_counts[slot], 1u));
}

fn block_pair(first_slot: u32, second_slot: u32) -> BlockPair {
    var pair: BlockPair;
    pair.first = load_body(first_slot);
    pair.second = load_body(second_slot);
    pair.split_first = body_split(pair.first, block_scale(first_slot));
    pair.split_second = body_split(pair.second, block_scale(second_slot));
    if (body_is_inert(pair.first)) {
        pair.first = body_frozen(pair.first);
        pair.split_first = body_frozen(pair.split_first);
    }
    if (body_is_inert(pair.second)) {
        pair.second = body_frozen(pair.second);
        pair.split_second = body_frozen(pair.split_second);
    }
    return pair;
}

fn store_block_delta(slot: u32, delta_a: vec3f, spin_a: vec3f, delta_b: vec3f, spin_b: vec3f) {
    block_deltas[slot * 4u] = vec4f(delta_a, 0.0);
    block_deltas[slot * 4u + 1u] = vec4f(spin_a, 0.0);
    block_deltas[slot * 4u + 2u] = vec4f(delta_b, 0.0);
    block_deltas[slot * 4u + 3u] = vec4f(spin_b, 0.0);
}

@compute @workgroup_size(WORKGROUP_SIZE)
fn main(@builtin(global_invocation_id) gid: vec3u) {
    let slot = gid.y * (WORKGROUPS_PER_ROW * WORKGROUP_SIZE) + gid.x;
    let contact_blocks = segments[SOLVER_BLOCK_CONTACT];
    if (slot >= contact_blocks + segments[SOLVER_BLOCK_CONSTRAINT]) {
        return;
    }
    let block = a_payload[slot];
    if (block < contact_blocks) {
        solve_contact_block(block, slot);
    } else {
        solve_constraint_block(block - contact_blocks, slot);
    }
}