# phys

`import "github.com/matjam/bunyip/phys"`

Package phys simulates rigid bodies in 2D and 3D on the entity component system. Shapes attached to entities collide, bounce, slide and stack under gravity, and the game reads what touched what.

A 2D entity carries a gfx.Transform2, a Body2 and a Collider2; a 3D entity a gfx.Transform, a Body3 and a Collider3. Register System2 or System3 (or both) on the world and set a Settings2 or Settings3 resource for gravity and solver quality. Each update the system integrates velocities, finds overlapping shapes with a sweep over bounding boxes, generates contact points, resolves them with sequential impulses (restitution, friction, positional correction) and emits Collision and Trigger events. Times are seconds, distances use the game's world units, and angles are radians unless a field says otherwise. Transform scale does not resize colliders; size the shapes themselves. A zero gravity vector means no gravity. World systems and queries require serialized access.

	w.SetResource(phys.Settings3{Gravity: lin.V3(0, -9.8, 0)})
	w.SpawnWith(gfx.At(0, 5, 0), phys.Dynamic3(1), phys.Collider3{Shape: phys.Sphere{Radius: 0.5}})
	w.SpawnWith(gfx.Transform{}, phys.Collider3{Shape: phys.Box3{Half: lin.V3(10, 0.5, 10)}}) // static floor
	w.AddSystem("physics", phys.System3)

Names carry their dimension as a suffix where a type exists in both (Body2 and Body3, Box2 and Box3, Collider2 and Collider3, the events, the systems and the settings); shapes that exist in one dimension only are plain words (Circle, Polygon2 for the 2D polygon, Sphere).

Shapes in 3D are Sphere, Box3, Capsule, ConvexHull, Compound3 (parts placed on one body) and MeshShape (a static triangle mesh for terrain and levels, with a triangle tree built by NewMeshShape). Sphere and box pairs have exact tests, as does a capsule lying along a box face; every other pair collides through support functions (GJK for distance, EPA for penetration) with face manifolds clipped the same way as the box test's. Shapes in 2D are Circle, Box2, Polygon2, Capsule2, and for terrain Edge2 and Chain2.

Queries inspect the world between updates. Raycast2 and Raycast3 return the nearest collider along a ray and RaycastAll2 and RaycastAll3 every one in order; OverlapShape2 and OverlapShape3 (with OverlapCircle2, OverlapBox2, OverlapSphere3 and OverlapBox3) return everything a placed shape touches; ShapeCast2 and ShapeCast3 sweep a shape and return the first thing in its way; Nearest2 and Nearest3 find the closest collider to a point. SignedDistance2 and SignedDistance3 measure a point against one placed shape without touching the world, for code that pushes points out of solids, such as the soft bodies in phys/soft. The queries that return a slice have an Into form (RaycastAll2Into, RaycastAll3Into, OverlapShape2Into, OverlapShape3Into) that appends to a slice the caller reuses, so a game can reuse result and scratch storage after their buffers grow. Each collider's placement (its rotation, position and bounds) is kept between steps and queries, and queries search a tree of those bounds, so a ray or a sweep tests only the colliders near it, in the order a walk over every collider would, with the same results. A query still walks the collider components once to notice transforms and shapes the game changed since the last step and places again only those; a character controller's move walks once for all its sweeps. In-place hull and compound edits are noticed even when bounds stay unchanged. MeshShape geometry must remain immutable.

Joints are components on their own entities that name the bodies they connect: DistanceJoint2 and DistanceJoint3 (rods and ropes), RevoluteJoint2 and HingeJoint3 (pins, with angle limits and a motor), BallJoint3 (a shoulder or hip, with cone and twist limits), PrismaticJoint2 and PrismaticJoint3 (sliders, with travel limits, a motor and a spring), WheelJoint2 (a wheel on a sprung suspension with a motor on its spin), SpringJoint2 and SpringJoint3 (damped springs) and FixedJoint2 and FixedJoint3 (welds). They are solved with the contacts, in entity order. NewRagdoll3 spawns a humanoid of capsules on limited joints from a RagdollSpec, and Ragdoll3.Pose places it from an animated character's bones. A body with CCD set is swept against static geometry every substep so it cannot tunnel, and its bounding sphere is swept against the other moving bodies. With Settings.SleepTime set, bodies that rest for that long sleep until touched or pushed (Body.Asleep, Body.Wake).

CharacterController2 and CharacterController3 move an upright capsule by sweeps rather than dynamics. The capsule slides along walls, climbs steps up to StepHeight, walks slopes up to MaxSlope and reports Grounded.

For orbits and spaceflight, see the orbit package. It works with the same transforms at astronomical scale.

## Constants

<a id="RagdollPelvis"></a>

<a id="RagdollSpine"></a>

<a id="RagdollHead"></a>

<a id="RagdollUpperArmL"></a>

<a id="RagdollForearmL"></a>

<a id="RagdollUpperArmR"></a>

<a id="RagdollForearmR"></a>

<a id="RagdollThighL"></a>

<a id="RagdollShinL"></a>

<a id="RagdollThighR"></a>

<a id="RagdollShinR"></a>

```go
const (
	RagdollPelvis    = "pelvis"
	RagdollSpine     = "spine"
	RagdollHead      = "head"
	RagdollUpperArmL = "upper_arm_l"
	RagdollForearmL  = "forearm_l"
	RagdollUpperArmR = "upper_arm_r"
	RagdollForearmR  = "forearm_r"
	RagdollThighL    = "thigh_l"
	RagdollShinL     = "shin_l"
	RagdollThighR    = "thigh_r"
	RagdollShinR     = "shin_r"
)
```

Ragdoll part names, in the order NewRagdoll3 spawns them.

## Variables

<a id="RagdollParts"></a>

```go
var RagdollParts = []string{ /* … */ }
```

RagdollParts lists the part names in the order NewRagdoll3 spawns them, the pelvis first.

## Functions

<a id="DrawColliders2"></a>

### DrawColliders2

```go
func DrawColliders2(g *gfx.Graphics, w *ecs.World)
```

DrawColliders2 outlines every 2D collider in the world as stroked paths in world units, and draws the normal of each contact the last update reported. Call it from Draw, under the same 2D camera the world is drawn with.

<a id="DrawColliders3"></a>

### DrawColliders3

```go
func DrawColliders3(g *gfx.Graphics, w *ecs.World)
```

DrawColliders3 outlines every 3D collider in the world as debug lines over the scene, and draws the normal of each contact the last update reported. Call it from Draw, with the same camera the scene is drawn with. Awake bodies, sleeping bodies and static colliders are told apart by colour; DrawCollidersColors3 chooses the colours.

<a id="DrawCollidersColors2"></a>

### DrawCollidersColors2

```go
func DrawCollidersColors2(g *gfx.Graphics, w *ecs.World, colors DebugColors)
```

DrawCollidersColors2 is DrawColliders2 with the colours chosen.

<a id="DrawCollidersColors3"></a>

### DrawCollidersColors3

```go
func DrawCollidersColors3(g *gfx.Graphics, w *ecs.World, colors DebugColors)
```

DrawCollidersColors3 is DrawColliders3 with the colours chosen.

<a id="DrawShape2"></a>

### DrawShape2

```go
func DrawShape2(g *gfx.Graphics, s Shape2, t gfx.Transform2, c gfx.Color)
```

DrawShape2 outlines one 2D shape placed by a transform, as a stroked path in world units: a circle, a box, a polygon, a capsule as two circles and their sides, an edge or chain as its segments.

<a id="DrawShape3"></a>

### DrawShape3

```go
func DrawShape3(g *gfx.Graphics, s Shape3, t gfx.Transform, c gfx.Color)
```

