wreck 0.2.2

Library for collision detection of 3d shapes
Documentation
# wreck

A 3D collision detection library for Rust. Built on top of `glam` for math and `wide` for SIMD acceleration.

## Traits

- `Collides<T>` - boolean collision test between two shapes. Every pair of built-in shapes has an implementation in both directions.
- `Scalable` - uniform scaling of a shape.
- `Transformable` - translate, rotate (via `Mat3` or `Quat`), or apply a full `Affine3` transform.
- `Stretchable` - sweep a shape along a translation vector, producing the convex hull of the motion.
- `Bounded` - compute bounding volumes: `broadphase()` (bounding sphere), `obb()` (oriented bounding box), and `aabb()` (axis-aligned bounding box). Implemented for all volume types, `ConvexPolygon`, `LineSegment`, `Pointcloud`, and `Collider`. For `Collider`, returns infinite bounds if the collider contains any `Plane`, `Line`, or `Ray`.

## Shapes

### Volumes

- **Sphere** - center + radius
- **Capsule** - line segment + radius, with a fast path for Z-aligned capsules
- **Cuboid** - oriented bounding box (center, 3 axes, half-extents), with fast paths for axis-aligned cases
- **ConvexPolytope** - arbitrary convex shape defined by half-planes and vertices, with an OBB broadphase

### Surfaces

- **Plane** - infinite half-space defined by a normal and offset (`normal · x <= d`)
- **ConvexPolygon** - bounded convex polygon embedded in 3D, defined by a center, normal, and 2D vertices

### Lines

- **Line** - infinite line through a point with a direction
- **Ray** - half-line with an origin and direction
- **LineSegment** - finite segment between two endpoints

### Primitives

- **Point** - a single point in space

### Spatial

- **Pointcloud** - point cloud backed by a CAPT spatial index for fast broadphase queries

All shape pairs implement `Collides<T>` for boolean intersection tests. The trait also provides `collides_many` which can be more performant.

## Collider

`Collider` is a heterogeneous collection of shapes that can be tested against any single shape or another `Collider`. It supports `Transformable`, `Scalable`, applying the operation to every contained shape.

`Stretchable` is only implemented for Collider<NoPcl> since there's no way to stretch a point cloud.

```rust
use glam::Vec3;
use wreck::*;

let mut collider: Collider = Collider {
    spheres: vec![Sphere::new(Vec3::ZERO, 1.0)],
    ..Default::default()
};

// add shapes dynamically
collider.add(Cuboid::from_aabb(Vec3::splat(-1.0), Vec3::splat(1.0)));

// test against a single shape
let probe = Sphere::new(Vec3::new(0.5, 0.0, 0.0), 0.2);
if collider.collides(&probe) {
    // hit
}
```

## Shapes API

### Creating shapes

```rust
use glam::Vec3;
use wreck::*;

// Sphere
let sphere = Sphere::new(Vec3::ZERO, 1.0);

// Capsule — defined by two endpoints and a radius
let capsule = Capsule::new(
    Vec3::new(-2.0, 0.0, 0.0),
    Vec3::new(2.0, 0.0, 0.0),
    0.3,
);

// Cuboid — oriented bounding box
let cuboid = Cuboid::new(
    Vec3::ZERO,                                          // center
    [Vec3::X, Vec3::Y, Vec3::Z],                         // axes
    [1.0, 2.0, 0.5],                                     // half-extents
);
// or from an axis-aligned bounding box
let aabb = Cuboid::from_aabb(Vec3::splat(-1.0), Vec3::splat(1.0));

// Point
let point = Point::new(1.0, 2.0, 3.0);

// Line — infinite, through a point with a direction
let line = Line::new(Vec3::ZERO, Vec3::Y);
let line = Line::from_points(Vec3::ZERO, Vec3::ONE);

// Ray — half-line from an origin
let ray = Ray::new(Vec3::ZERO, Vec3::X);

// LineSegment — between two endpoints
let seg = LineSegment::new(Vec3::ZERO, Vec3::new(1.0, 1.0, 0.0));

// Plane — infinite half-space (normal · x <= d)
let plane = Plane::new(Vec3::Y, 0.0);
let plane = Plane::from_point_normal(Vec3::ZERO, Vec3::Y);

// ConvexPolygon — bounded polygon in 3D
let polygon = ConvexPolygon::new(
    Vec3::ZERO,                                          // center
    Vec3::Z,                                             // normal
    vec![[1.0, 0.0], [0.0, 1.0], [-1.0, 0.0], [0.0, -1.0]],  // 2D vertices
);

// ConvexPolytope — arbitrary convex hull
let polytope = ConvexPolytope::new(
    vec![(Vec3::X, 1.0), (-Vec3::X, 1.0),               // half-planes (normal, d)
         (Vec3::Y, 1.0), (-Vec3::Y, 1.0),
         (Vec3::Z, 1.0), (-Vec3::Z, 1.0)],
    vec![                                                // vertices
        Vec3::new( 1.0,  1.0,  1.0), Vec3::new(-1.0,  1.0,  1.0),
        Vec3::new( 1.0, -1.0,  1.0), Vec3::new(-1.0, -1.0,  1.0),
        Vec3::new( 1.0,  1.0, -1.0), Vec3::new(-1.0,  1.0, -1.0),
        Vec3::new( 1.0, -1.0, -1.0), Vec3::new(-1.0, -1.0, -1.0),
    ],
);
```

### Collision testing

```rust
use wreck::Collides;

// pairwise — works in both directions
sphere.collides(&capsule);
capsule.collides(&sphere);

// batch — SIMD-accelerated for some shapes
let others: Vec<Sphere> = vec![/* ... */];
sphere.collides_many(&others);
```

### Transforming shapes

```rust
use wreck::{Transformable, Scalable};

let mut sphere = Sphere::new(Vec3::ZERO, 1.0);

// in-place
sphere.translate(Vec3::new(1.0, 0.0, 0.0));
sphere.scale(2.0);

// or get a new copy
let moved = sphere.clone().translated([5.0, 0.0, 0.0]);
let rotated = sphere.clone().rotated_quat(glam::Quat::from_rotation_y(1.0));
let transformed = sphere.clone().transformed(glam::Affine3::IDENTITY);
```

### Bounding volumes

```rust
use wreck::Bounded;

// bounding sphere
let bsphere = capsule.broadphase();

// axis-aligned bounding box
let aabb = capsule.aabb();

// oriented bounding box
let obb = capsule.obb();

// works on Collider too — returns infinite bounds if it contains a Plane, Line, or Ray
let collider_aabb = collider.aabb();
```

### Stretching (swept volumes)

```rust
use wreck::Stretchable;

// stretching a sphere along a direction produces a capsule
let capsule = Sphere::new(Vec3::ZERO, 1.0).stretch(Vec3::X);

// stretching a cuboid produces either a larger cuboid (axis-aligned case)
// or a convex polytope (general case)
let swept = Cuboid::from_aabb(Vec3::splat(-1.0), Vec3::splat(1.0))
    .stretch(Vec3::new(1.0, 1.0, 0.0));
```

## Features

- `wreck-assert` — enables internal assertions in all builds
- `debug-wreck-assert` — enables internal assertions in debug builds only