# Gridiron geometry

The football family's dependency-free maths: the ball as a real prolate spheroid, drag-free ballistics, counter-rotating wheel exit conditions, a route tree sampled by arc length, a sprung pad arm at equilibrium, and the column pitch a hand on the turf implies.

> For the complete index, see [llms.txt](https://robocn.dev/llms.txt). A Markdown version of any page is available by appending `.md` to its URL or by sending an `Accept: text/markdown` header.

## Install

```bash
bunx --bun shadcn@latest add https://robocn.dev/r/gridiron-geometry.json
```

Registry item: `gridiron-geometry` · [`https://robocn.dev/r/gridiron-geometry.json`](https://robocn.dev/r/gridiron-geometry.json)

## Notes

- No React, no three.js, no dependencies beyond the kinematics and skeleton cores, and nothing is mutated.
- Every trajectory is drag-free. That is an exact parabola of a ball that does not exist: a real punt goes a good deal less far, and the hang time is optimistic.
- The wheel launcher assumes no slip at either contact. A real one loses some of the surface speed to the ball skidding through the gap.
- There is no contact, no defender, no rule and no clock anywhere in it.

## Usage

```tsx
import { ballSilhouette, kickFlight, launcherExit, sampleRoute } from "@/lib/robocn/gridiron"

// The outline of an ellipsoid is a central section, not its equator.
ballSilhouette(ballFrame({ pitch: 8, roll: 120 }), defaultBall, viewDir)

kickFlight({ speed: 26, angle: 44 })      // { range, apex, hangTime, at, path }
launcherExit({ top: 48, bottom: 16 })     // { speed, spin, bias }
sampleRoute(routePath("post", { depth: 12 }), 13.4)  // { point, heading, turn }
```

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `ballFrame` | `(attitude?) => BallFrame` | — | The ball's own axes in world space from a yaw, a pitch and a roll. At rest the nose points downfield and the laces face up. |
| `ballSilhouette` | `(frame, shape, viewDir, steps?) => Vec3[]` | — | The outline, exactly: the great circle whose pole is M⁻¹Rᵀd, pushed back out through R M. End-on it degenerates to a circle of the waist radius, and nothing special-cases it. |
| `ballSeam / ballLaces / ballStripes` | `(frame, shape, viewDir, …) => marks` | — | Surface marks, each carrying the sign of its own normal against the view, so what is on the far side is not drawn on the near one. |
| `flightAttitude` | `(flight, t, options?) => BallAttitude` | — | Spiral, wobble, tumble and snap as one mechanism: the nose walks a cone at a third of the roll rate, and the cone opens as the spin comes down. |
| `kickFlight` | `(options?) => KickFlight` | — | A drag-free parabola. The hang time, range, apex and impact angle are read off the one curve rather than typed in. |
| `launcherExit` | `(options?) => LauncherExit` | — | Exit speed is the mean of the two wheel surface speeds; spin is their difference over the ball's own diameter. |
| `routePath / sampleRoute` | `(route, options?) => Vec2[] / (path, distance) => RouteSample` | — | Eleven routes in yards, and the runner at an arc length along one: position, heading, and how hard it is turning at the nearest break. |
| `playerSpine / playerUpperBody` | `(options) => Vec3[] / UpperBody` | — | Equal segments at a constant curvature whose chord is the pitch asked for, plus the head's own axes so a helmet lays onto it as a solid. |
| `stancePitch` | `(options) => number` | — | The column pitch that puts the shoulder exactly one arm's length from a hand already on the turf. Bisection on the same column the drawing uses. |
| `sledDeflection / sledSlide` | `(load, options?) => number / (drive, options?) => SledSlide` | — | Static equilibrium of a pivoted pad arm against its return spring, and the friction threshold a frame will not move below. |
| `helmetOutline / facemaskBars / shoulderYoke / padOutline` | `(…) => Vec2[]` | — | The kit all four players wear. Illustration, shared so they match — nothing here is load-bearing. |

## Source

- `src/lib/robocn/gridiron.ts`
