dynamis-soft 0.7.0

Soft body and fluid particle simulation
Documentation
@group(0) @binding(0) var<uniform> params: StepParams;
@group(0) @binding(1) var<storage, read> attachments: array<SoftAttachment>;
@group(0) @binding(2) var<storage, read_write> particles: array<SoftParticle>;
@group(0) @binding(3) var<storage, read> body_states: array<BodyState>;
@group(0) @binding(4) var<storage, read> body_descs: array<BodyDescriptor>;
@group(0) @binding(5) var<storage, read> row_of_body: array<u32>;
@group(0) @binding(6) var<storage, read_write> reactions: array<atomic<u32>>;
@group(0) @binding(7) var<storage, read> bodies: array<SoftBody>;

fn work(index: u32) {
    let attachment = attachments[index];
    if (attachment.particle == NO_SLOT) {
        return;
    }
    var particle = particles[attachment.particle];
    if (particle.owner == NO_BODY || bodies[particle.owner].sleeping != 0u) {
        return;
    }
    let row = rigid_row(attachment.body_id, attachment.generation);
    if (row == NO_BODY) {
        return;
    }
    let body = Body(body_states[row], body_descs[row]);
    let anchor = rigid_anchor(body, attachment.local);
    let offset = anchor - particle.position.xyz;
    let error = length(offset);
    if (error <= 1e-6) {
        return;
    }
    let axis = offset / error;
    let weight = particle.prev_position.w;
    var anchor_weight = 0.0;
    var lever = vec3f(0.0);
    if (!body_is_inert(body)) {
        lever = cross(anchor - body_com(body), axis);
        anchor_weight = body.desc.inverse_mass + dot(lever, apply_inverse_inertia(body, lever));
    }
    let total = weight + anchor_weight;
    if (total <= 0.0) {
        return;
    }
    let lambda = error / total;
    particle.position = vec4f(
        particle.position.xyz + axis * (lambda * weight),
        particle.position.w,
    );
    particle.velocity = vec4f(
        (particle.position.xyz - particle.prev_position.xyz) / params.soft_substep_dt,
        particle.velocity.w,
    );
    particles[attachment.particle] = particle;
    if (anchor_weight > 0.0) {
        accumulate_reaction(
            row,
            -axis * (lambda * body.desc.inverse_mass),
            -apply_inverse_inertia(body, lever) * lambda,
        );
    }
}