Skip to content
View source

physicsGenerated

Category: Packages · Manifest: use "kernels/";

Rigid circles and boxes in the plane that fall, collide, rest, slide and bounce.

Rigid circles and boxes in the plane that fall, collide, rest, slide and bounce: pairs found through a grid, manifolds solved all at once over substeps.

Layer: Simulation. Uses: parallel.

use "physics.entpkg";
  • kernels/body.ent — Rigid bodies in the plane.
  • kernels/broad_phase.ent — Finding pairs. Kernels: physics.bounds@1, physics.spans@1, physics.owners@1, physics.cells@1, physics.cell_counts@1, physics.places@1, physics.no_entries@1, physics.pair_counts@1, physics.no_pairs@1, physics.pairs@1.
  • kernels/contact.ent — Colliding. Kernels: physics.collide@1, physics.shared@1, physics.no_counts@1, physics.no_pushes@1.
  • kernels/query.ent — Asking the world. Kernels: physics.ray@1, physics.no_contacts@1.
  • kernels/solve.ent — Solving. Kernels: physics.warm@1, physics.solve@1, physics.bounce@1, physics.pushes@1, physics.push@1, physics.fall@1, physics.move@1.
  • graphs/step.esn — One step of a world of bodies, dt long.
  • graphs/substep.esn — One substep of step.esn.

tests/ holds scenes and their replays, run on every backend: many.replay, motion.replay, pile.replay, rest.replay, roll.replay, wide.replay. Every Kernel of the package is reached by one of them.

Used by the physics example.

