logo

Babylon.js Market

CameraState6DOF

camera

CameraState6DOF

1
Unlock

Install with the CLI:

bjs download CameraState6DOF

CameraState6DOF

The smoothed pose and lens of a free 6-DOF chase camera, held as a shared component so "decide the pose" and "push the pose" stay two separate systems.

What it does

CameraState6DOFComponent is pure state: a world-space position (x/y/z), an orientation stored as a unit quaternion q ([w, x, y, z]) rather than Euler angles — so the camera can loop, roll, and fly inverted with no gimbal-lock singularity at pitch ±π/2 — an initialized flag, and the perspective lens (fov/near/far). Two systems share it instead of private fields: the smoother (ChaseCamera6DOFSystem, shipped by the ChaseCamera6DOF dependency) writes the trailing pose into it each frame; CameraSync6DOFSystem (this component's system, aliased CameraState6DOFSystem) only reads it. On the first frame a camera-state entity exists, the sync system lazily mints one perspective camera from the lens via the adapter's createPerspectiveCamera, remembers the opaque handle, and thereafter pushes the pose with setCameraPose(handle, position, quaternion) — the quaternion goes straight through, no lossy quat→Euler round-trip. Until the smoother snaps on frame 1 (initialized still false), the sync leaves the camera at its creation pose instead of pushing an identity origin.

Use it in a scene

A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.

Build it from scratch with the bjs CLI:

  1. 1Scaffold a project
    npm create @babylonjsmarket/arcade@latest my-game

    World, renderer, and dev server — ready to run.

  2. 2Install dependencies
    cd my-game && npm install
  3. 3Add CameraState6DOF
    bjs download CameraState6DOF

    Copies its source into src/ so the scene resolves.

    First time? Run bjs login once.

  4. 4Paste the scene into src/scenes/arcade-room.ts and run
    npm run dev

    SceneLoader builds the world from the JSON; reload to rebuild.

JSON
{
  "Camera": {
    "tags": ["camera"],
    "components": {
      "CameraState6DOF": { "fov": 1.05, "near": 0.1, "far": 200000 },
      "ChaseCamera6DOF": { "trailDistance": 18, "trailHeight": 6, "tau": 0.18 }
    }
  }
}

Props

  • x (number, default 0) — smoothed world-space X; written by the smoother, rarely set by hand.
  • y (number, default 0) — smoothed world-space Y.
  • z (number, default 0) — smoothed world-space Z.
  • q ([w, x, y, z], default [1, 0, 0, 0]) — orientation unit quaternion, the source of truth; written by the smoother. Not Euler, so no gimbal lock.
  • initialized (boolean, default false) — false until the smoother snaps to its target on frame 1; leave it out.
  • fov (number, default 1.05) — vertical field of view in radians handed to createPerspectiveCamera.
  • near (number, default 0.1) — near clip-plane distance in world units.
  • far (number, default 200000) — far clip-plane distance; the large default is what lets a space-scale world draw.

Events

  • Emits nothing.
  • Listens for nothing.

The coupling here isn't the bus — it's the shared component. ChaseCamera6DOFSystem mutates this component's fields and CameraSync6DOFSystem reads them, so there's no event to subscribe to.

Dependencies

ChaseCamera6DOF — its system is what actually writes this pose (place behind + above the target, exponential ease, quaternion SLERP). Without it, CameraState6DOF sits at its default pose and never moves. ChaseCamera6DOF lives on the same camera singleton and carries the follow tuning (trailDistance/trailHeight/tau). The followed subject is a separate entity carrying ChaseCameraTarget + Transform6DOF (typically the player ship); the smoother resolves the camera singleton by scanning for whoever holds CameraState6DOF.

Notes

  • Put CameraState6DOF on one camera singleton entity (tag it camera). The smoother follows the first active ChaseCameraTarget, so exactly one camera and one subject.
  • fov is radians, not degrees — 1.05 is ~60°.
  • The default far of 200000 is deliberate for a space scene; shrink it for a small level or distant geometry will z-fight against a needlessly deep buffer.
  • The camera is minted lazily on the first live frame and the adapter owns its lifetime — it's freed wholesale at renderer dispose, so the sync system only drops its handle reference on shutdown.
  • You normally never author x/y/z/q/initialized by hand; they're the smoother's scratch state. Set only the lens (fov/near/far) in scene JSON.
  • The sync runs unpauseable at priority -94, after the smoother (-90), so the view keeps updating even while game logic is paused and always reads the freshest pose.

More like this

ChaseCamera6DOF
ArcCamera
CameraFollow
ChaseCameraTarget
FlightIntent
PinballCamera
PlayerFlightInput
Renderable
ShipFlight
ShooterCamera
SpaceDust
Transform6DOF
Velocity6DOF
WorldOriginAnchor

Was this page helpful?

We read every note — tell us what's working and what isn't.

↑↓ NavigateEnter SelectEsc CloseCtrl+K Open Search