DrawShape3 outlines one 3D shape placed by a transform, as debug lines: a sphere as three rings, a box as its edges, a capsule as two spheres and the lines between them, a hull as every edge between its points, a compound as each of its parts. A mesh shape is left out, since a terrain mesh is already drawn.

<a id="SignedDistance2"></a>

### SignedDistance2

```go
func SignedDistance2(s Shape2, pos lin.Vec2, rot float32, point lin.Vec2) (dist float32, normal lin.Vec2, ok bool)
```

SignedDistance2 measures a point against a shape placed at pos with rotation rot. It returns the distance from the point to the nearest outline, negative when the point is inside, and the unit normal there, pointing out of the shape. Use it to push a point out of a solid: move it along the normal until the distance reaches the clearance wanted.

The shapes it understands are Circle, Box2, Polygon2 and Capsule2; ok is false for Edge2, Chain2 and a nil shape, which have no inside. It allocates nothing for polygons of up to sixteen points, so it suits a per-particle inner loop.

<a id="SignedDistance3"></a>

### SignedDistance3

```go
func SignedDistance3(s Shape3, pos lin.Vec3, rot lin.Quat, point lin.Vec3) (dist float32, normal lin.Vec3, ok bool)
```

SignedDistance3 measures a point against a shape placed at pos with rotation rot. It returns the distance from the point to the nearest surface, negative when the point is inside, and the unit normal there, pointing out of the shape. Use it to push a point out of a solid: move it along the normal until the distance reaches the clearance wanted.

The shapes it understands are Sphere, Box3, Capsule and a Compound3 of those; ok is false for ConvexHull, MeshShape and a nil shape, which have no cheap signed distance. It allocates nothing, so it suits a per-particle inner loop.

<a id="System2"></a>

### System2

```go
func System2(w *ecs.World, dt float64)
```

System2 advances every 2D body by dt seconds.

<a id="System3"></a>

### System3

```go
func System3(w *ecs.World, dt float64)
```

System3 advances every 3D body by dt seconds.

## Types

<a id="BallJoint3"></a>

<a id="BallJoint3.A"></a>

<a id="BallJoint3.B"></a>

<a id="BallJoint3.AnchorA"></a>

<a id="BallJoint3.AnchorB"></a>

<a id="BallJoint3.AxisA"></a>

<a id="BallJoint3.AxisB"></a>

<a id="BallJoint3.ConeAngle"></a>

<a id="BallJoint3.TwistAngle"></a>

### BallJoint3

```go
type BallJoint3 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec3
	AxisA, AxisB     lin.Vec3
	ConeAngle        float32
	TwistAngle       float32
	// contains filtered or unexported fields
}
```

BallJoint3 pins two bodies at an anchor and lets them turn freely about it: a shoulder, a hip, a neck. AxisB is the limb's axis in B's frame (zero means local Y) and AxisA the centre of its cone in A's frame (zero means where AxisB pointed on the first step). ConeAngle limits how far AxisB may swing from AxisA and TwistAngle how far B may turn about AxisB either way, both in radians; zero means unlimited. A side set to ecs.None fixes that anchor and axis in the world.

<a id="BallJoint3.Angles"></a>

#### BallJoint3.Angles

```go
func (j *BallJoint3) Angles(w *ecs.World) (cone, twist float32)
```

Angles returns the swing of AxisB away from AxisA and the twist of B about AxisB, in radians. The first call captures the reference pose and default cone axis if the solver has not measured them yet.

<a id="Body2"></a>

<a id="Body2.Vel"></a>

<a id="Body2.AngVel"></a>

<a id="Body2.Mass"></a>

<a id="Body2.Restitution"></a>

<a id="Body2.Friction"></a>

<a id="Body2.LinearDamping"></a>

<a id="Body2.AngularDamping"></a>

<a id="Body2.GravityScale"></a>

<a id="Body2.Kinematic"></a>

<a id="Body2.LockRotation"></a>

<a id="Body2.Sleeping"></a>

<a id="Body2.CCD"></a>

### Body2

```go
type Body2 struct {
	Vel    lin.Vec2
	AngVel float32 // radians per second; positive rotates +X toward +Y (clockwise on screen)
	Mass   float32
	// Restitution is bounciness, 0 to 1; Friction is the Coulomb
	// coefficient, 0 slides freely.
	Restitution, Friction float32
	// Damping removes a fraction of velocity per second.
	LinearDamping, AngularDamping float32
	// GravityScale multiplies the world gravity; zero means 1.
	GravityScale float32
	Kinematic    bool
	LockRotation bool
	Sleeping     bool // set by the game to freeze a body
	// CCD sweeps the body against static colliders every substep and
	// stops it at the first one, so a fast small body cannot pass
	// through a thin wall.
	CCD bool
	// contains filtered or unexported fields
}
```

Body2 makes a 2D entity move. Mass zero is static; Kinematic bodies move by their velocity and push others without being pushed.

<a id="Dynamic2"></a>

#### Dynamic2

```go
func Dynamic2(mass float32) Body2
```

Dynamic2 returns a body with the given mass, restitution 0.1, friction 0.5 and gravity scale 1. A positive mass makes it dynamic.

<a id="Kinematic2"></a>

#### Kinematic2

```go
func Kinematic2() Body2
```

Kinematic2 returns a body moved by its velocity that others cannot push.

<a id="Body2.AddForce"></a>

#### Body2.AddForce

```go
func (b *Body2) AddForce(f lin.Vec2)
```

AddForce accumulates a force (units of mass·distance/s²) until the next update.

<a id="Body2.AddImpulse"></a>

#### Body2.AddImpulse

```go
func (b *Body2) AddImpulse(i lin.Vec2)
```

AddImpulse changes velocity at once by impulse/mass.

<a id="Body2.AddTorque"></a>

#### Body2.AddTorque

```go
func (b *Body2) AddTorque(t float32)
```

AddTorque accumulates a torque until the next update.

<a id="Body2.Asleep"></a>

#### Body2.Asleep

```go
func (b *Body2) Asleep() bool
```

Asleep reports that the body has come to rest and is skipped by the simulation until something touches or pushes it.

<a id="Body2.Wake"></a>

#### Body2.Wake

```go
func (b *Body2) Wake()
```

Wake clears automatic sleep and its timer. It does not clear Sleeping, which remains under the game's control.

<a id="Body3"></a>

<a id="Body3.Vel"></a>

<a id="Body3.AngVel"></a>

<a id="Body3.Mass"></a>

<a id="Body3.Restitution"></a>

<a id="Body3.Friction"></a>

<a id="Body3.LinearDamping"></a>

<a id="Body3.AngularDamping"></a>

<a id="Body3.GravityScale"></a>

<a id="Body3.Kinematic"></a>

<a id="Body3.LockRotation"></a>

<a id="Body3.Sleeping"></a>

<a id="Body3.CCD"></a>

### Body3

```go
type Body3 struct {
	Vel    lin.Vec3
	AngVel lin.Vec3 // radians per second about each world axis
	Mass   float32
	// Restitution is bounciness, 0 to 1; Friction is the Coulomb
	// coefficient, 0 slides freely.
	Restitution, Friction float32
	// Damping removes a fraction of velocity per second.
	LinearDamping, AngularDamping float32
	// GravityScale multiplies the world gravity; zero means 1.
	GravityScale float32
	Kinematic    bool
	LockRotation bool
	Sleeping     bool // set by the game to freeze a body
	// CCD sweeps the body against static colliders every substep and
	// stops it at the first one, so a fast small body cannot pass
	// through a thin wall.
	CCD bool
	// contains filtered or unexported fields
}
```

Body3 makes a 3D entity move. Mass zero is static; Kinematic bodies move by their velocity and push others without being pushed.

<a id="Dynamic3"></a>

#### Dynamic3

```go
func Dynamic3(mass float32) Body3
```

