dynamis-rigid 0.7.0

Rigid body integration, islands, CCD, and constraint solving
Documentation
use crate::RigidFrame;
use crate::RigidStream;
use dynamis_broadphase::BroadphaseStream;
use dynamis_gpu::Resources;
use dynamis_pass::{Schedule, Stage, domain_passes};

use dynamis_abi::{COUNTER_PAIRS, Count};
use dynamis_gpu::GpuContext;
use dynamis_shader::{CORE, GEOMETRY, rows, stream};
use dynamis_state::StateStream;

domain_passes!(
    CcdPasses,
    ccd_sweep => &["substeps"],
    ccd_apply => &["ccd_sweep"],
);

pub struct Ccd {
    passes: CcdPasses,
    sweep: Stage,
    apply: Stage,
}

impl Ccd {
    pub fn new(context: &GpuContext, streams: &impl Resources, passes: CcdPasses) -> Self {
        Self {
            passes,
            sweep: Stage::build(
                context,
                "ccd_sweep",
                stream(
                    context,
                    include_str!("../shaders/ccd_sweep.wgsl"),
                    GEOMETRY,
                    "work",
                    BroadphaseStream::PairMajor,
                ),
                streams,
                &[
                    ("params", StateStream::Params.whole()),
                    ("body_states", StateStream::BodyStates.whole()),
                    ("body_descs", StateStream::BodyDescriptors.whole()),
                    ("colliders", StateStream::Colliders.whole()),
                    ("pair_major", BroadphaseStream::PairMajor.whole()),
                    ("pair_minor", BroadphaseStream::PairMinor.whole()),
                    ("pair_count", dynamis_state::counter(COUNTER_PAIRS)),
                    ("collider_owners", StateStream::ColliderOwners.whole()),
                    ("ccd_factor", RigidStream::CcdFactor.whole()),
                    ("ccd_impact", RigidStream::CcdImpact.whole()),
                ],
                &dynamis_state::shape_resources(),
            ),
            apply: Stage::build(
                context,
                "ccd_apply",
                rows(
                    context,
                    include_str!("../shaders/ccd_apply.wgsl"),
                    CORE,
                    Count::Dynamic.field(),
                ),
                streams,
                &[
                    ("params", StateStream::Params.whole()),
                    ("body_states", StateStream::BodyStates.whole()),
                    ("ccd_factor", RigidStream::CcdFactor.whole()),
                    ("ccd_impact", RigidStream::CcdImpact.whole()),
                ],
                &[],
            ),
        }
    }

    pub fn record(
        &self,
        pass: u32,
        schedule: &mut Schedule,
        encoder: &mut wgpu::CommandEncoder,
        streams: &impl Resources,
        frame: &RigidFrame,
    ) {
        if !frame.ccd || !frame.simulating {
            return;
        }
        if pass == self.passes.ccd_sweep {
            let mut sweep = schedule.open(encoder, pass);
            self.sweep.record_stream(&mut sweep, streams);
            drop(sweep);
        } else if pass == self.passes.ccd_apply {
            let mut apply = schedule.open(encoder, pass);
            self.apply
                .record_rows(&mut apply, streams, Count::Dynamic.rows(&frame.params));
            drop(apply);
        }
    }
}