ncollide2d_updated/shape/
heightfield2.rs1use na::{DVector, Point2, RealField};
2use std::iter;
3
4use crate::bounding_volume::AABB;
5use crate::math::Vector;
6use crate::query::{Contact, ContactKinematic, ContactPreprocessor};
7use crate::shape::Segment;
8
9#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10#[derive(Clone, Debug)]
11pub struct HeightField<N: RealField + Copy> {
13 heights: DVector<N>,
14 scale: Vector<N>,
15 removed: Vec<bool>,
16 aabb: AABB<N>,
17}
18
19impl<N: RealField + Copy> HeightField<N> {
20 pub fn new(heights: DVector<N>, scale: Vector<N>) -> Self {
22 assert!(
23 heights.len() > 1,
24 "A heightfield heights must have at least 2 elements."
25 );
26
27 let max = heights.max();
28 let min = heights.min();
29 let hscale = scale * na::convert::<_, N>(0.5);
30 let aabb = AABB::new(
31 Point2::new(-hscale.x, min * scale.y),
32 Point2::new(hscale.x, max * scale.y),
33 );
34
35 HeightField {
36 heights,
37 scale,
38 aabb,
39 removed: Vec::new(),
40 }
41 }
42
43 pub fn num_cells(&self) -> usize {
45 self.heights.len() - 1
46 }
47
48 pub fn heights(&self) -> &DVector<N> {
50 &self.heights
51 }
52
53 pub fn scale(&self) -> &Vector<N> {
55 &self.scale
56 }
57
58 pub fn aabb(&self) -> &AABB<N> {
60 &self.aabb
61 }
62
63 pub fn cell_width(&self) -> N {
65 self.unit_cell_width() * self.scale.x
66 }
67
68 pub fn unit_cell_width(&self) -> N {
70 N::one() / na::convert(self.heights.len() as f64 - 1.0)
71 }
72
73 pub fn start_x(&self) -> N {
75 self.scale.x * na::convert(-0.5)
76 }
77
78 fn quantize_floor(&self, val: N, seg_length: N) -> usize {
79 let _0_5: N = na::convert(0.5);
80 let i = na::clamp(
81 ((val + _0_5) / seg_length).floor(),
82 N::zero(),
83 na::convert((self.num_cells() - 1) as f64),
84 );
85 na::convert_unchecked::<N, f64>(i) as usize
86 }
87
88 fn quantize_ceil(&self, val: N, seg_length: N) -> usize {
89 let _0_5: N = na::convert(0.5);
90 let i = na::clamp(
91 ((val + _0_5) / seg_length).ceil(),
92 N::zero(),
93 na::convert(self.num_cells() as f64),
94 );
95 na::convert_unchecked::<N, f64>(i) as usize
96 }
97
98 pub fn cell_at_point(&self, pt: &Point2<N>) -> Option<usize> {
100 let _0_5: N = na::convert(0.5);
101 let scaled_pt = pt.coords.component_div(&self.scale);
102 let seg_length = self.unit_cell_width();
103
104 if scaled_pt.x < -_0_5 || scaled_pt.x > _0_5 {
105 None
107 } else {
108 Some(self.quantize_floor(scaled_pt.x, seg_length))
109 }
110 }
111
112 pub fn segments<'a>(&'a self) -> impl Iterator<Item = Segment<N>> + 'a {
114 (0..self.num_cells()).filter_map(move |i| self.segment_at(i))
117 }
118
119 pub fn segment_at(&self, i: usize) -> Option<Segment<N>> {
121 if i >= self.num_cells() || self.is_segment_removed(i) {
122 return None;
123 }
124
125 let _0_5: N = na::convert(0.5);
126 let seg_length = N::one() / na::convert(self.heights.len() as f64 - 1.0);
127
128 let x0 = -_0_5 + seg_length * na::convert(i as f64);
129 let x1 = x0 + seg_length;
130
131 let y0 = self.heights[i + 0];
132 let y1 = self.heights[i + 1];
133
134 let mut p0 = Point2::new(x0, y0);
135 let mut p1 = Point2::new(x1, y1);
136
137 p0.coords.component_mul_assign(&self.scale);
139 p1.coords.component_mul_assign(&self.scale);
140
141 Some(Segment::new(p0, p1))
142 }
143
144 pub fn set_segment_removed(&mut self, i: usize, removed: bool) {
146 if self.removed.len() == 0 {
147 self.removed = iter::repeat(false).take(self.num_cells()).collect()
148 }
149
150 self.removed[i] = removed
151 }
152
153 pub fn is_segment_removed(&self, i: usize) -> bool {
155 self.removed.len() != 0 && self.removed[i]
156 }
157
158 pub fn map_elements_in_local_aabb(
160 &self,
161 aabb: &AABB<N>,
162 f: &mut impl FnMut(usize, &Segment<N>, &dyn ContactPreprocessor<N>),
163 ) {
164 let _0_5: N = na::convert(0.5);
165 let ref_mins = aabb.mins.coords.component_div(&self.scale);
166 let ref_maxs = aabb.maxs.coords.component_div(&self.scale);
167 let seg_length = N::one() / na::convert(self.heights.len() as f64 - 1.0);
168
169 if ref_maxs.x < -_0_5 || ref_mins.x > _0_5 {
170 return;
172 }
173
174 let min_x = self.quantize_floor(ref_mins.x, seg_length);
175 let max_x = self.quantize_ceil(ref_maxs.x, seg_length);
176
177 for i in min_x..max_x {
180 if self.is_segment_removed(i) {
181 continue;
182 }
183
184 let x0 = -_0_5 + seg_length * na::convert(i as f64);
185 let x1 = x0 + seg_length;
186
187 let y0 = self.heights[i + 0];
188 let y1 = self.heights[i + 1];
189
190 if (y0 > ref_maxs.y && y1 > ref_maxs.y) || (y0 < ref_mins.y && y1 < ref_mins.y) {
191 continue;
192 }
193
194 let mut p0 = Point2::new(x0, y0);
195 let mut p1 = Point2::new(x1, y1);
196
197 p0.coords.component_mul_assign(&self.scale);
199 p1.coords.component_mul_assign(&self.scale);
200
201 let seg = Segment::new(p0, p1);
203
204 let seg_id = i;
206 let proc = HeightFieldTriangleContactPreprocessor::new(self, seg_id);
207
208 f(seg_id, &seg, &proc);
210 }
211 }
212}
213
214#[allow(dead_code)]
215pub struct HeightFieldTriangleContactPreprocessor<'a, N: RealField + Copy> {
217 heightfield: &'a HeightField<N>,
218 triangle: usize,
219}
220
221impl<'a, N: RealField + Copy> HeightFieldTriangleContactPreprocessor<'a, N> {
222 pub fn new(heightfield: &'a HeightField<N>, triangle: usize) -> Self {
224 HeightFieldTriangleContactPreprocessor {
225 heightfield,
226 triangle,
227 }
228 }
229}
230
231impl<'a, N: RealField + Copy> ContactPreprocessor<N>
232 for HeightFieldTriangleContactPreprocessor<'a, N>
233{
234 fn process_contact(
235 &self,
236 _c: &mut Contact<N>,
237 _kinematic: &mut ContactKinematic<N>,
238 _is_first: bool,
239 ) -> bool {
240 true
277 }
278}