Dynamic3 returns a body with the given mass, restitution 0.1, friction 0.5 and gravity scale 1. A positive mass makes it dynamic.

<a id="Kinematic3"></a>

#### Kinematic3

```go
func Kinematic3() Body3
```

Kinematic3 returns a body moved by its velocity that others cannot push.

<a id="Body3.AddForce"></a>

#### Body3.AddForce

```go
func (b *Body3) AddForce(f lin.Vec3)
```

AddForce accumulates a force until the next update.

<a id="Body3.AddImpulse"></a>

#### Body3.AddImpulse

```go
func (b *Body3) AddImpulse(i lin.Vec3)
```

AddImpulse changes velocity at once by impulse/mass.

<a id="Body3.AddTorque"></a>

#### Body3.AddTorque

```go
func (b *Body3) AddTorque(t lin.Vec3)
```

AddTorque accumulates a torque until the next update.

<a id="Body3.Asleep"></a>

#### Body3.Asleep

```go
func (b *Body3) Asleep() bool
```

Asleep reports that the body has come to rest and is skipped by the simulation until something touches or pushes it.

<a id="Body3.Wake"></a>

#### Body3.Wake

```go
func (b *Body3) Wake()
```

Wake clears automatic sleep and its timer. It does not clear Sleeping, which remains under the game's control.

<a id="Box2"></a>

<a id="Box2.HalfW"></a>

<a id="Box2.HalfH"></a>

### Box2

```go
type Box2 struct{ HalfW, HalfH float32 }
```

Box2 is a rectangle centred on the body with the given half extents.

<a id="Box3"></a>

<a id="Box3.Half"></a>

### Box3

```go
type Box3 struct{ Half lin.Vec3 }
```

Box3 is a box centred on the body with the given half extents.

<a id="Capsule"></a>

<a id="Capsule.Radius"></a>

<a id="Capsule.HalfHeight"></a>

### Capsule

```go
type Capsule struct{ Radius, HalfHeight float32 }
```

Capsule is a cylinder along the body's local Y axis with hemispherical ends: Radius around the axis, HalfHeight from the centre to the centre of each cap, so the whole is 2·(HalfHeight+Radius) tall.

<a id="Capsule2"></a>

<a id="Capsule2.Radius"></a>

<a id="Capsule2.HalfHeight"></a>

### Capsule2

```go
type Capsule2 struct{ Radius, HalfHeight float32 }
```

Capsule2 is a segment along the body's local Y axis grown by Radius: HalfHeight from the centre to the centre of each round end.

<a id="Chain2"></a>

<a id="Chain2.Points"></a>

<a id="Chain2.Loop"></a>

### Chain2

```go
type Chain2 struct {
	Points []lin.Vec2
	Loop   bool
}
```

Chain2 is a run of edges through Points, for terrain outlines; Loop joins the last point back to the first.

<a id="CharacterController2"></a>

<a id="CharacterController2.Radius"></a>

<a id="CharacterController2.HalfHeight"></a>

<a id="CharacterController2.StepHeight"></a>

<a id="CharacterController2.MaxSlope"></a>

<a id="CharacterController2.Skin"></a>

<a id="CharacterController2.Mask"></a>

<a id="CharacterController2.Grounded"></a>

<a id="CharacterController2.GroundNormal"></a>

### CharacterController2

```go
type CharacterController2 struct {
	Radius     float32 // capsule radius; zero means 0.4
	HalfHeight float32 // centre to the centre of each cap; zero means 0.5
	StepHeight float32 // tallest ledge it climbs; zero means none
	MaxSlope   float32 // steepest walkable slope in degrees; zero means 45
	Skin       float32 // gap kept from surfaces; zero means 0.02
	Mask       uint32  // which collider layers block it; zero means all

	// Set by Move.
	Grounded     bool
	GroundNormal lin.Vec2
	// contains filtered or unexported fields
}
```

CharacterController2 is the 2D CharacterController3: an upright capsule moved by sweeps that slide along walls, climb ledges no taller than StepHeight, walk slopes up to MaxSlope and report ground contact. The entity needs a gfx.Transform2, which Move updates; a Collider2 on the same entity is ignored by its own sweeps.

<a id="CharacterController2.Move"></a>

#### CharacterController2.Move

```go
func (c *CharacterController2) Move(w *ecs.World, e ecs.Entity, velocity lin.Vec2, dt float32)
```

Move advances the character by velocity·dt: horizontally with sliding and stepping, then vertically, then out of anything it still overlaps. dt is seconds and velocity is world units per second. It applies no gravity or impulses; the game supplies vertical velocity. A missing transform leaves the controller unchanged. Use nonnegative dt; even a zero timestep may resolve overlaps and update ground contact.

<a id="CharacterController3"></a>

<a id="CharacterController3.Radius"></a>

<a id="CharacterController3.HalfHeight"></a>

<a id="CharacterController3.StepHeight"></a>

<a id="CharacterController3.MaxSlope"></a>

<a id="CharacterController3.Skin"></a>

<a id="CharacterController3.Mask"></a>

<a id="CharacterController3.Grounded"></a>

<a id="CharacterController3.GroundNormal"></a>

### CharacterController3

```go
type CharacterController3 struct {
	Radius     float32 // capsule radius; zero means 0.4
	HalfHeight float32 // centre to the centre of each cap; zero means 0.5
	StepHeight float32 // tallest ledge it climbs; zero means none
	MaxSlope   float32 // steepest walkable slope in degrees; zero means 45
	Skin       float32 // gap kept from surfaces; zero means 0.02
	Mask       uint32  // which collider layers block it; zero means all

	// Set by Move.
	Grounded     bool
	GroundNormal lin.Vec3
	// contains filtered or unexported fields
}
```

CharacterController3 moves an upright capsule through the world the way a player expects, without rigid-body dynamics: Move sweeps it along a velocity, slides it along whatever it hits, climbs ledges no taller than StepHeight, walks slopes up to MaxSlope and reports whether it stands on ground. The entity needs a gfx.Transform, which Move updates; a Collider3 on the same entity is ignored by its own sweeps, so other bodies can still bump into it.

<a id="CharacterController3.Move"></a>

#### CharacterController3.Move

```go
func (c *CharacterController3) Move(w *ecs.World, e ecs.Entity, velocity lin.Vec3, dt float32)
```

Move advances the character by velocity·dt: horizontally with sliding and stepping, then vertically, then out of anything it still overlaps. dt is seconds and velocity is world units per second. It applies no gravity or impulses; the game supplies vertical velocity. A missing transform leaves the controller unchanged. Use nonnegative dt; even a zero timestep may resolve overlaps and update ground contact.

<a id="Circle"></a>

<a id="Circle.Radius"></a>

### Circle

```go
type Circle struct{ Radius float32 }
```

Circle is a disc centred on the body.

<a id="Collider2"></a>

<a id="Collider2.Shape"></a>

<a id="Collider2.Offset"></a>

<a id="Collider2.Trigger"></a>

<a id="Collider2.Layers"></a>

### Collider2

```go
type Collider2 struct {
	Shape   Shape2
	Offset  lin.Vec2 // shape centre relative to the transform
	Trigger bool     // overlaps are reported but not resolved
	Layers
}
```

Collider2 gives an entity a shape. An entity with a Collider2 and no Body2 is a static obstacle. It also needs gfx.Transform2. A nil Shape is ignored; transform scale does not resize the shape.

<a id="Collider3"></a>

<a id="Collider3.Shape"></a>

<a id="Collider3.Offset"></a>

<a id="Collider3.Trigger"></a>

<a id="Collider3.Layers"></a>

### Collider3

```go
type Collider3 struct {
	Shape   Shape3
	Offset  lin.Vec3 // local offset, rotated by the transform's rotation
	Trigger bool     // overlaps emit events without applying collision impulses
	Layers
}
```