Kernel Mode Brief
physics.bounce@1 map Each manifold’s bounce: the points that closed faster than threshold and push, given back the restitution of what they closed at.
physics.bounds@1 map Each body’s box, grown by margin and by how far it may move in the step.
physics.cell_counts@1 scatter into input 1 with sum How many entries each cell holds.
physics.cells@1 map The cell each entry is, a body’s cells in rows.
physics.collide@1 map Each pair’s manifold. A pair keeps points up to margin apart and as far as the two may close in the step; a sensor’s only where they touch. A point starts from the impulses the pair’s point there held in the last step, held, so a resting stack is pushed as hard as it was a step ago.
physics.fall@1 map Each moving body pulled by gravity for a substep and slowed by damping a second.
physics.move@1 map Each body moved by its velocity and turned by its spin for a substep.
physics.no_contacts@1 map No manifolds: what a world’s held starts from.
physics.no_counts@1 map A zero for each body.
physics.no_entries@1 map A zero for each entry.
physics.no_pairs@1 map Pairs of nothing, to be filled.
physics.no_pushes@1 map No push for each body.
physics.owners@1 map The body each entry is.
physics.pair_counts@1 map How many pairs each body is the higher of.
physics.pairs@1 scatter into input 12 with max The pairs, each body’s in its part of the list, so the list is in order of the higher body: the walk physics.pair_counts@1 counts.
physics.places@1 scatter into input 1 with max Where each entry is in the sorted order.
physics.push@1 map Each body with its pushes: its velocity and spin changed by them.
physics.pushes@1 scatter into input 1 with sum The pushes the manifolds give each body, summed.
physics.ray@1 map The nearest body each ray meets: sensors are passed through.
physics.shared@1 scatter into input 1 with sum How many manifolds push each body, among which its mass is split.
physics.solve@1 map Each manifold solved against its copies of its bodies: the normal impulses, pushing apart what overlaps unless relax, then friction; with ahead, the impulses it then holds pushed again for the next substep.
physics.spans@1 map How many cells each body’s box covers.
physics.warm@1 map Each manifold’s push with by times the impulses it holds: once to warm a step’s first substep, once less to take back the warm its last substep gave a substep that does not come. A pass of its own, so every body is pushed by every manifold before the next pass reads it.
Function Brief
circle(position: Vec2, radius: Float, density: Float) -> Body A circle of density per unit area; no density makes it static.
box(position: Vec2, half: Vec2, angle: Float, density: Float) -> Body A box of half extents half, turned by angle, of density per unit area; no density makes it static.
touching(m: Manifold, slop: Float) -> Bool Whether a manifold’s bodies touch rather than only close on each other: a point within slop of touching.
turn(v: Vec2, angle: Float) -> Vec2
unturn(v: Vec2, angle: Float) -> Vec2
wedge(a: Vec2, b: Vec2) -> Float
swirl(w: Float, r: Vec2) -> Vec2
arm_angle(b: Body) -> Float
extent(b: Body) -> Float
sweep(b: Body, dt: Float) -> Float
cell_at(p: Vec2, origin: Vec2, cell: Float, columns: Int, rows: Int) -> IVec2
meets(a: Body, b: Body) -> Bool
paired(i: Int, j: Int, c: Int, bodies: Rows<Body>, bounds: Rows<Bounds>, columns: Int) -> Bool
before(e: Int, places: Rows<Int>, keys: Rows<Int>, cell_ends: Rows<Int>, cell_counts: Rows<Int>) -> IVec3
apart() -> Touch
circles(a: Body, b: Body) -> Touch
box_circle(a: Body, b: Body) -> Touch
clip(v0: Vec2, v1: Vec2, normal: Vec2, offset: Float) -> Clipped
incident(h: Vec2, p: Vec2, x: Vec2, y: Vec2, normal: Vec2) -> Clipped
boxes(a: Body, b: Body, margin: Float) -> Touch
touch(a: Body, b: Body, margin: Float) -> Touch
holding(a: Body, b: Body, c: Vec2, s: Float, n: Vec2) -> Contact
last_of(held: Rows<Manifold>, a: Int, b: Int) -> Int
carried(p: Contact, last: Manifold, n: Vec2, near: Float, round: Bool) -> Contact
solid(m: Manifold) -> Bool
ray_circle(o: Vec2, d: Vec2, c: Vec2, r: Float) -> Float
ray_box(o: Vec2, d: Vec2, h: Vec2) -> Vec3
copy_of(b: Body, shared: Rows<Int>, i: Int) -> Copy
pushed(c: Copy, p: Vec2, r: Vec2) -> Copy
closing(both: Both, ra: Vec2, rb: Vec2) -> Vec2
apply(both: Both, p: Vec2, ra: Vec2, rb: Vec2) -> Both
inverse_along(both: Both, ra: Vec2, rb: Vec2, d: Vec2) -> Float
unsplit(both: Both, ra: Vec2, rb: Vec2, d: Vec2) -> Float
softness(h: Float, hertz: Float, ratio: Float) -> Vec3
solve_normal(pt: Contact, both: Both, a: Body, b: Body, n: Vec2, h: Float, relax: Bool, soft: Vec3, speed: Float) -> Solved
solve_tangent(pt: Contact, both: Both, a: Body, b: Body, n: Vec2, friction: Float) -> Solved
warm(pt: Contact, both: Both, a: Body, b: Body, n: Vec2, by: Float) -> Both
warmed(m: Manifold, both: Both, a: Body, b: Body, by: Float) -> Both
bounce(pt: Contact, both: Both, a: Body, b: Body, n: Vec2, e: Float, threshold: Float) -> Solved
settled(m: Manifold, both: Both, a: Body, b: Body) -> Manifold
nothing(m: Manifold) -> Manifold
substep(dt: Float, substeps: Int) -> Float
Name Syntax
BodyShape type BodyShape = enum { Circle, Box };
Body struct Body
Bounds struct Bounds { lo: Vec2; hi: Vec2; first: IVec2; last: IVec2; }
Pair struct Pair { a: Int; b: Int; }
Counted struct Counted { at: Int; value: Int; }
Contact struct Contact
Manifold struct Manifold
Push struct Push { at: Int; value: Vec3; }
Ray struct Ray { origin: Vec2; direction: Vec2; length: Float; mask: Int; }
Hit struct Hit { body: Int; fraction: Float; point: Vec2; normal: Vec2; }
Touch struct Touch { normal: Vec2; count: Int; c1: Vec2; s1: Float; c2: Vec2; s2: Float; }
Clipped struct Clipped { v0: Vec2; v1: Vec2; n: Int; }
Copy struct Copy { velocity: Vec2; spin: Float; mass: Float; inertia: Float; share: Float; }
Both struct Both { a: Copy; b: Copy; }
Solved struct Solved { point: Contact; both: Both; }
Name Interface Description
step input bodies: Rows<Body>
input held: Rows<Manifold>
param dt: Float = 0.0166667
param substeps: Int = 8
param gravity: Vec2 = vec2(0.0, -10.0)
param damping: Float = 0.0
param margin: Float = 0.02
param hertz: Float = 30.0
param ratio: Float = 10.0
param speed: Float = 3.0
param threshold: Float = 1.0
param origin: Vec2 = vec2(-32.0, -32.0)
param cell: Float = 1.0
param columns: Int = 64
param rows: Int = 64
param bits: Int = 12
output result <- bounced.result
output contacts <- bounce.result
One step of a world of bodies, dt long: node none: physics.no_contacts@1 { domain = 1; } node world: graph “physics.entpkg/graphs/step.esn” { bodies <~ world.result from start.result; held <~ world.contacts from none.result; } result is the bodies stepped and contacts the manifolds that stepped them, whose touching says what touches what; a world is given its last step’s as held, which each step starts from. The grid of columns by rows cells of side cell from origin should cover where the bodies are, a cell about the size of a common body; one outside it is entered in the edge cells. bits is enough for columns * rows, which the graph requires. substeps are the passes a step takes, more for a pile many bodies deep that lands at once; hertz is how stiff a contact is, higher for a deep pile to sink into itself less. A step finds contacts where the bodies are at its start, so a box turning much of a turn in one step (150 radians a second at 30 m/s) may pass through a thin wall a corner swings across.
substep input bodies: Rows<Body>
input manifolds: Rows<Manifold>
input shared: Rows<Int>
input zeros: Rows<Vec3>
param dt: Float = 0.0166667
param substeps: Int = 8
param gravity: Vec2 = vec2(0.0, -10.0)
param damping: Float = 0.0
param hertz: Float = 30.0
param ratio: Float = 10.0
param speed: Float = 3.0
output moved <- relaxed.result
output held <- relax.result
One substep of step.esn: gravity, the manifolds solved, the bodies moved, and the manifolds solved once more without pushing apart, the impulses they then hold pushed again to warm the next substep.

