Skip to main content

dynamis_rigid/
ccd.rs

1use crate::RigidFrame;
2use crate::RigidStream;
3use dynamis_broadphase::BroadphaseStream;
4use dynamis_gpu::Resources;
5use dynamis_pass::{Schedule, Stage, domain_passes};
6
7use dynamis_abi::{COUNTER_PAIRS, Count};
8use dynamis_gpu::GpuContext;
9use dynamis_shader::{CORE, GEOMETRY, rows, stream};
10use dynamis_state::StateStream;
11
12domain_passes!(
13    CcdPasses,
14    ccd_sweep => &["substeps"],
15    ccd_apply => &["ccd_sweep"],
16);
17
18pub struct Ccd {
19    passes: CcdPasses,
20    sweep: Stage,
21    apply: Stage,
22}
23
24impl Ccd {
25    pub fn new(context: &GpuContext, streams: &impl Resources, passes: CcdPasses) -> Self {
26        Self {
27            passes,
28            sweep: Stage::build(
29                context,
30                "ccd_sweep",
31                stream(
32                    context,
33                    include_str!("../shaders/ccd_sweep.wgsl"),
34                    GEOMETRY,
35                    "work",
36                    BroadphaseStream::PairMajor,
37                ),
38                streams,
39                &[
40                    ("params", StateStream::Params.whole()),
41                    ("body_states", StateStream::BodyStates.whole()),
42                    ("body_descs", StateStream::BodyDescriptors.whole()),
43                    ("colliders", StateStream::Colliders.whole()),
44                    ("pair_major", BroadphaseStream::PairMajor.whole()),
45                    ("pair_minor", BroadphaseStream::PairMinor.whole()),
46                    ("pair_count", dynamis_state::counter(COUNTER_PAIRS)),
47                    ("collider_owners", StateStream::ColliderOwners.whole()),
48                    ("ccd_factor", RigidStream::CcdFactor.whole()),
49                    ("ccd_impact", RigidStream::CcdImpact.whole()),
50                ],
51                &dynamis_state::shape_resources(),
52            ),
53            apply: Stage::build(
54                context,
55                "ccd_apply",
56                rows(
57                    context,
58                    include_str!("../shaders/ccd_apply.wgsl"),
59                    CORE,
60                    Count::Dynamic.field(),
61                ),
62                streams,
63                &[
64                    ("params", StateStream::Params.whole()),
65                    ("body_states", StateStream::BodyStates.whole()),
66                    ("ccd_factor", RigidStream::CcdFactor.whole()),
67                    ("ccd_impact", RigidStream::CcdImpact.whole()),
68                ],
69                &[],
70            ),
71        }
72    }
73
74    pub fn record(
75        &self,
76        pass: u32,
77        schedule: &mut Schedule,
78        encoder: &mut wgpu::CommandEncoder,
79        streams: &impl Resources,
80        frame: &RigidFrame,
81    ) {
82        if !frame.ccd || !frame.simulating {
83            return;
84        }
85        if pass == self.passes.ccd_sweep {
86            let mut sweep = schedule.open(encoder, pass);
87            self.sweep.record_stream(&mut sweep, streams);
88            drop(sweep);
89        } else if pass == self.passes.ccd_apply {
90            let mut apply = schedule.open(encoder, pass);
91            self.apply
92                .record_rows(&mut apply, streams, Count::Dynamic.rows(&frame.params));
93            drop(apply);
94        }
95    }
96}