Collider3 gives an entity a shape. An entity with a Collider3 and no Body3 is a static obstacle. It also needs gfx.Transform. A nil Shape is ignored; transform scale does not resize the shape.

<a id="Collision2"></a>

<a id="Collision2.A"></a>

<a id="Collision2.B"></a>

<a id="Collision2.Point"></a>

<a id="Collision2.Normal"></a>

<a id="Collision2.Depth"></a>

<a id="Collision2.Impulse"></a>

### Collision2

```go
type Collision2 struct {
	A, B    ecs.Entity
	Point   lin.Vec2
	Normal  lin.Vec2 // from A to B
	Depth   float32
	Impulse float32
}
```

Collision2 is emitted for each pair of colliders that touched this update; A and B are ordered by entity id. Impulse is the total normal impulse the contact applied in the first substep it was seen, a measure of how hard the hit was.

<a id="Collision3"></a>

<a id="Collision3.A"></a>

<a id="Collision3.B"></a>

<a id="Collision3.Point"></a>

<a id="Collision3.Normal"></a>

<a id="Collision3.Depth"></a>

<a id="Collision3.Impulse"></a>

### Collision3

```go
type Collision3 struct {
	A, B    ecs.Entity
	Point   lin.Vec3
	Normal  lin.Vec3 // from A to B
	Depth   float32
	Impulse float32
}
```

Collision3 is emitted for each pair of colliders that touched this update; A and B are ordered by entity id. Impulse is the total normal impulse the contact applied in the first substep it was seen, a measure of how hard the hit was.

<a id="Compound3"></a>

<a id="Compound3.Parts"></a>

### Compound3

```go
type Compound3 struct{ Parts []Part3 }
```

Compound3 is several shapes moving as one body, for things a single convex shape cannot describe: a table, an L-shaped wall, a hammer. Parts may overlap each other.

<a id="ConvexHull"></a>

<a id="ConvexHull.Points"></a>

### ConvexHull

```go
type ConvexHull struct{ Points []lin.Vec3 }
```

ConvexHull is the convex volume around a set of points in the body's frame. Only the extreme points matter; interior ones are ignored by collision and may be left out. The points should surround the body's origin, which is its centre of mass.

<a id="DebugColors"></a>

<a id="DebugColors.Awake"></a>

<a id="DebugColors.Asleep"></a>

<a id="DebugColors.Static"></a>

<a id="DebugColors.Contacts"></a>

### DebugColors

```go
type DebugColors struct {
	Awake    gfx.Color // bodies that are simulating
	Asleep   gfx.Color // bodies that have gone to sleep
	Static   gfx.Color // colliders with no body
	Contacts gfx.Color // contact points and their normals
}
```

DebugColors are the colours the debug drawing uses. A zero colour where one is expected is left at the default noted, so DebugColors{} draws awake bodies orange, sleeping bodies grey, static colliders blue and contact normals red.

<a id="DistanceJoint2"></a>

<a id="DistanceJoint2.A"></a>

<a id="DistanceJoint2.B"></a>

<a id="DistanceJoint2.AnchorA"></a>

<a id="DistanceJoint2.AnchorB"></a>

<a id="DistanceJoint2.Length"></a>

<a id="DistanceJoint2.Min"></a>

<a id="DistanceJoint2.Max"></a>

### DistanceJoint2

```go
type DistanceJoint2 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec2
	Length           float32
	Min, Max         float32
	// contains filtered or unexported fields
}
```

DistanceJoint2 keeps two anchors a fixed distance apart, like a rod, or within a range, like a rope. AnchorA and AnchorB are in each body's frame; with B set to ecs.None, AnchorB is a point in the world. Length zero measures the distance on the first step. When Max is above zero the joint only acts outside \[Min, Max].

<a id="DistanceJoint3"></a>

<a id="DistanceJoint3.A"></a>

<a id="DistanceJoint3.B"></a>

<a id="DistanceJoint3.AnchorA"></a>

<a id="DistanceJoint3.AnchorB"></a>

<a id="DistanceJoint3.Length"></a>

<a id="DistanceJoint3.Min"></a>

<a id="DistanceJoint3.Max"></a>

### DistanceJoint3

```go
type DistanceJoint3 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec3
	Length           float32
	Min, Max         float32
	// contains filtered or unexported fields
}
```

DistanceJoint3 keeps two anchors a fixed distance apart, like a rod, or within a range, like a rope. AnchorA and AnchorB are in each body's frame; with B set to ecs.None, AnchorB is a point in the world. Length zero measures the distance on the first step. When Max is above zero the joint only acts outside \[Min, Max].

<a id="Edge2"></a>

<a id="Edge2.A"></a>

<a id="Edge2.B"></a>

### Edge2

```go
type Edge2 struct{ A, B lin.Vec2 }
```

Edge2 is a line segment in the body's frame with no inside: a piece of ground or wall that shapes collide with from either side.

<a id="FixedJoint2"></a>

<a id="FixedJoint2.A"></a>

<a id="FixedJoint2.B"></a>

<a id="FixedJoint2.AnchorA"></a>

<a id="FixedJoint2.AnchorB"></a>

### FixedJoint2

```go
type FixedJoint2 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec2
	// contains filtered or unexported fields
}
```

FixedJoint2 welds two bodies together at an anchor, keeping the angle between them as it was on the first step.

<a id="FixedJoint3"></a>

<a id="FixedJoint3.A"></a>

<a id="FixedJoint3.B"></a>

<a id="FixedJoint3.AnchorA"></a>

<a id="FixedJoint3.AnchorB"></a>

### FixedJoint3

```go
type FixedJoint3 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec3
	// contains filtered or unexported fields
}
```

FixedJoint3 welds two bodies together at an anchor, keeping the rotation between them as it was on the first step.

<a id="HingeJoint3"></a>

<a id="HingeJoint3.A"></a>

<a id="HingeJoint3.B"></a>

<a id="HingeJoint3.AnchorA"></a>

<a id="HingeJoint3.AnchorB"></a>

<a id="HingeJoint3.AxisA"></a>

<a id="HingeJoint3.AxisB"></a>

<a id="HingeJoint3.MinAngle"></a>

<a id="HingeJoint3.MaxAngle"></a>

<a id="HingeJoint3.MotorSpeed"></a>

<a id="HingeJoint3.MaxMotorTorque"></a>

### HingeJoint3

```go
type HingeJoint3 struct {
	A, B               ecs.Entity
	AnchorA, AnchorB   lin.Vec3
	AxisA, AxisB       lin.Vec3
	MinAngle, MaxAngle float32
	MotorSpeed         float32
	MaxMotorTorque     float32
	// contains filtered or unexported fields
}
```

HingeJoint3 pins two bodies at an anchor and lets them turn about one axis, given in each body's frame; a zero axis means local Y. A side set to ecs.None fixes that anchor and axis in the world.

The angle is how far B has turned about the axis relative to A since the first step, by the right-hand rule, in (-π, π]. MinAngle and MaxAngle limit it; both zero means unlimited. A motor drives the angle at MotorSpeed radians per second with up to MaxMotorTorque; zero torque means no motor.

<a id="HingeJoint3.Angle"></a>

#### HingeJoint3.Angle

```go
func (j *HingeJoint3) Angle(w *ecs.World) float32
```

Angle is the hinge angle: how far B has turned about the axis relative to A since the reference pose, in radians. The first call captures that pose if the solver has not measured it yet.

<a id="Hit2"></a>

<a id="Hit2.Entity"></a>

<a id="Hit2.Point"></a>

<a id="Hit2.Normal"></a>

<a id="Hit2.Distance"></a>

### Hit2

```go
type Hit2 struct {
	Entity   ecs.Entity
	Point    lin.Vec2
	Normal   lin.Vec2
	Distance float32
}
```

