dynamis-rigid 0.7.0

Rigid body integration, islands, CCD, and constraint solving
Documentation
use crate::RigidDomain;
use dynamis_abi::{
    AabbRecord, BodyStateRecord, CONTACT_MAX_POINTS, ConstraintRowsRecord, ConstraintRuntimeRecord,
    ContactEventRecord, ContactRecord, JointStateRecord, NO_SLOT, SOLVER_BLOCK_CONSTRAINT,
};
use dynamis_domain::Domain;
use dynamis_domain::streams;
use dynamis_gpu::Contents;
use dynamis_gpu::EVENT_SLOTS;

pub const COMPACT_BLOCK: u32 = 256;

const SOLVER_BLOCK_KINDS: u32 = SOLVER_BLOCK_CONSTRAINT + 1;

pub const DELTA_WORDS: u32 = dynamis_abi::SOLVER_DELTA_WORDS;
pub const BLOCK_LANES: u32 = 2;

streams! {
    RigidStreams, RigidStream, RigidDemand, RigidDomain::ID, demand,
    demand {
        bodies: u32,
        colliders: u32,
        constraints: u32,
        pairs: u32,
        events: u32,
        sort: u32,
    }
    streams {
        collider_aabbs, ColliderAabbs: "broadphase aabbs", AabbRecord, 1, Contents::Scratch, demand.colliders;
        live_bodies, LiveBodies: "live body rows", u32, 1, Contents::Scratch, demand.bodies;
        body_activity, BodyActivity: "body activity", u32, 1, Contents::Scratch, demand.bodies;
        body_motion, BodyMotion: "body motion", u32, 1, Contents::Scratch, demand.bodies;
        body_state_scratch, BodyStateScratch: "body state scratch", BodyStateRecord, 1, Contents::Scratch, demand.bodies;
        constraint_rows, ConstraintRows: "constraint rows", ConstraintRowsRecord, 1, Contents::Scratch, demand.constraints;
        joint_states, JointStates: "joint states", JointStateRecord, 1, Contents::Scratch, demand.constraints;
        constraint_scratch, ConstraintScratch: "constraint state scratch", ConstraintRuntimeRecord, 1, Contents::Scratch, demand.constraints;
        joint_filter_major, JointFilterMajor: "joint filter major", u32, 1, Contents::Scratch, demand.constraints;
        joint_filter_minor, JointFilterMinor: "joint filter minor", u32, 1, Contents::Scratch, demand.constraints;
        ccd_factor, CcdFactor: "ccd retreat factors", u32, 1, Contents::Scratch, demand.bodies;
        ccd_impact, CcdImpact: "ccd impacts", [f32; 4], 1, Contents::Scratch, demand.bodies;
        contacts_raw, ContactsRaw: "contacts raw", ContactRecord, 1, Contents::Scratch, demand.pairs;
        contact_valid, ContactValid: "contact valid", u32, 1, Contents::Scratch, demand.pairs;
        compact_ranks, CompactRanks: "compact ranks", u32, 1, Contents::Scratch, demand.pairs;
        compact_block_sums, CompactBlockSums: "compact block sums", u32, 1, Contents::Scratch, demand.compact_blocks();
        compact_block_offsets, CompactBlockOffsets: "compact block offsets", u32, 1, Contents::Scratch, demand.compact_blocks();
        contacts, Contacts: "contacts", ContactRecord, 1, Contents::Scratch, demand.pairs;
        contact_target_speeds, ContactTargetSpeeds: "contact target speeds", f32, CONTACT_MAX_POINTS, Contents::Scratch, demand.pairs;
        contact_matched, ContactMatched: "contact matched", u32, 1, Contents::Scratch, demand.pairs;
        contact_archive, ContactArchive: "contact archive", ContactRecord, 1, Contents::Durable, demand.pairs;
        resting_contacts, RestingContacts: "resting contacts", ContactRecord, 1, Contents::Durable, demand.pairs;
        resting_live, RestingLive: "resting contact live", u32, 1, Contents::Durable, demand.pairs;
        resting_next, RestingNext: "resting contact next", u32, 1, Contents::Durable, demand.pairs;
        resting_free, RestingFree: "resting contact free", u32, 1, Contents::Seeded(NO_SLOT), 1;
        resting_index_major, RestingIndexMajor: "resting index major", u32, 1, Contents::Durable, demand.pairs;
        resting_index_minor, RestingIndexMinor: "resting index minor", u32, 1, Contents::Durable, demand.pairs;
        resting_index_slots, RestingIndexSlots: "resting index slots", u32, 1, Contents::Durable, demand.pairs;
        solver_segments, SolverSegments: "solver segments", u32, 1, Contents::Scratch, SOLVER_BLOCK_KINDS;
        solver_block_counts, SolverBlockCounts: "solver block counts", u32, 1, Contents::Scratch, demand.bodies;
        solver_blocks, SolverBlocks: "solver block lanes", u32, 1, Contents::Scratch, demand.solver_words();
        solver_velocity_deltas, SolverVelocityDeltas: "solver velocity deltas", u32, 1, Contents::Scratch, demand.body_words();
        solver_position_deltas, SolverPositionDeltas: "solver position deltas", u32, 1, Contents::Scratch, demand.body_words();
        solver_resolution, SolverResolution: "solver resolution", [f32; 4], 1, Contents::Scratch, demand.bodies;
        solver_contributions, SolverContributions: "solver contributions", u32, 1, Contents::Scratch, demand.bodies;
        island_parents, IslandParents: "island parents", u32, 1, Contents::Scratch, demand.bodies;
        island_state, IslandState: "island state", u32, 1, Contents::Scratch, demand.bodies;
        events, Events: "contact events", ContactEventRecord, 1, Contents::Scratch, demand.events.saturating_mul(EVENT_SLOTS);
        sort_scratch_major, SortScratchMajor: "sort scratch major", u32, 1, Contents::Scratch, demand.sort;
        sort_scratch_minor, SortScratchMinor: "sort scratch minor", u32, 1, Contents::Scratch, demand.sort;
        sort_scratch_payload, SortScratchPayload: "sort scratch payload", u32, 1, Contents::Scratch, demand.sort;
        sort_dummy_payload, SortDummyPayload: "sort dummy payload", u32, 1, Contents::Scratch, demand.sort;
    }
}

impl RigidDemand {
    pub fn blocks(&self) -> u32 {
        self.pairs.saturating_add(self.constraints)
    }

    pub fn solver_words(&self) -> u32 {
        self.blocks().saturating_mul(BLOCK_LANES)
    }

    pub fn body_words(&self) -> u32 {
        self.bodies.saturating_mul(DELTA_WORDS)
    }

    pub fn compact_blocks(&self) -> u32 {
        self.pairs.div_ceil(COMPACT_BLOCK)
    }

    pub fn sort_slots(pairs: u32, constraints: u32) -> u32 {
        pairs.saturating_add(constraints)
    }
}

pub fn event_capacity<R: dynamis_gpu::Resources>(resources: &R) -> u32 {
    resources.slots(RigidStream::Events.into()) / EVENT_SLOTS
}

pub fn sort_capacity<R: dynamis_gpu::Resources>(resources: &R) -> u32 {
    resources.slots(RigidStream::SortScratchMajor.into())
}