← The API

Phaser AE

API docs

v3.0.0-2206 exports in 26 modulesreleased October 19, 2026

Contents3D maths

Need to get started? Install the Phaser AE CLI →

Content and maths

3D maths

Pure 3D maths (matrices, rays, quaternions, directions) and the three drag conventions

engine/kernel/src/maths3d.tsengine/kernel/src/controls3d.ts

Functions

backward

function backward(yaw: number, pitch = 0): { x: number; y: number; z: number }

From @phaser-ae/kernel

Unit BACKWARD direction — the opposite of forward. Reverse, recoil, a chase camera's eye offset (target − forward × distance is the same thing as target + backward × distance).

composeChain

function composeChain( localX: number, localY: number, localZ: number, localYaw: number, localPitch: number, localRoll: number, parent: ParentLike | null | undefined, ): { x: number; y: number; z: number; yaw: number; pitch: number; roll: number; scale: number }

From @phaser-ae/kernel

Compose a child's LOCAL pose through its parent chain into world space. Returns world position, world euler (engine order) and the accumulated uniform scale. Guards against cycles (depth cap). Mesh parents contribute position + rotation only — a crate's SIZE never inflates its rider; a parent's scale is the deliberate scaling knob.

down

function down(yaw: number, pitch = 0): { x: number; y: number; z: number }

From @phaser-ae/kernel

Unit DOWN direction for a yaw/pitch — the opposite of up.

dragToLook

function dragToLook(d: DragDelta, sensitivity: number, invertY = false): TurnDelta

From @phaser-ae/kernel

LOOK — first person. Direct: the view turns the way your hand goes.

Drag RIGHT → the view turns right. Drag DOWN → the view looks down.

invertY is the one preference a player genuinely expects to find in a menu; nothing else here is a matter of taste.

dragToOrbit

function dragToOrbit(d: DragDelta, sensitivity: number, pitchScale = 0.8): TurnDelta

From @phaser-ae/kernel

ORBIT — a camera circling a subject. Grab-and-drag on the WORLD: the scene follows your hand, so the camera travels the opposite way.