Hit2 is what a query found. Distance is the fraction along the ray or sweep for casts, the penetration depth for overlaps and the gap for Nearest2.

<a id="Nearest2"></a>

#### Nearest2

```go
func Nearest2(w *ecs.World, point lin.Vec2, radius float32, mask uint32) (Hit2, bool)
```

Nearest2 finds the collider closest to a point within radius: Point is the nearest point on its outline, Normal points from there toward the query point (zero when the point is inside) and Distance is how far.

<a id="OverlapBox2"></a>

#### OverlapBox2

```go
func OverlapBox2(w *ecs.World, center lin.Vec2, halfW, halfH, rot float32, mask uint32) []Hit2
```

OverlapBox2 returns every collider a rotated rectangle overlaps.

<a id="OverlapCircle2"></a>

#### OverlapCircle2

```go
func OverlapCircle2(w *ecs.World, center lin.Vec2, radius float32, mask uint32) []Hit2
```

OverlapCircle2 returns every collider a circle overlaps.

<a id="OverlapShape2"></a>

#### OverlapShape2

```go
func OverlapShape2(w *ecs.World, s Shape2, pos lin.Vec2, rot float32, mask uint32) []Hit2
```

OverlapShape2 returns every collider the shape overlaps when placed at pos with rotation rot. Each hit carries the deepest contact: Point on the collider, Normal pointing from the collider back toward the shape and Distance the penetration depth. Triggers are included. s must be non-nil. rot is radians; mask zero includes every collider layer.

<a id="OverlapShape2Into"></a>

#### OverlapShape2Into

```go
func OverlapShape2Into(out []Hit2, w *ecs.World, s Shape2, pos lin.Vec2, rot float32, mask uint32) []Hit2
```

OverlapShape2Into appends every collider the shape overlaps to out and returns out. Pass the previous result truncated with \[:0] to reuse its storage; pass nil for a fresh slice. Result and scratch buffers may allocate on initial use or growth. OverlapShape2's contracts apply.

<a id="Raycast2"></a>

#### Raycast2

```go
func Raycast2(w *ecs.World, r Ray2, mask uint32) (Hit2, bool)
```

Raycast2 finds the nearest collider along the ray, ignoring triggers and colliders the mask excludes.

Example:

```go
package main

import (
	"fmt"

	"github.com/matjam/bunyip/ecs"
	"github.com/matjam/bunyip/gfx"
	"github.com/matjam/bunyip/lin"
	"github.com/matjam/bunyip/phys"
)

func main() {
	w := ecs.NewWorld()
	w.AddSystem("physics", phys.System2)
	w.SpawnWith(gfx.At2(100, 0), phys.Collider2{Shape: phys.Box2{HalfW: 10, HalfH: 10}})
	w.Update(1.0 / 60)
	hit, ok := phys.Raycast2(w, phys.Ray2{Origin: lin.V2(0, 0), Dir: lin.V2(200, 0)}, 0)
	fmt.Printf("%v at (%.0f, %.0f), normal x %.0f\n", ok, hit.Point.X, hit.Point.Y, hit.Normal.X)
}
```

Output:

```
true at (90, 0), normal x -1
```

<a id="RaycastAll2"></a>

#### RaycastAll2

```go
func RaycastAll2(w *ecs.World, r Ray2, mask uint32) []Hit2
```

RaycastAll2 returns every collider along the ray, nearest first, ignoring triggers and colliders the mask excludes. To cast repeatedly without allocating a result each time, call RaycastAll2Into.

<a id="RaycastAll2Into"></a>

#### RaycastAll2Into

```go
func RaycastAll2Into(out []Hit2, w *ecs.World, r Ray2, mask uint32) []Hit2
```

RaycastAll2Into appends every collider along the ray to out, nearest first, and returns out. Pass the previous result truncated with \[:0] to reuse its storage; pass nil for a fresh slice. The appended hits are sorted among themselves, not against what out already held.

<a id="ShapeCast2"></a>

#### ShapeCast2

```go
func ShapeCast2(w *ecs.World, s Shape2, pos lin.Vec2, rot float32, delta lin.Vec2, mask uint32) (Hit2, bool)
```

ShapeCast2 sweeps a shape from pos along delta and returns the first collider it touches: Distance is the fraction of delta travelled, Point where the surfaces meet and Normal the collider's surface normal there. Colliders already overlapping the shape at the start and triggers are ignored.

<a id="Hit3"></a>

<a id="Hit3.Entity"></a>

<a id="Hit3.Point"></a>

<a id="Hit3.Normal"></a>

<a id="Hit3.Distance"></a>

### Hit3

```go
type Hit3 struct {
	Entity   ecs.Entity
	Point    lin.Vec3
	Normal   lin.Vec3
	Distance float32
}
```

Hit3 is what a query found. Distance is the fraction along the ray or sweep for casts, the penetration depth for overlaps and the gap for Nearest3.

<a id="Nearest3"></a>

#### Nearest3

```go
func Nearest3(w *ecs.World, point lin.Vec3, radius float32, mask uint32) (Hit3, bool)
```

Nearest3 finds the collider closest to a point within radius: Point is the nearest point on its surface, Normal points from there toward the query point (zero when the point is inside) and Distance is how far.

<a id="OverlapBox3"></a>

#### OverlapBox3

```go
func OverlapBox3(w *ecs.World, center, half lin.Vec3, rot lin.Quat, mask uint32) []Hit3
```

OverlapBox3 returns every collider an oriented box overlaps.

<a id="OverlapShape3"></a>

#### OverlapShape3

```go
func OverlapShape3(w *ecs.World, s Shape3, pos lin.Vec3, rot lin.Quat, mask uint32) []Hit3
```

OverlapShape3 returns every collider the shape overlaps when placed at pos with rotation rot. Each hit carries the deepest contact: Point on the collider, Normal pointing from the collider back toward the shape and Distance the penetration depth. Triggers are included. s must be non-nil. A zero rot is identity; mask zero includes every collider layer.

<a id="OverlapShape3Into"></a>

#### OverlapShape3Into

```go
func OverlapShape3Into(out []Hit3, w *ecs.World, s Shape3, pos lin.Vec3, rot lin.Quat, mask uint32) []Hit3
```

OverlapShape3Into appends every collider the shape overlaps to out and returns out. Pass the previous result truncated with \[:0] to reuse its storage; pass nil for a fresh slice. Result and scratch buffers may allocate on initial use or growth. OverlapShape3's contracts apply.

<a id="OverlapSphere3"></a>

#### OverlapSphere3

```go
func OverlapSphere3(w *ecs.World, center lin.Vec3, radius float32, mask uint32) []Hit3
```

OverlapSphere3 returns every collider a sphere overlaps.

<a id="Raycast3"></a>

#### Raycast3

```go
func Raycast3(w *ecs.World, r Ray3, mask uint32) (Hit3, bool)
```

Raycast3 finds the nearest collider along the ray, ignoring triggers and colliders the mask excludes.

<a id="RaycastAll3"></a>

#### RaycastAll3

```go
func RaycastAll3(w *ecs.World, r Ray3, mask uint32) []Hit3
```

RaycastAll3 returns every collider along the ray, nearest first, ignoring triggers and colliders the mask excludes. To cast repeatedly without allocating a result each time, call RaycastAll3Into.

<a id="RaycastAll3Into"></a>

#### RaycastAll3Into

```go
func RaycastAll3Into(out []Hit3, w *ecs.World, r Ray3, mask uint32) []Hit3
```

RaycastAll3Into appends every collider along the ray to out, nearest first, and returns out. Pass the previous result truncated with \[:0] to reuse its storage; pass nil for a fresh slice. The appended hits are sorted among themselves, not against what out already held.

<a id="ShapeCast3"></a>

