logo

Babylon.js Market

Transform6DOF

core

Transform6DOF

1
Unlock

Install with the CLI:

bjs download Transform6DOF

Transform6DOF

A full six-degrees-of-freedom pose — position plus a gimbal-lock-free orientation — for flight and space entities.

What it does

Transform6DOFComponent is pure pose data: a world-space position (x, y, z) and an orientation stored as a unit quaternion q (w, x, y, z) that is the source of truth. It keeps a synced YXZ Euler mirror (rx, ry, rz) so the renderer and legacy readers still work, but those are derived state — writing orientation goes through setEulerYXZ() (which rebuilds q) or by mutating q[] and calling syncEulerFromQuat(). The quaternion is the whole point: a ship can pitch through ±π/2, roll, and fly inverted without the singularity that blows up Euler angles. It owns no System — it is just the pose that sibling systems read and write: Movement6DOFSystem (shipped with Velocity6DOF) integrates it each frame, RenderSyncSystem (from Renderable) pushes it onto the mesh, and the chase camera reads it to trail the ship. Floating-origin correction is the renderer's job, so these values stay in true world space and serialize cleanly.

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 Transform6DOF
    bjs download Transform6DOF

    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
{
  "Player": {
    "tags": ["player"],
    "components": {
      "Transform6DOF": { "x": 0, "y": 0, "z": 0, "rx": 0, "ry": 0, "rz": 0 },
      "Velocity6DOF": {},
      "Renderable": {
        "shape": "spaceplane",
        "sx": 3, "sy": 1, "sz": 4,
        "glbSrc": "/wingman/falconship.glb"
      }
    }
  }
}

Props

  • x (number, default 0) — world-space position on the X axis.
  • y (number, default 0) — world-space position on the Y axis.
  • z (number, default 0) — world-space position on the Z axis (+Z is the ship's nose-forward).
  • rx (number, default 0) — initial pitch in radians (YXZ Euler); seeds the quaternion q at construction.
  • ry (number, default 0) — initial yaw in radians (YXZ Euler); seeds q.
  • rz (number, default 0) — initial roll in radians (YXZ Euler); seeds q.

Events

  • Emits nothing and listens for nothing — Transform6DOF has no {Name}Events / {Name}InputEvents constants. It is a plain data component that sibling systems read and mutate directly (position/orientation are touched in-place by Movement6DOFSystem, RenderSyncSystem, and the chase-camera smoother), so there is no bus traffic to wire.

Dependencies

None required — Transform6DOF is standalone pose data (meta.json lists no dependencies). On its own it does nothing visible; it becomes useful when paired with the systems that consume it:

  • Velocity6DOF — its Movement6DOFSystem integrates the pose (pos += vel·dt + body-frame quaternion integration). Add it (plus FlightIntent + ShipFlight) to make the entity actually move.
  • Renderable — its RenderSyncSystem mints a mesh and each frame copies this pose onto it, so the entity is drawn where the pose says.
  • CameraState6DOF + ChaseCamera6DOF — the camera reads the followed entity's Transform6DOF to trail it.

Notes

  • The quaternion q is authoritative; rx/ry/rz are a mirror. After you mutate q[] directly, call syncEulerFromQuat() or the Euler fields go stale. Setting rx/ry/rz at construction time seeds q once — mutating those numbers afterward does not re-derive q; use setEulerYXZ() for that.
  • A bare Transform6DOF + Renderable with no Velocity6DOF gives you a static posed object (a station, an asteroid, an oil-blob) — it renders at its pose and never moves. That's the trimmed form used for the enemy and blob in example.scene.json.
  • Keep values in true world space. Do not pre-offset them for a floating origin — the renderer applies that correction, so save/load and physics stay simple.
  • serialize() round-trips only x, y, z, rx, ry, rz; the quaternion is rebuilt from the Euler mirror on load, so a deserialized pose matches the saved orientation.

More like this

ArcCamera
CameraState6DOF
ChaseCamera6DOF
ChaseCameraTarget
FlightIntent
FreighterChain
Jump
KeyboardMover
Lifetime
Mesh
MeshPrimitive
Movement
Physics
PlayerFlightInput
Renderable
Score
ShipFlight
SpaceDust
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