Drag RIGHT → the scene appears to rotate right (the eye orbits to the camera's left). Drag DOWN → the eye rises, so you look down on the subject — the same as pulling its top toward you.

sensitivity is radians per pixel. pitchScale trims the vertical rate against the horizontal, because a screen is wider than it is tall and an equal rate feels twice as fast going up.

dragToSpin

function dragToSpin(d: DragDelta, sensitivity: number, pitchScale = 0.8): TurnDelta

From @phaser-ae/kernel

SPIN — a model on a turntable. Grab-and-drag on the OBJECT: it follows your hand.

Drag RIGHT → the object turns right (its left face swings toward you). Drag DOWN → the object tips its top toward you.

The visible result matches ORBIT, which is the whole trap: the same picture, reached by turning the object rather than the camera. Use this when the subject is one thing and the camera should stay put — an inspector, a character select, a product view — and ORBIT when the camera is exploring a scene.

eulerFromBasis

function eulerFromBasis( fx: number, fy: number, fz: number, ux: number, uy: number, uz: number, ): [number, number, number]

From @phaser-ae/kernel

The engine euler (yaw, pitch, roll) that points an object's local +z along forward and its local +y along up — the pose a thing riding a curve wants, where forward is the tangent and up is the frame's normal. up need not be perpendicular: the component along forward is removed first.

It is the way to orient anything on a path — a cart on a rail, a plane on a route, a camera on a dolly — because a path frame gives vectors and every object wears eulers.

A frame that INVERTS (a loop) is carried correctly: the normal turns over and the roll follows it, which is what makes a coaster train hang upside down rather than flip its yaw round.

eulerToQuat

function eulerToQuat(yaw: number, pitch: number, roll: number): Quat

From @phaser-ae/kernel

Quaternion for the engine euler order: q = qY(yaw) · qX(pitch) · qZ(roll). YAW HANDEDNESS: yaw is CLOCKWISE-from-above — increasing yaw turns to the RIGHT (the mainstream / three.js / FPS sense). That is baked in here by building qY from −yaw (sy is negated); the WGSL rotate(), forward(), lookAtEuler(), physics and picking all share this one sign.

forward

function forward(yaw: number, pitch = 0): { x: number; y: number; z: number }

From @phaser-ae/kernel

Unit forward direction for a yaw/pitch (engine rotate order, roll 0) — the inverse of lookAtEuler: forward(yaw, pitch) = (−cos p·sin y, −sin p, cos p·cos y). +Z is forward at yaw 0; INCREASING yaw turns to the RIGHT (mainstream / three.js / FPS). Use it for first-person movement and camera aim.

frustumPlanes

function frustumPlanes(m: Mat4): Float32Array

From @phaser-ae/kernel

Extract the six frustum planes of a column-major viewProj (WebGPU depth 0..1; works for PERSPECTIVE and ORTHO alike): 24 floats, [a, b, c, d] × (left, right, bottom, top, near, far), xyz normalised. A point is inside a plane when a·x + b·y + c·z + d ≥ 0. Gribb–Hartmann, near plane from the z ≥ 0 clip (not GL's z ≥ -w).

left

function left(yaw: number): { x: number; y: number; z: number }

From @phaser-ae/kernel

Unit LEFT direction, HORIZONTAL — the opposite of right. left(0) = (1, 0, 0).

lookAtEuler

function lookAtEuler( fromX: number, fromY: number, fromZ: number, toX: number, toY: number, toZ: number, ): { yaw: number; pitch: number }

From @phaser-ae/kernel

Yaw/pitch that aim local +Z at a target (engine rotate order, roll 0): forward(yaw, pitch) = (−cos p · sin y, −sin p, cos p · cos y).

mat4Inverse

function mat4Inverse(m: Mat4): Mat4

From @phaser-ae/kernel

General 4×4 inverse (column-major, cofactor expansion). Returns identity for a singular input rather than NaNs — callers unproject with it and a degenerate frame should read as "no transform", never as poison.

mat4LookAt

function mat4LookAt(eye: V3, target: V3, up: V3 = vec3(0, 1, 0)): Mat4

From @phaser-ae/kernel

A view matrix looking from eye at target (y-up world).

mat4Mul

function mat4Mul(a: Mat4, b: Mat4): Mat4

From @phaser-ae/kernel

m = a × b (column-major).

mat4Ortho

function mat4Ortho(l: number, r: number, b: number, t: number, near: number, far: number): Mat4

From @phaser-ae/kernel

Orthographic projection (WebGPU depth 0..1) — shadow-map cameras.

mat4Perspective

function mat4Perspective(fovYDeg: number, aspect: number, near: number, far: number): Mat4

From @phaser-ae/kernel

Perspective projection (fovY degrees, WebGPU depth range 0..1).

mat4Project

function mat4Project(m: Mat4, p: V3): V3

From @phaser-ae/kernel

Transform a point (w=1) and perspective-divide — for tests + picking.

meshCullRadius

function meshCullRadius(verts: ArrayLike<number>, stride = 8): number

From @phaser-ae/kernel

A mesh's CULL RADIUS at scale 1: the sphere about its origin that holds every vertex. verts are interleaved, position first, stride floats a vertex (8 for a registered mesh: pos, normal, uv). Times an object's largest |scale| it bounds the object however it is turned, so a cull stays one sphere test whatever size the mesh was authored at. A mesh drawn off to one side of its origin gets a sphere that reaches it, not a tight one.

Never less than UNIT_MESH_RADIUS. Surfaces that move vertices on the GPU (a sway, a bend, a wobble) reach past the vertices registered, and a unit mesh's corner is the slack they have always had, so nothing is culled tighter than a one-unit cube would be.

quatMul

function quatMul(a: Quat, b: Quat): Quat

From @phaser-ae/kernel

Returns the quaternion product a · b: apply b first, then a.

quatRotate

function quatRotate(q: Quat, x: number, y: number, z: number): [number, number, number]

From @phaser-ae/kernel

Rotate a point by a quaternion (q v q*).

quatToEuler

function quatToEuler(q: Quat): [number, number, number]

From @phaser-ae/kernel

Quaternion → the engine's yaw/pitch/roll (Ry·Rx·Rz): the inverse of eulerToQuat. At a pitch pole (±π/2) roll is 0 and yaw takes the whole turn.

rayFromNdc

function rayFromNdc(invVp: Mat4, nx: number, ny: number): { origin: V3; dir: V3 }

From @phaser-ae/kernel

A world-space picking ray from an NDC point (nx, ny in -1..1, y UP) — unproject near and far and take the difference. invVp is the inverse of the camera's viewProj (mat4Inverse). Returns unit dir.

rayObb

function rayObb( origin: V3, dir: V3, center: V3, half: V3, yaw: number, pitch: number, roll: number, ): number | null

From @phaser-ae/kernel

Ray vs an ORIENTED box (the engine euler order: roll about z, pitch about x, yaw about y — the mesh shader's rotate()): nearest positive hit distance or null. Exact for boxes and a tight proxy for everything else — bounding SPHERES are useless for flat meshes (a ground disc's sphere swallows every click in the scene).

rayObbLocal

function rayObbLocal( origin: V3, dir: V3, pos: V3, size: V3, yaw: number, pitch: number, roll: number, bounds?: { cx: number; cy: number; cz: number; hx: number; hy: number; hz: number }, ): number | null

From @phaser-ae/kernel

Ray vs an oriented box derived from a mesh's LOCAL geometry AABB. pos + size (w,h,d) + euler place a UNIT-fit geometry; bounds is that geometry's local AABB (centre + half-extents, unit space). The box is the AABB scaled by size, its centre offset rotated into world (mesh euler order: roll·z → pitch·x → yaw·y). With no bounds, falls back to the symmetric size/2 cube (only exact for box). Nearest positive t or null.

This is what makes picking tight for off-centre / thin / multi-part model geometry, whose symmetric w/h/d cube overshoots and swallows clicks behind it.

rayPlaneY

function rayPlaneY(origin: V3, dir: V3, h: number): V3 | null

From @phaser-ae/kernel

Ray vs the horizontal plane y = h: hit point, or null (parallel/behind).

raySphere

function raySphere(origin: V3, dir: V3, c: V3, r: number): number | null

From @phaser-ae/kernel

Ray vs sphere: nearest positive hit distance, or null.

function right(yaw: number): { x: number; y: number; z: number }

From @phaser-ae/kernel

Unit RIGHT direction, HORIZONTAL — the direction increasing yaw turns toward. Strafing, steering, lane offsets and anything mounted on the right of a body. Pitch is deliberately ignored: a player looking at the sky still strafes along the ground. right(0) = (−1, 0, 0).

slerpEuler

function slerpEuler( yaw0: number, pitch0: number, roll0: number, yaw1: number, pitch1: number, roll1: number, a: number, out: number[] | Float32Array | Float64Array, ): void

From @phaser-ae/kernel

Blend one orientation toward another and write the result back as yaw/pitch/roll.

Euler angles cannot be blended one at a time. Away from the pitch poles they are near enough that nobody notices, but at pitch ±π/2 yaw and roll rotate about the SAME axis and only their sum is determined: the decomposition is free to hand back (yaw, pitch, roll) or the equally correct (yaw + π, π − pitch, roll + π), and it switches between them as an object crosses the pole. Blending the three numbers separately across that switch sends the object through orientations at neither end — measured at 180° partway through a single step on a cone attached nose-down, which is a model turning inside out and snapping back once or twice a second.

So go through the quaternion, where a blend has no seams. Normalised lerp rather than a true slerp: one step of interpolation is a small arc, the two differ by well under a pixel there, and this runs per object per frame. Allocation-free — the caller owns out.

  • yaw0 Start yaw, radians.

  • pitch0 Start pitch.

  • roll0 Start roll.

  • yaw1 End yaw, radians.

  • pitch1 End pitch.

  • roll1 End roll.

  • a Blend factor, 0 at the start orientation and 1 at the end.

  • out Written as [yaw, pitch, roll].

sphereVsFrustum

function sphereVsFrustum(planes: Float32Array, x: number, y: number, z: number, r: number): boolean

From @phaser-ae/kernel

Sphere-vs-frustum: true when the sphere touches the volume (conservative — corner cases may pass a sphere that is just outside; never culls a visible one). planes from frustumPlanes().

up

function up(yaw: number, pitch = 0): { x: number; y: number; z: number }

From @phaser-ae/kernel

Unit UP direction for a yaw/pitch — the body's own up, perpendicular to forward. With pitch 0 it is world up (0, 1, 0); nose-down pitch tips it forward, which is what a banking aircraft or a loop needs. For "up the screen" in a game with no pitch, use (0, 1, 0) directly.

vec3

function vec3(x = 0, y = 0, z = 0): V3

From @phaser-ae/kernel

Creates a V3 from components. All default to 0.

viewBasis

function viewBasis(view: Mat4): { right: V3; up: V3 }

From @phaser-ae/kernel

The camera's right/up basis from a view matrix (billboards face with these).

Constants

UNIT_MESH_RADIUS

const UNIT_MESH_RADIUS: number

From @phaser-ae/kernel

Half the diagonal of a one-unit cube: the corner of every built-in primitive, and the least a mesh is culled with.

Types

DragDelta

interface DragDelta

From @phaser-ae/kernel

A frame's drag, in screen pixels. dy is positive DOWNWARD, as screens are.

  • dx: number — Pixels moved right.
  • dy: number — Pixels moved down.

Mat4

type Mat4 = Float32Array

From @phaser-ae/kernel

A column-major 4x4 matrix as 16 floats (WebGPU NDC, depth 0..1).

ParentLike

interface ParentLike

From @phaser-ae/kernel

The minimal parent shape composeChain walks: a world pose plus an optional parent link.

  • x: number — The parent's world x position, in world units.
  • y: number — The parent's world y position, in world units.
  • z: number — The parent's world z position, in world units.
  • yaw: number — The parent's yaw, in radians, clockwise from above.
  • pitch: number — The parent's pitch, in radians.
  • roll: number — The parent's roll, in radians.
  • scale?: number — Uniform child-scale contribution (groups; mesh parents contribute 1).
  • parent?: ParentLike | null — The next parent up the chain, or null at the root.

Quat

type Quat = [number, number, number, number]

From @phaser-ae/kernel

A rotation quaternion as [x, y, z, w].

TurnDelta

interface TurnDelta

From @phaser-ae/kernel

How much a control turned this frame, in radians.

  • dYaw: number — Yaw change, radians.
  • dPitch: number — Pitch change, radians.

V3

interface V3

From @phaser-ae/kernel

A 3D point or vector.

  • x: number — The x component.
  • y: number — The y component. Up is positive.
  • z: number — The z component.