dynamis-rigid 0.7.0

Rigid body integration, islands, CCD, and constraint solving
Documentation
use crate::capacity::Capacity;
use crate::{
    Ccd, CcdPasses, Rigid, RigidCapacity, RigidDemand, RigidFrame, RigidInputs, RigidPasses,
    RigidResolutionPasses, RigidShape, RigidStreams,
};
use dynamis_abi::COUNTER_ACTIVE;
use dynamis_abi::Counters;
use dynamis_domain::{Domain, Run, StepFacts};
use dynamis_gpu::GpuContext;
use dynamis_gpu::Resources;
use dynamis_pass::{PassGroup, Pipeline, Schedule};
use wgpu::CommandEncoder;

pub struct RigidDomain;

pub struct RigidDomainPasses {
    pub simulation: RigidPasses,
    pub continuous: CcdPasses,
    pub resolution: RigidResolutionPasses,
}

pub struct RigidDomainRuntime {
    pub simulation: Rigid,
    pub continuous: Ccd,
}

#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct RigidWork {
    pub body_commands: u32,
    pub constraint_commands: u32,
}

impl Domain for RigidDomain {
    const ID: u32 = 2;

    const SIMULATES: bool = true;

    const PASS_EDGES: dynamis_pass::PassEdges = &[
        RigidPasses::EDGES,
        CcdPasses::EDGES,
        RigidResolutionPasses::EDGES,
    ];

    type Demand = RigidDemand;
    type Inputs = RigidInputs;
    type Work = RigidWork;
    type Streams = RigidStreams;
    type Planner = Capacity;
    type Passes = RigidDomainPasses;
    type Runtime = RigidDomainRuntime;
    type Frame = RigidFrame;
    type Capacity = RigidCapacity;

    fn minimum() -> RigidDemand {
        Capacity::floor(dynamis_domain::STREAM_FLOOR)
    }

    fn occupied(inputs: &RigidInputs) -> bool {
        inputs.bodies > 0
    }

    fn pending(work: &RigidWork) -> bool {
        work.body_commands > 0 || work.constraint_commands > 0
    }

    fn active(measured: &Counters) -> bool {
        measured[COUNTER_ACTIVE] != 0
    }

    fn pass_groups() -> &'static [PassGroup] {
        &[
            RigidPasses::GROUP,
            CcdPasses::GROUP,
            RigidResolutionPasses::GROUP,
        ]
    }

    fn resolve(pipeline: &Pipeline) -> RigidDomainPasses {
        RigidDomainPasses {
            simulation: RigidPasses::resolve(pipeline),
            continuous: CcdPasses::resolve(pipeline),
            resolution: RigidResolutionPasses::resolve(pipeline),
        }
    }

    fn build(
        context: &GpuContext,
        streams: &impl Resources,
        passes: RigidDomainPasses,
    ) -> RigidDomainRuntime {
        RigidDomainRuntime {
            simulation: Rigid::new(context, streams, passes.simulation, passes.resolution),
            continuous: Ccd::new(context, streams, passes.continuous),
        }
    }

    fn frame(facts: &StepFacts, inputs: &RigidInputs, run: Run) -> RigidFrame {
        RigidFrame {
            params: facts.params,
            shape: RigidShape::of(&facts.counts),
            query_count: inputs.queries,
            observed_count: inputs.observed,
            simulating: run.awake,
            indexing: run.indexing,
            ccd: inputs.ccd,
        }
    }

    fn capacity(streams: &RigidStreams) -> RigidCapacity {
        crate::capacity(streams)
    }

    fn record(
        runtime: &RigidDomainRuntime,
        pass: u32,
        schedule: &mut Schedule,
        encoder: &mut CommandEncoder,
        streams: &impl Resources,
        frame: &RigidFrame,
    ) {
        runtime
            .simulation
            .record(pass, schedule, encoder, streams, frame);
        runtime
            .continuous
            .record(pass, schedule, encoder, streams, frame);
    }
}