#### ShapeCast3

```go
func ShapeCast3(w *ecs.World, s Shape3, pos lin.Vec3, rot lin.Quat, delta lin.Vec3, mask uint32) (Hit3, bool)
```

ShapeCast3 sweeps a shape from pos along delta and returns the first collider it touches: Distance is the fraction of delta travelled, Point where the surfaces meet and Normal the collider's surface normal there. Colliders already overlapping the shape at the start and triggers are ignored.

<a id="Layers"></a>

<a id="Layers.Layer"></a>

<a id="Layers.Mask"></a>

### Layers

```go
type Layers struct {
	Layer uint32
	Mask  uint32
}
```

Layers restrict which colliders meet: two colliders collide when each one's Layer bits appear in the other's Mask. Zero means "all".

<a id="MeshShape"></a>

<a id="MeshShape.Vertices"></a>

<a id="MeshShape.Indices"></a>

### MeshShape

```go
type MeshShape struct {
	Vertices []lin.Vec3
	Indices  []uint32
	// contains filtered or unexported fields
}
```

MeshShape is a triangle mesh for static geometry such as terrain and level walls: Indices are triples into Vertices, and either winding is fine since triangles collide from both sides. Bodies do not carry meshes; dynamic shapes collide against them. NewMeshShape builds the triangle tree once. A literal MeshShape builds it on first use and keeps it by the identity of the slices, so do not change them after.

<a id="NewMeshShape"></a>

#### NewMeshShape

```go
func NewMeshShape(vertices []lin.Vec3, indices []uint32) MeshShape
```

NewMeshShape makes a mesh collider with its triangle tree built. It retains vertices and indices without copying. Treat both slices as immutable after construction; build a new MeshShape to change geometry.

<a id="Part3"></a>

<a id="Part3.Shape"></a>

<a id="Part3.Offset"></a>

<a id="Part3.Rotation"></a>

### Part3

```go
type Part3 struct {
	Shape    Shape3
	Offset   lin.Vec3
	Rotation lin.Quat // zero means none
}
```

Part3 is one shape of a Compound3, placed in the body's frame.

<a id="PlacedShape2"></a>

### PlacedShape2

```go
type PlacedShape2 struct {
	// contains filtered or unexported fields
}
```

PlacedShape2 is a 2D shape placed in the world once, so that many points can be measured against it without placing it again for each one: a polygon's world points and edge normals and a capsule's segment are worked out when it is placed. The zero value measures nothing.

<a id="PlaceShape2"></a>

#### PlaceShape2

```go
func PlaceShape2(s Shape2, pos lin.Vec2, rot float32) PlacedShape2
```

PlaceShape2 places a shape at pos with rotation rot, in radians, for measuring. To measure many points against one collider, such as every particle of a fluid against a wall, call it once and call SignedDistance for each point. A polygon of more than sixteen points allocates when placed.

<a id="PlacedShape2.Bounds"></a>

#### PlacedShape2.Bounds

```go
func (p *PlacedShape2) Bounds() (lo, hi lin.Vec2)
```

Bounds returns the world box around the placed shape.

<a id="PlacedShape2.SignedDistance"></a>

#### PlacedShape2.SignedDistance

```go
func (p *PlacedShape2) SignedDistance(point lin.Vec2) (dist float32, normal lin.Vec2, ok bool)
```

SignedDistance measures a point against the placed shape. It returns exactly what SignedDistance2 returns for the shape, position and rotation the shape was placed with, and ok false for the same shapes.

<a id="PlacedShape3"></a>

### PlacedShape3

```go
type PlacedShape3 struct {
	// contains filtered or unexported fields
}
```

PlacedShape3 is a shape placed in the world once, so that many points can be measured against it without placing it again for each one: the rotation, a box's inverse rotation and a capsule's segment are worked out when it is placed. The zero value measures nothing.

<a id="PlaceShape3"></a>

#### PlaceShape3

```go
func PlaceShape3(s Shape3, pos lin.Vec3, rot lin.Quat) PlacedShape3
```

PlaceShape3 places a shape at pos with rotation rot for measuring. A zero rot is the identity. To measure many points against one collider, such as every particle of a cloth against a solid, call it once and call SignedDistance for each point. A compound still places its parts on each call.

<a id="PlacedShape3.Bounds"></a>

#### PlacedShape3.Bounds

```go
func (p *PlacedShape3) Bounds() (lo, hi lin.Vec3)
```

Bounds returns the world box around the placed shape, the region outside which a point is at least as far from the shape as it is from the box. A nil shape has empty bounds at the origin.

<a id="PlacedShape3.SignedDistance"></a>

#### PlacedShape3.SignedDistance

```go
func (p *PlacedShape3) SignedDistance(point lin.Vec3) (dist float32, normal lin.Vec3, ok bool)
```

SignedDistance measures a point against the placed shape. It returns exactly what SignedDistance3 returns for the shape, position and rotation the shape was placed with, and ok false for the same shapes.

<a id="Polygon2"></a>

<a id="Polygon2.Points"></a>

### Polygon2

```go
type Polygon2 struct{ Points []lin.Vec2 }
```

Polygon2 is a convex polygon with points in the body's frame, in any winding order.

<a id="PrismaticJoint2"></a>

<a id="PrismaticJoint2.A"></a>

<a id="PrismaticJoint2.B"></a>

<a id="PrismaticJoint2.AnchorA"></a>

<a id="PrismaticJoint2.AnchorB"></a>

<a id="PrismaticJoint2.Axis"></a>

<a id="PrismaticJoint2.Min"></a>

<a id="PrismaticJoint2.Max"></a>

<a id="PrismaticJoint2.MotorSpeed"></a>

<a id="PrismaticJoint2.MaxMotorForce"></a>

<a id="PrismaticJoint2.Stiffness"></a>

<a id="PrismaticJoint2.Damping"></a>

### PrismaticJoint2

```go
type PrismaticJoint2 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec2
	Axis             lin.Vec2
	Min, Max         float32
	MotorSpeed       float32
	MaxMotorForce    float32
	Stiffness        float32
	Damping          float32
	// contains filtered or unexported fields
}
```

PrismaticJoint2 is a slider: two bodies may only move along one axis relative to each other, and keep the angle they had on the first step. Axis is the slide direction in A's frame and a zero axis means local X. AnchorA and AnchorB are in each body's frame; a side set to ecs.None fixes that anchor and the axis in the world.

The translation is how far B's anchor sits from A's along the axis, so it is zero when the anchors meet. Min and Max limit it; both zero means unlimited. A motor drives the translation at MotorSpeed units per second with up to MaxMotorForce; zero force means no motor. A spring pulls the translation back toward zero with Stiffness as the force per unit of travel and Damping as the force per unit of speed; zero stiffness means no spring.

<a id="PrismaticJoint2.Translation"></a>

#### PrismaticJoint2.Translation

```go
func (j *PrismaticJoint2) Translation(w *ecs.World) float32
```

Translation is how far B's anchor has slid from A's along the axis, in world units.

<a id="PrismaticJoint3"></a>

<a id="PrismaticJoint3.A"></a>

<a id="PrismaticJoint3.B"></a>

<a id="PrismaticJoint3.AnchorA"></a>

<a id="PrismaticJoint3.AnchorB"></a>

<a id="PrismaticJoint3.Axis"></a>

<a id="PrismaticJoint3.Min"></a>

<a id="PrismaticJoint3.Max"></a>

<a id="PrismaticJoint3.MotorSpeed"></a>

<a id="PrismaticJoint3.MaxMotorForce"></a>

<a id="PrismaticJoint3.Stiffness"></a>

<a id="PrismaticJoint3.Damping"></a>

### PrismaticJoint3

