pub use oxiphysics_core::math::Real;
pub use oxiphysics_core::math::Vec3;
pub use oxiphysics_core::math::Vec4;
pub use oxiphysics_core::math::Mat3;
pub use oxiphysics_core::math::Mat4;
pub use oxiphysics_core::math::Quat;
pub use oxiphysics_core::Aabb;
pub use oxiphysics_core::Transform;
pub use oxiphysics_core::MassProperties;
pub use oxiphysics_core::BodyHandle;
pub use oxiphysics_core::ColliderHandle;
pub use oxiphysics_core::PhysicsConfig;
pub use oxiphysics_core::TimeStep;
pub use oxiphysics_core::math::quat_from_axis_angle;
pub use oxiphysics_core::math::quat_to_euler;
pub use oxiphysics_core::math::quat_from_euler;
pub use oxiphysics_core::math::quat_slerp;
pub use oxiphysics_core::math::perspective;
pub use oxiphysics_core::math::look_at;
pub use oxiphysics_rigid::world::RigidWorld;
pub use oxiphysics_rigid::world::WorldConfig;
pub use oxiphysics_rigid::world::WorldStatistics;
pub use oxiphysics_rigid::RigidBody;
pub use oxiphysics_rigid::BodyType;
pub use oxiphysics_rigid::BodyState;
pub use oxiphysics_rigid::RigidBodySet;
pub use oxiphysics_rigid::ColliderSet;
pub use oxiphysics_collision::CollisionPair;
pub use oxiphysics_collision::ContactManifold;
pub use oxiphysics_collision::Contact;
pub use oxiphysics_collision::NarrowPhaseDispatcher;
pub use oxiphysics_collision::SweepAndPrune;
pub use oxiphysics_collision::BruteForceBroadPhase;
pub use oxiphysics_collision::BvhBroadphase;
pub use oxiphysics_geometry::Shape;
pub use oxiphysics_geometry::Sphere;
pub use oxiphysics_geometry::BoxShape;
pub use oxiphysics_geometry::Capsule;
pub use oxiphysics_geometry::Cylinder;
pub use oxiphysics_geometry::Cone;
pub use oxiphysics_geometry::TriangleMesh;
pub use oxiphysics_geometry::HeightField;
pub use oxiphysics_geometry::Compound;
pub use oxiphysics_geometry::Torus;
pub use oxiphysics_materials::elastic::ElasticMaterial;
pub use oxiphysics_materials::elastic::IsotropicElastic;
pub use oxiphysics_materials::elastic::OrthotropicElastic;
pub use oxiphysics_materials::elastic::NeoHookean;
pub use oxiphysics_constraints::Constraint;
pub use oxiphysics_constraints::ContactConstraint;
pub use oxiphysics_constraints::PgsSolver;
pub use oxiphysics_constraints::TgsSolver;
pub use oxiphysics_constraints::FixedJoint;
pub use oxiphysics_constraints::RevoluteJoint;
pub use oxiphysics_constraints::PrismaticJoint;
pub use oxiphysics_constraints::BallJoint;
pub use oxiphysics_constraints::SpringJoint;
pub use oxiphysics_constraints::MotorJoint;
pub use oxiphysics_constraints::SphericalJoint;
pub use oxiphysics_constraints::DistanceJoint;
pub use oxiphysics_constraints::WeldJoint;
pub type PhysicsVec3 = [f64; 3];
pub type PhysicsScalar = f64;
pub type PhysicsMat3 = [f64; 9];
pub type BodyIndex = usize;
pub type ColliderIndex = usize;
#[inline]
pub fn arr_to_vec3(a: PhysicsVec3) -> Vec3 {
Vec3::new(a[0], a[1], a[2])
}
#[inline]
pub fn vec3_to_arr(v: Vec3) -> PhysicsVec3 {
[v.x, v.y, v.z]
}
#[inline]
pub fn arr_distance(a: PhysicsVec3, b: PhysicsVec3) -> PhysicsScalar {
let dx = a[0] - b[0];
let dy = a[1] - b[1];
let dz = a[2] - b[2];
(dx * dx + dy * dy + dz * dz).sqrt()
}
#[inline]
pub fn arr_lerp(a: PhysicsVec3, b: PhysicsVec3, t: PhysicsScalar) -> PhysicsVec3 {
[
a[0] + t * (b[0] - a[0]),
a[1] + t * (b[1] - a[1]),
a[2] + t * (b[2] - a[2]),
]
}
#[inline]
pub fn arr_normalize(v: PhysicsVec3) -> PhysicsVec3 {
let len = arr_distance([0.0, 0.0, 0.0], v);
if len < 1e-15 {
[0.0, 0.0, 0.0]
} else {
[v[0] / len, v[1] / len, v[2] / len]
}
}
#[inline]
pub fn arr_dot(a: PhysicsVec3, b: PhysicsVec3) -> PhysicsScalar {
a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
}
#[inline]
pub fn arr_cross(a: PhysicsVec3, b: PhysicsVec3) -> PhysicsVec3 {
[
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0],
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_arr_to_vec3_basic() {
let v = arr_to_vec3([1.0, 2.0, 3.0]);
assert!((v.x - 1.0).abs() < 1e-12);
assert!((v.y - 2.0).abs() < 1e-12);
assert!((v.z - 3.0).abs() < 1e-12);
}
#[test]
fn test_vec3_to_arr_basic() {
let v = Vec3::new(7.0, 8.0, 9.0);
let a = vec3_to_arr(v);
assert_eq!(a, [7.0, 8.0, 9.0]);
}
#[test]
fn test_round_trip_arr_vec3() {
let orig = [1.5, -2.5, 3.14];
let v = arr_to_vec3(orig);
let back = vec3_to_arr(v);
for (a, b) in orig.iter().zip(back.iter()) {
assert!((a - b).abs() < 1e-12);
}
}
#[test]
fn test_arr_to_vec3_zero() {
let v = arr_to_vec3([0.0, 0.0, 0.0]);
assert_eq!(v.norm(), 0.0);
}
#[test]
fn test_arr_to_vec3_negative() {
let v = arr_to_vec3([-1.0, -2.0, -3.0]);
assert!((v.x + 1.0).abs() < 1e-12);
}
#[test]
fn test_arr_distance_unit() {
let d = arr_distance([0.0, 0.0, 0.0], [1.0, 0.0, 0.0]);
assert!((d - 1.0).abs() < 1e-12);
}
#[test]
fn test_arr_distance_zero() {
let d = arr_distance([1.0, 2.0, 3.0], [1.0, 2.0, 3.0]);
assert!(d.abs() < 1e-12);
}
#[test]
fn test_arr_distance_3d() {
let d = arr_distance([0.0, 0.0, 0.0], [1.0, 1.0, 1.0]);
assert!((d - 3f64.sqrt()).abs() < 1e-12);
}
#[test]
fn test_arr_distance_negative_coords() {
let d = arr_distance([-1.0, 0.0, 0.0], [1.0, 0.0, 0.0]);
assert!((d - 2.0).abs() < 1e-12);
}
#[test]
fn test_arr_lerp_start() {
let r = arr_lerp([0.0, 0.0, 0.0], [10.0, 20.0, 30.0], 0.0);
assert_eq!(r, [0.0, 0.0, 0.0]);
}
#[test]
fn test_arr_lerp_end() {
let r = arr_lerp([0.0, 0.0, 0.0], [10.0, 20.0, 30.0], 1.0);
assert!((r[0] - 10.0).abs() < 1e-12);
}
#[test]
fn test_arr_lerp_mid() {
let r = arr_lerp([0.0, 0.0, 0.0], [2.0, 4.0, 6.0], 0.5);
assert!((r[0] - 1.0).abs() < 1e-12);
assert!((r[1] - 2.0).abs() < 1e-12);
assert!((r[2] - 3.0).abs() < 1e-12);
}
#[test]
fn test_arr_lerp_quarter() {
let r = arr_lerp([0.0, 0.0, 0.0], [4.0, 0.0, 0.0], 0.25);
assert!((r[0] - 1.0).abs() < 1e-12);
}
#[test]
fn test_arr_normalize_x() {
let n = arr_normalize([5.0, 0.0, 0.0]);
assert!((n[0] - 1.0).abs() < 1e-12);
assert!(n[1].abs() < 1e-12);
assert!(n[2].abs() < 1e-12);
}
#[test]
fn test_arr_normalize_diagonal() {
let n = arr_normalize([1.0, 1.0, 1.0]);
let expected = 1.0 / 3f64.sqrt();
for c in n.iter() {
assert!((c - expected).abs() < 1e-12);
}
}
#[test]
fn test_arr_normalize_zero_safe() {
let n = arr_normalize([0.0, 0.0, 0.0]);
assert_eq!(n, [0.0, 0.0, 0.0]);
}
#[test]
fn test_arr_normalize_unit_length() {
let n = arr_normalize([3.0, 4.0, 0.0]);
let len = arr_distance([0.0, 0.0, 0.0], n);
assert!((len - 1.0).abs() < 1e-12);
}
#[test]
fn test_arr_dot_parallel() {
assert!((arr_dot([1.0, 0.0, 0.0], [1.0, 0.0, 0.0]) - 1.0).abs() < 1e-12);
}
#[test]
fn test_arr_dot_perpendicular() {
assert!(arr_dot([1.0, 0.0, 0.0], [0.0, 1.0, 0.0]).abs() < 1e-12);
}
#[test]
fn test_arr_dot_anti_parallel() {
assert!((arr_dot([1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]) + 1.0).abs() < 1e-12);
}
#[test]
fn test_arr_dot_general() {
let d = arr_dot([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]);
assert!((d - 32.0).abs() < 1e-12);
}
#[test]
fn test_arr_cross_xy() {
let c = arr_cross([1.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
assert!((c[2] - 1.0).abs() < 1e-12);
}
#[test]
fn test_arr_cross_anti_commutative() {
let a = arr_cross([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]);
let b = arr_cross([4.0, 5.0, 6.0], [1.0, 2.0, 3.0]);
for i in 0..3 {
assert!((a[i] + b[i]).abs() < 1e-12);
}
}
#[test]
fn test_arr_cross_parallel_zero() {
let c = arr_cross([1.0, 0.0, 0.0], [2.0, 0.0, 0.0]);
for comp in c.iter() {
assert!(comp.abs() < 1e-12);
}
}
#[test]
fn test_arr_cross_magnitude() {
let c = arr_cross([1.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
let mag = arr_distance([0.0, 0.0, 0.0], c);
assert!((mag - 1.0).abs() < 1e-12);
}
#[test]
fn test_physics_scalar_type() {
let s: PhysicsScalar = 3.14;
assert!((s - 3.14).abs() < 1e-12);
}
#[test]
fn test_physics_vec3_type() {
let v: PhysicsVec3 = [1.0, 2.0, 3.0];
assert_eq!(v.len(), 3);
}
#[test]
fn test_physics_mat3_type() {
let m: PhysicsMat3 = [0.0; 9];
assert_eq!(m.len(), 9);
}
#[test]
fn test_body_index_type() {
let idx: BodyIndex = 42;
assert_eq!(idx, 42);
}
#[test]
fn test_collider_index_type() {
let idx: ColliderIndex = 7;
assert_eq!(idx, 7);
}
#[test]
fn test_physics_config_default() {
let _cfg = PhysicsConfig::default();
}
#[test]
fn test_vec3_negation() {
let v = arr_to_vec3([1.0, 2.0, 3.0]);
let neg = -v;
assert!((neg.x + 1.0).abs() < 1e-12);
}
#[test]
fn test_vec3_addition() {
let a = arr_to_vec3([1.0, 0.0, 0.0]);
let b = arr_to_vec3([0.0, 1.0, 0.0]);
let sum = a + b;
assert!((sum.x - 1.0).abs() < 1e-12);
assert!((sum.y - 1.0).abs() < 1e-12);
}
}