oxiphysics_geometry/heightfield/
heightfield_traits.rs1use crate::shape::{RayHit, Shape};
12use oxiphysics_core::Aabb;
13use oxiphysics_core::math::{Mat3, Real, Vec3};
14
15use super::functions::ray_triangle;
16use super::types::HeightField;
17
18impl Shape for HeightField {
19 fn bounding_box(&self) -> Aabb {
20 let (min_h, max_h) = self.height_bounds();
21 Aabb::new(
22 Vec3::new(0.0, min_h, 0.0),
23 Vec3::new(
24 self.scale_x * (self.cols - 1) as Real,
25 max_h,
26 self.scale_z * (self.rows - 1) as Real,
27 ),
28 )
29 }
30 fn support_point(&self, direction: &Vec3) -> Vec3 {
31 let mut best_dot = Real::NEG_INFINITY;
32 let mut best_point = Vec3::zeros();
33 for row in 0..self.rows {
34 for col in 0..self.cols {
35 let p = Vec3::new(
36 col as Real * self.scale_x,
37 self.height_at(row, col),
38 row as Real * self.scale_z,
39 );
40 let d = p.dot(direction);
41 if d > best_dot {
42 best_dot = d;
43 best_point = p;
44 }
45 }
46 }
47 best_point
48 }
49 fn volume(&self) -> Real {
50 if self.rows < 2 || self.cols < 2 {
51 return 0.0;
52 }
53 let cell_area = self.scale_x * self.scale_z;
54 let mut total = 0.0;
55 for row in 0..(self.rows - 1) {
56 for col in 0..(self.cols - 1) {
57 let h00 = self.height_at(row, col);
58 let h10 = self.height_at(row + 1, col);
59 let h01 = self.height_at(row, col + 1);
60 let h11 = self.height_at(row + 1, col + 1);
61 let avg_h = (h00 + h10 + h01 + h11) / 4.0;
62 total += avg_h * cell_area;
63 }
64 }
65 total
66 }
67 fn center_of_mass(&self) -> Vec3 {
68 Vec3::zeros()
69 }
70 fn inertia_tensor(&self, _mass: Real) -> Mat3 {
71 Mat3::zeros()
72 }
73 fn ray_cast(&self, ray_origin: &Vec3, ray_direction: &Vec3, max_toi: Real) -> Option<RayHit> {
74 let mut best: Option<RayHit> = None;
75 for row in 0..(self.rows.saturating_sub(1)) {
76 for col in 0..(self.cols.saturating_sub(1)) {
77 let x0 = col as Real * self.scale_x;
78 let x1 = (col + 1) as Real * self.scale_x;
79 let z0 = row as Real * self.scale_z;
80 let z1 = (row + 1) as Real * self.scale_z;
81 let v00 = Vec3::new(x0, self.height_at(row, col), z0);
82 let v10 = Vec3::new(x0, self.height_at(row + 1, col), z1);
83 let v01 = Vec3::new(x1, self.height_at(row, col + 1), z0);
84 let v11 = Vec3::new(x1, self.height_at(row + 1, col + 1), z1);
85 for tri in [&[v00, v01, v11], &[v00, v11, v10]] {
86 if let Some(hit) = ray_triangle(
87 ray_origin,
88 ray_direction,
89 max_toi,
90 &tri[0],
91 &tri[1],
92 &tri[2],
93 ) && best.as_ref().is_none_or(|b| hit.toi < b.toi)
94 {
95 best = Some(hit);
96 }
97 }
98 }
99 }
100 best
101 }
102}