```go
type PrismaticJoint3 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec3
	Axis             lin.Vec3
	Min, Max         float32
	MotorSpeed       float32
	MaxMotorForce    float32
	Stiffness        float32
	Damping          float32
	// contains filtered or unexported fields
}
```

PrismaticJoint3 is a slider: two bodies may only move along one axis relative to each other, and keep the rotation they had on the first step. Axis is the slide direction in A's frame and a zero axis means local X. AnchorA and AnchorB are in each body's frame; a side set to ecs.None fixes that anchor and the axis in the world.

The translation is how far B's anchor sits from A's along the axis, so it is zero when the anchors meet. Min and Max limit it; both zero means unlimited. A motor drives the translation at MotorSpeed units per second with up to MaxMotorForce; zero force means no motor. A spring pulls the translation back toward zero with Stiffness as the force per unit of travel and Damping as the force per unit of speed; zero stiffness means no spring.

<a id="PrismaticJoint3.Translation"></a>

#### PrismaticJoint3.Translation

```go
func (j *PrismaticJoint3) Translation(w *ecs.World) float32
```

Translation is how far B's anchor has slid from A's along the axis, in world units.

<a id="Ragdoll3"></a>

<a id="Ragdoll3.Parts"></a>

<a id="Ragdoll3.Joints"></a>

<a id="Ragdoll3.Bones"></a>

### Ragdoll3

```go
type Ragdoll3 struct {
	// Parts maps a part name to its entity.
	Parts map[string]ecs.Entity
	// Joints maps a part name to the joint entity tying it to its
	// parent; the pelvis has none. Waist, neck, shoulder and hip joints
	// are BallJoint3, elbows and knees HingeJoint3.
	Joints map[string]ecs.Entity
	// Bones records each part's size as built, so a game can place the
	// centre of a part from the position of its joint.
	Bones map[string]RagdollBone
}
```

Ragdoll3 is a spawned humanoid: capsule bodies for the parts, joined by ball joints at the waist, neck, shoulders and hips and limited hinges at the elbows and knees. Every part's capsule runs along its local Y with the parent joint at the top, and every part starts with the spec's rotation, so a standing figure has all its parts upright.

<a id="NewRagdoll3"></a>

#### NewRagdoll3

```go
func NewRagdoll3(w *ecs.World, spec RagdollSpec) *Ragdoll3
```

NewRagdoll3 spawns the parts and joints of a humanoid ragdoll and returns them by name. Each part carries a gfx.Transform, a Body3 and a Collider3 with a Capsule.

<a id="Ragdoll3.Despawn"></a>

#### Ragdoll3.Despawn

```go
func (r *Ragdoll3) Despawn(w *ecs.World)
```

Despawn removes every part and joint.

<a id="Ragdoll3.Entities"></a>

#### Ragdoll3.Entities

```go
func (r *Ragdoll3) Entities() []ecs.Entity
```

Entities returns every part and joint entity, parts first.

<a id="Ragdoll3.Pose"></a>

#### Ragdoll3.Pose

```go
func (r *Ragdoll3) Pose(w *ecs.World, positions map[string]lin.Vec3, rotations map[string]lin.Quat)
```

Pose places the parts at once and brings them to rest, to hand an animated character over to physics: positions are part centres and rotations part rotations in the world, by part name; a part missing from a map keeps what it has. A game with a bone's world position and rotation finds the centre of the part hanging from it as the bone position plus the rotation applied to (0, -Length/2, 0), with Length from Bones.

<a id="RagdollBone"></a>

<a id="RagdollBone.Length"></a>

<a id="RagdollBone.Radius"></a>

### RagdollBone

```go
type RagdollBone struct{ Length, Radius float32 }
```

RagdollBone sizes one part of a ragdoll: the distance from one end of its capsule to the other and the capsule's radius.

<a id="RagdollSpec"></a>

<a id="RagdollSpec.Position"></a>

<a id="RagdollSpec.Rotation"></a>

<a id="RagdollSpec.Height"></a>

<a id="RagdollSpec.Mass"></a>

<a id="RagdollSpec.Friction"></a>

<a id="RagdollSpec.Damping"></a>

<a id="RagdollSpec.Layers"></a>

<a id="RagdollSpec.Pelvis"></a>

<a id="RagdollSpec.Spine"></a>

<a id="RagdollSpec.Head"></a>

<a id="RagdollSpec.UpperArm"></a>

<a id="RagdollSpec.Forearm"></a>

<a id="RagdollSpec.Thigh"></a>

<a id="RagdollSpec.Shin"></a>

### RagdollSpec

```go
type RagdollSpec struct {
	// Position is the point on the ground between the feet and Rotation
	// turns the whole figure, which stands facing -Z with +X on its
	// right.
	Position lin.Vec3
	Rotation lin.Quat
	// Height scales the default bone sizes; zero means 1.8.
	Height float32
	// Mass is the total mass, shared between the parts in human
	// proportions; zero means 70.
	Mass float32
	// Friction and Damping apply to every part; zero friction means 0.6
	// and zero damping means 0.5 per second.
	Friction float32
	Damping  float32
	// Layers apply to every part. Zero puts the ragdoll on a layer of
	// its own that meets everything except other ragdoll parts, so
	// neighbouring limbs do not fight their joints.
	Layers Layers
	// Bone sizes; a zero field takes the default scaled by Height.
	Pelvis, Spine, Head, UpperArm, Forearm, Thigh, Shin RagdollBone
}
```

RagdollSpec describes a humanoid ragdoll for NewRagdoll3. Zero fields take the defaults of a figure 1.8 units tall.

<a id="Ray2"></a>

<a id="Ray2.Origin"></a>

<a id="Ray2.Dir"></a>

### Ray2

```go
type Ray2 struct {
	Origin, Dir lin.Vec2 // Dir need not be unit length
}
```

Ray2 describes a finite cast from Origin to Origin+Dir. Dir is the full displacement; a hit's Distance is its fraction in \[0, 1].

<a id="Ray3"></a>

<a id="Ray3.Origin"></a>

<a id="Ray3.Dir"></a>

### Ray3

```go
type Ray3 struct {
	Origin, Dir lin.Vec3 // Dir need not be unit length
}
```

Ray3 describes a finite cast from Origin to Origin+Dir. Dir is the full displacement; a hit's Distance is its fraction in \[0, 1].

<a id="RevoluteJoint2"></a>

<a id="RevoluteJoint2.A"></a>

<a id="RevoluteJoint2.B"></a>

<a id="RevoluteJoint2.AnchorA"></a>

<a id="RevoluteJoint2.AnchorB"></a>

<a id="RevoluteJoint2.MinAngle"></a>

<a id="RevoluteJoint2.MaxAngle"></a>

<a id="RevoluteJoint2.MotorSpeed"></a>

<a id="RevoluteJoint2.MaxMotorTorque"></a>

### RevoluteJoint2

```go
type RevoluteJoint2 struct {
	A, B               ecs.Entity
	AnchorA, AnchorB   lin.Vec2
	MinAngle, MaxAngle float32
	MotorSpeed         float32
	MaxMotorTorque     float32
	// contains filtered or unexported fields
}
```

RevoluteJoint2 pins two bodies together at an anchor so they turn freely about it. A side set to ecs.None fixes that anchor in the world.

The angle is how far B has turned relative to A since the first step or first Angle call, positive from +X toward +Y (clockwise on screen), in (-π, π]. MinAngle and MaxAngle limit it; both zero means unlimited. A motor drives the angle at MotorSpeed radians per second with up to MaxMotorTorque; zero torque means no motor.

<a id="RevoluteJoint2.Angle"></a>

#### RevoluteJoint2.Angle

```go
func (j *RevoluteJoint2) Angle(w *ecs.World) float32
```

Angle is the joint angle: how far B has turned relative to A since the reference pose, in radians. The first call captures that pose if the solver has not measured it yet.