Each manifold’s bounce: the points that closed faster than threshold and push, given back the restitution of what they closed at.

Mode map
Requires field.read, field.write
Inputs manifolds: Rows<Manifold>, bodies: Rows<Body>, shared: Rows<Int>
Params threshold: Float = 1.0
Outputs result: Rows<Manifold>
Source packages/physics.entpkg/kernels/solve.ent

Each body’s box, grown by margin and by how far it may move in the step.

Mode map
Requires field.read, field.write
Inputs bodies: Rows<Body>
Params dt: Float = 0.0166667, margin: Float = 0.02, origin: Vec2 = [0.0, 0.0], cell: Float = 1.0, columns: Int = 64, rows: Int = 64
Outputs result: Rows<Bounds>
Source packages/physics.entpkg/kernels/broad_phase.ent

How many entries each cell holds.

Mode scatter into input 1 with sum
Requires field.read, field.write
Inputs keys: Rows<Int>, zeros: Rows<Int>
Params —
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/broad_phase.ent

The cell each entry is, a body’s cells in rows.

Mode map
Requires field.read, field.write
Inputs owners: Rows<Int>, spans: Rows<Int>, ends: Rows<Int>, bounds: Rows<Bounds>
Params columns: Int = 64
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/broad_phase.ent

Each pair’s manifold. A pair keeps points up to margin apart and as far as the two may close in the step; a sensor’s only where they touch. A point starts from the impulses the pair’s point there held in the last step, held, so a resting stack is pushed as hard as it was a step ago.

Mode map
Requires field.read, field.write
Inputs pairs: Rows<Pair>, bodies: Rows<Body>, held: Rows<Manifold>
Params dt: Float = 0.0166667, margin: Float = 0.02
Outputs result: Rows<Manifold>
Source packages/physics.entpkg/kernels/contact.ent

Each moving body pulled by gravity for a substep and slowed by damping a second.

Mode map
Requires field.read, field.write
Inputs bodies: Rows<Body>
Params dt: Float = 0.0166667, substeps: Int = 8, gravity: Vec2 = [0.0, -10.0], damping: Float = 0.0
Outputs result: Rows<Body>
Source packages/physics.entpkg/kernels/solve.ent

Each body moved by its velocity and turned by its spin for a substep.

Mode map
Requires field.read, field.write
Inputs bodies: Rows<Body>
Params dt: Float = 0.0166667, substeps: Int = 8
Outputs result: Rows<Body>
Source packages/physics.entpkg/kernels/solve.ent

No manifolds: what a world’s held starts from.

Mode map
Requires field.read, field.write
Inputs —
Params —
Outputs result: Rows<Manifold>
Source packages/physics.entpkg/kernels/query.ent

A zero for each body.

Mode map
Requires field.read, field.write
Inputs bodies: Rows<Body>
Params —
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/contact.ent

A zero for each entry.

Mode map
Requires field.read, field.write
Inputs order: Rows<Int>
Params —
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/broad_phase.ent

