oxiphysics_geometry/shape.rs
1// Copyright 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3
4//! Shape trait and raycast types.
5
6use oxiphysics_core::math::{Mat3, Real, Vec3};
7use oxiphysics_core::{Aabb, MassProperties};
8
9/// Result of a ray intersection test.
10#[derive(Debug, Clone)]
11pub struct RayHit {
12 /// Point of intersection in world space.
13 pub point: Vec3,
14 /// Surface normal at the intersection point.
15 pub normal: Vec3,
16 /// Parameter along the ray (distance = toi * ray_direction.norm()).
17 pub toi: Real,
18}
19
20/// Trait for geometric shapes used in physics simulation.
21pub trait Shape: std::fmt::Debug + Send + Sync {
22 /// Compute the axis-aligned bounding box of this shape (in local space).
23 fn bounding_box(&self) -> Aabb;
24
25 /// Compute the support point in the given direction (for GJK).
26 fn support_point(&self, direction: &Vec3) -> Vec3;
27
28 /// Compute the volume of this shape.
29 fn volume(&self) -> Real;
30
31 /// Compute the center of mass in local space.
32 fn center_of_mass(&self) -> Vec3;
33
34 /// Compute the inertia tensor for the given mass.
35 fn inertia_tensor(&self, mass: Real) -> Mat3;
36
37 /// Compute full mass properties for a given density.
38 fn mass_properties(&self, density: Real) -> MassProperties {
39 let mass = density * self.volume();
40 MassProperties::new(mass, self.center_of_mass(), self.inertia_tensor(mass))
41 }
42
43 /// Cast a ray against this shape (in local space).
44 /// Returns the first intersection within `max_toi`.
45 fn ray_cast(&self, ray_origin: &Vec3, ray_direction: &Vec3, max_toi: Real) -> Option<RayHit>;
46}