nx_beach_contact_sweep.nx source
↩ module page · 72 lines · 2315 B
1// Axis-aligned body sweep. Bounds and units belong to the caller's body contract.
2// An interval is open for overlap: touching faces are contact, not penetration.
3struct BeachContactBox {
4 min_x: i64,
5 min_y: i64,
6 min_z: i64,
7 max_x: i64,
8 max_y: i64,
9 max_z: i64,
10}
11func beach_contact_min(box: *BeachContactBox, axis: i64) -> i64 {
12 if axis == 0 { return box.min_x }
13 if axis == 1 { return box.min_y }
14 return box.min_z
15}
16func beach_contact_max(box: *BeachContactBox, axis: i64) -> i64 {
17 if axis == 0 { return box.max_x }
18 if axis == 1 { return box.max_y }
19 return box.max_z
20}
21func beach_contact_overlap(a: *BeachContactBox, b: *BeachContactBox) -> i64 {
22 if a.max_x <= b.min_x || a.min_x >= b.max_x { return 0 }
23 if a.max_y <= b.min_y || a.min_y >= b.max_y { return 0 }
24 if a.max_z <= b.min_z || a.min_z >= b.max_z { return 0 }
25 return 1
26}
27func beach_contact_translate(box: *BeachContactBox, axis: i64, delta: i64) -> i64 {
28 if axis == 0 { box.min_x=box.min_x+delta; box.max_x=box.max_x+delta }
29 if axis == 1 { box.min_y=box.min_y+delta; box.max_y=box.max_y+delta }
30 if axis == 2 { box.min_z=box.min_z+delta; box.max_z=box.max_z+delta }
31 return delta
32}
33// Clips only the moving axis. Initial penetration is not silently repaired.
34// Caller must report it separately using beach_contact_overlap.
35func beach_contact_clip(a: *BeachContactBox, b: *BeachContactBox, axis: i64, delta: i64) -> i64 {
36 var other: i64=0
37 while other < 3 {
38 if other != axis {
39 let alo: i64=beach_contact_min(a,other)
40 let ahi: i64=beach_contact_max(a,other)
41 let blo: i64=beach_contact_min(b,other)
42 let bhi: i64=beach_contact_max(b,other)
43 // Tangential face contact must remain free on a stationary axis, including a point footprint.
44 if ahi <= blo || alo >= bhi { return delta }
45 }
46 other=other+1
47 }
48 let amin: i64=beach_contact_min(a,axis)
49 let amax: i64=beach_contact_max(a,axis)
50 let bmin: i64=beach_contact_min(b,axis)
51 let bmax: i64=beach_contact_max(b,axis)
52 if amax > bmin && amin < bmax { return 0 }
53 if delta > 0 {
54 if amax <= bmin {
55 let gap: i64=bmin-amax
56 if gap < delta { return gap }
57 }
58 }
59 if delta < 0 {
60 if amin >= bmax {
61 let gap: i64=bmax-amin
62 if gap > delta { return gap }
63 }
64 }
65 return delta
66}
67
68struct BeachContactResult {
69 delta_q8: i64,
70 initial_overlap: i64,
71 hit_material: i64,
72}