Pairs of nothing, to be filled.

Mode map
Requires field.read, field.write
Inputs total: Rows<Int>
Params —
Outputs result: Rows<Pair>
Source packages/physics.entpkg/kernels/broad_phase.ent

No push for each body.

Mode map
Requires field.read, field.write
Inputs bodies: Rows<Body>
Params —
Outputs result: Rows<Vec3>
Source packages/physics.entpkg/kernels/contact.ent

The body each entry is.

Mode map
Requires field.read, field.write
Inputs total: Rows<Int>, ends: Rows<Int>
Params —
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/broad_phase.ent

How many pairs each body is the higher of.

Mode map
Requires field.read, field.write
Inputs bodies: Rows<Body>, spans: Rows<Int>, span_ends: Rows<Int>, order: Rows<Int>, places: Rows<Int>, keys: Rows<Int>, owners: Rows<Int>, cell_counts: Rows<Int>, cell_ends: Rows<Int>, bounds: Rows<Bounds>
Params columns: Int = 64
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/broad_phase.ent

The pairs, each body’s in its part of the list, so the list is in order of the higher body: the walk physics.pair_counts@1 counts.

Mode scatter into input 12 with max
Requires field.read, field.write
Inputs bodies: Rows<Body>, counts: Rows<Int>, ends: Rows<Int>, spans: Rows<Int>, span_ends: Rows<Int>, order: Rows<Int>, places: Rows<Int>, keys: Rows<Int>, owners: Rows<Int>, cell_counts: Rows<Int>, cell_ends: Rows<Int>, bounds: Rows<Bounds>, slots: Rows<Pair>
Params columns: Int = 64
Outputs result: Rows<Pair>
Source packages/physics.entpkg/kernels/broad_phase.ent

Where each entry is in the sorted order.

Mode scatter into input 1 with max
Requires field.read, field.write
Inputs order: Rows<Int>, zeros: Rows<Int>
Params —
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/broad_phase.ent

Each body with its pushes: its velocity and spin changed by them.

Mode map
Requires field.read, field.write
Inputs bodies: Rows<Body>, pushes: Rows<Vec3>
Params —
Outputs result: Rows<Body>
Source packages/physics.entpkg/kernels/solve.ent

The pushes the manifolds give each body, summed.

Mode scatter into input 1 with sum
Requires field.read, field.write
Inputs manifolds: Rows<Manifold>, zeros: Rows<Vec3>
Params —
Outputs result: Rows<Vec3>
Source packages/physics.entpkg/kernels/solve.ent

The nearest body each ray meets: sensors are passed through.

Mode map
Requires field.read, field.write
Inputs rays: Rows<Ray>, bodies: Rows<Body>
Params —
Outputs result: Rows<Hit>
Source packages/physics.entpkg/kernels/query.ent

How many manifolds push each body, among which its mass is split.

Mode scatter into input 1 with sum
Requires field.read, field.write
Inputs manifolds: Rows<Manifold>, zeros: Rows<Int>
Params —
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/contact.ent

Each manifold solved against its copies of its bodies: the normal impulses, pushing apart what overlaps unless relax, then friction; with ahead, the impulses it then holds pushed again for the next substep.

Mode map
Requires field.read, field.write
Inputs manifolds: Rows<Manifold>, bodies: Rows<Body>, shared: Rows<Int>
Params dt: Float = 0.0166667, substeps: Int = 8, relax: Bool = False, ahead: Bool = False, hertz: Float = 30.0, ratio: Float = 10.0, speed: Float = 3.0
Outputs result: Rows<Manifold>
Source packages/physics.entpkg/kernels/solve.ent

How many cells each body’s box covers.

Mode map
Requires field.read, field.write
Inputs bounds: Rows<Bounds>
Params —
Outputs result: Rows<Int>
Source packages/physics.entpkg/kernels/broad_phase.ent

Each manifold’s push with by times the impulses it holds: once to warm a step’s first substep, once less to take back the warm its last substep gave a substep that does not come. A pass of its own, so every body is pushed by every manifold before the next pass reads it.

Mode map
Requires field.read, field.write
Inputs manifolds: Rows<Manifold>, bodies: Rows<Body>, shared: Rows<Int>
Params by: Float = 1.0
Outputs result: Rows<Manifold>
Source packages/physics.entpkg/kernels/solve.ent

many.replay, motion.replay, pile.replay, rest.replay, roll.replay, wide.replay