code wiki / (root) / nx_beach_contact_sweep.nx

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}