<a id="Settings2"></a>

<a id="Settings2.Gravity"></a>

<a id="Settings2.Substeps"></a>

<a id="Settings2.Iterations"></a>

<a id="Settings2.SleepTime"></a>

<a id="Settings2.SleepThreshold"></a>

### Settings2

```go
type Settings2 struct {
	Gravity    lin.Vec2 // world units per second squared; zero disables gravity
	Substeps   int      // integration steps per update; more is stabler
	Iterations int      // solver passes per step; more is stiffer
	// SleepTime is how long a body and everything touching it must rest
	// before they sleep and drop out of the simulation until touched;
	// zero means bodies never sleep. Half a second suits most games.
	SleepTime float32
	// SleepThreshold is the speed (units and radians per second) below
	// which a body counts as resting; zero means 0.05.
	SleepThreshold float32
}
```

Settings2 is the world resource that tunes 2D simulation. Zero substeps or iterations mean 4 and 8.

<a id="Settings3"></a>

<a id="Settings3.Gravity"></a>

<a id="Settings3.Substeps"></a>

<a id="Settings3.Iterations"></a>

<a id="Settings3.SleepTime"></a>

<a id="Settings3.SleepThreshold"></a>

### Settings3

```go
type Settings3 struct {
	Gravity    lin.Vec3 // world units per second squared; zero disables gravity
	Substeps   int      // integration steps per update; nonpositive means 4
	Iterations int      // solver passes per substep; nonpositive means 8
	// SleepTime is how long a body and everything touching it must rest
	// before they sleep and drop out of the simulation until touched;
	// zero means bodies never sleep. Half a second suits most games.
	SleepTime float32
	// SleepThreshold is the speed, in units per second, below which a
	// body counts as resting: both its own speed and the speed its turning
	// gives the point of its collider farthest from its centre must be
	// slower. Zero means 0.05.
	SleepThreshold float32
}
```

Settings3 is the world resource that tunes 3D simulation. Zero substeps or iterations mean 4 and 8.

<a id="Shape2"></a>

### Shape2

```go
type Shape2 interface {
	// contains filtered or unexported methods
}
```

Shape2 is a collider outline in the body's local frame.

<a id="Shape3"></a>

### Shape3

```go
type Shape3 interface {
	// contains filtered or unexported methods
}
```

Shape3 is a collider volume in the body's local frame.

<a id="Sphere"></a>

<a id="Sphere.Radius"></a>

### Sphere

```go
type Sphere struct{ Radius float32 }
```

Sphere is a ball centred on the body.

<a id="SpringJoint2"></a>

<a id="SpringJoint2.A"></a>

<a id="SpringJoint2.B"></a>

<a id="SpringJoint2.AnchorA"></a>

<a id="SpringJoint2.AnchorB"></a>

<a id="SpringJoint2.RestLength"></a>

<a id="SpringJoint2.Stiffness"></a>

<a id="SpringJoint2.Damping"></a>

### SpringJoint2

```go
type SpringJoint2 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec2
	RestLength       float32
	Stiffness        float32
	Damping          float32
	// contains filtered or unexported fields
}
```

SpringJoint2 pulls two anchors toward a rest length with a damped spring force. RestLength zero measures it on the first step; zero Stiffness means 10 and Damping is the velocity coefficient.

<a id="SpringJoint3"></a>

<a id="SpringJoint3.A"></a>

<a id="SpringJoint3.B"></a>

<a id="SpringJoint3.AnchorA"></a>

<a id="SpringJoint3.AnchorB"></a>

<a id="SpringJoint3.RestLength"></a>

<a id="SpringJoint3.Stiffness"></a>

<a id="SpringJoint3.Damping"></a>

### SpringJoint3

```go
type SpringJoint3 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec3
	RestLength       float32
	Stiffness        float32
	Damping          float32
	// contains filtered or unexported fields
}
```

SpringJoint3 pulls two anchors toward a rest length with a damped spring force. RestLength zero measures it on the first step; zero Stiffness means 10 and Damping is the velocity coefficient.

<a id="Trigger2"></a>

<a id="Trigger2.Trigger"></a>

<a id="Trigger2.Other"></a>

### Trigger2

```go
type Trigger2 struct {
	Trigger, Other ecs.Entity
}
```

Trigger2 is emitted while a trigger collider overlaps another collider. A pair is reported in its first overlapping substep of the update; when both colliders are triggers, each receives its own event.

<a id="Trigger3"></a>

<a id="Trigger3.Trigger"></a>

<a id="Trigger3.Other"></a>

### Trigger3

```go
type Trigger3 struct {
	Trigger, Other ecs.Entity
}
```

Trigger3 is emitted while a trigger collider overlaps another collider. A pair is reported in its first overlapping substep of the update; when both colliders are triggers, each receives its own event.

<a id="WheelJoint2"></a>

<a id="WheelJoint2.A"></a>

<a id="WheelJoint2.B"></a>

<a id="WheelJoint2.AnchorA"></a>

<a id="WheelJoint2.AnchorB"></a>

<a id="WheelJoint2.Axis"></a>

<a id="WheelJoint2.Frequency"></a>

<a id="WheelJoint2.DampingRatio"></a>

<a id="WheelJoint2.Min"></a>

<a id="WheelJoint2.Max"></a>

<a id="WheelJoint2.MotorSpeed"></a>

<a id="WheelJoint2.MaxMotorTorque"></a>

### WheelJoint2

```go
type WheelJoint2 struct {
	A, B             ecs.Entity
	AnchorA, AnchorB lin.Vec2
	Axis             lin.Vec2
	Frequency        float32
	DampingRatio     float32
	Min, Max         float32
	MotorSpeed       float32
	MaxMotorTorque   float32
}
```

WheelJoint2 is a wheel on a suspension: B may spin freely and slide along one axis of A, and is held on that line in every other direction. A is the chassis and B the wheel. Axis is the suspension direction in A's frame and a zero axis means local Y. AnchorA and AnchorB are in each body's frame, so AnchorA is where the wheel sits when the suspension is at rest; a side set to ecs.None fixes that anchor and the axis in the world.

The spring along the axis is tuned by Frequency in hertz and DampingRatio, where 1 is critically damped; zero frequency means no spring and zero DampingRatio means 0.7. Min and Max limit the travel along the axis; both zero means unlimited. A motor drives B's spin at MotorSpeed radians per second with up to MaxMotorTorque; zero torque means no motor.

<a id="WheelJoint2.Translation"></a>

#### WheelJoint2.Translation

```go
func (j *WheelJoint2) Translation(w *ecs.World) float32
```

Translation is how far the suspension has moved from its rest position, in world units. It is negative while the spring is compressed toward A.

## Examples

Example:

```go
package main

import (
	"fmt"

	"github.com/matjam/bunyip/ecs"
	"github.com/matjam/bunyip/gfx"
	"github.com/matjam/bunyip/lin"
	"github.com/matjam/bunyip/phys"
)

func main() {
	w := ecs.NewWorld()
	w.SetResource(phys.Settings3{Gravity: lin.V3(0, -9.8, 0)})
	w.AddSystem("physics", phys.System3)

	// A static floor (collider, no body) and a ball dropped onto it.
	w.SpawnWith(gfx.Transform{}, phys.Collider3{Shape: phys.Box3{Half: lin.V3(10, 0.5, 10)}})
	ball := w.SpawnWith(gfx.At(0, 5, 0), phys.Dynamic3(1), phys.Collider3{Shape: phys.Sphere{Radius: 0.5}})
	for range 180 {
		w.Update(1.0 / 60)
	}
	t, _ := w.Get[gfx.Transform](ball)
	fmt.Printf("ball rests at y = %.1f\n", t.Position.Y)
}
```

Output:

```
ball rests at y = 1.0
```
