Skip to content
hikari
RenderingEditorAIToolchainDocumentation
Download

© 2026 Flying Rat Studio.
All rights reserved.

Explore the engineDocumentationContributorsDownloadLicenseBack to top
Documentation / Systems
Browse docs
Overview
Tutorials17
OverviewPlay, Edit, and scenesFirst UI documentFirst game projectFirst entityComponent properties and the inspectorFirst mesh and materialFirst physics body and triggerFirst character controllerFirst session servicesFirst UIFirst input actionFirst messagesFirst runtime spawnFirst motionFirst skeletal animationAssets in Play (soft refs and hot reload)Dynamic editor recompile
Guides25
OverviewWorking in the editorDevelopment guideGameplay APIActor and component lifecycleThreads, jobs, events, and routinesGameplay AI tasksGame AI: perception and movement playgroundBrain assetsBrain execution for swarm populationsLocalizationGame cursorsChoosing component storageBuild and packagingProject filePluginsHikari Plugin APIData-driven content, JSON, and pathsScripting with KawaShader authoringChoosing and scaling shadowsTime of dayUser interfaceUI layoutUI widgetsMigration from Unity / Unreal
Systems32
OverviewArchitectureApplication lifecycleFrontends and driversPlatforms and supportSession services and cross-scene stateScenes and gameplayActor communication (hi.actors)Game-facing refsSave / replication wire versionCoordinate space and camera conventionsRenderingRenderer architecture mapFrame governorPipeline compilationSkeletal animationGPU particlesVisual ZonesVolumetric mediaInputAudioPhysicsMotion KitTemporal KitUI documentsAssets and ShinraPrefabsAsset residencyAsset formats (Shinra pipeline)Document schemasUI and editorEditor asset hot reloadEditor Project Selector
Language reference3
OverviewAkari GPU ABIAkari language referenceKawa language reference
Engine overview
Start exploring
  • No matching sections. Try fewer words or another topic.
NavigateEnter Openesc Close
Overview
Tutorials17
OverviewPlay, Edit, and scenesFirst UI documentFirst game projectFirst entityComponent properties and the inspectorFirst mesh and materialFirst physics body and triggerFirst character controllerFirst session servicesFirst UIFirst input actionFirst messagesFirst runtime spawnFirst motionFirst skeletal animationAssets in Play (soft refs and hot reload)Dynamic editor recompile
Guides25
OverviewWorking in the editorDevelopment guideGameplay APIActor and component lifecycleThreads, jobs, events, and routinesGameplay AI tasksGame AI: perception and movement playgroundBrain assetsBrain execution for swarm populationsLocalizationGame cursorsChoosing component storageBuild and packagingProject filePluginsHikari Plugin APIData-driven content, JSON, and pathsScripting with KawaShader authoringChoosing and scaling shadowsTime of dayUser interfaceUI layoutUI widgetsMigration from Unity / Unreal
Systems32
OverviewArchitectureApplication lifecycleFrontends and driversPlatforms and supportSession services and cross-scene stateScenes and gameplayActor communication (hi.actors)Game-facing refsSave / replication wire versionCoordinate space and camera conventionsRenderingRenderer architecture mapFrame governorPipeline compilationSkeletal animationGPU particlesVisual ZonesVolumetric mediaInputAudioPhysicsMotion KitTemporal KitUI documentsAssets and ShinraPrefabsAsset residencyAsset formats (Shinra pipeline)Document schemasUI and editorEditor asset hot reloadEditor Project Selector
Language reference3
OverviewAkari GPU ABIAkari language referenceKawa language reference
Engine overview
Systems4 min read

Coordinate space and camera conventions

On this page
On this pageWhy this setWorld axesCamera and gameplayEuler angles (degrees)QuaternionsUnitsProjection and clip spacevs other engines Back to top

Engine standard (unreleased; no +Z-forward or non-reverse-Z path):

PropertyChoice
HandednessRight-handed (+X × +Y = +Z)
Up+Y
Forward−Z (identity camera looks down −Z)
Matrix storageColumn-major
Clip / depthReverse-Z (NDC: near → 1, far → 0; infinite-far perspective preferred)

This matches glTF / classic GL camera math (right-handed, Y-up, cameras looking along −Z), plus reverse-Z depth as used in contemporary high-end renderers. It is not left-handed +Z-forward, and it is not Z-up.

Source of truth: src/hikari/src/math/, scene/camera.zig, sdk/src/camera_rig.zig, projection consumers, depth/Hi-Z paths.

Why this set

  1. RH Y-up −Z forward — Object +X, view-right, and lookAt’s X axis coincide at identity. No separate “view-right = −local X” story.
  2. glTF / DCC alignment — Assets and tools already speak RH Y-up; camera space matches OpenGL-style −Z view.
  3. Reverse-Z — Best depth precision for large far / outdoor scales with 24–32-bit depth; pairs naturally with an infinite-far projection.
  4. Rejected alternatives — left-handed +Z-forward keeps glTF awkward; Z-up forces constant axis remaps; RH +Z forward would force view-right ≠ local +X.

World axes

AxisDirection
+XRight (math_vector.right) — also view/screen right for an identity camera
+YUp
−ZForward (identity camera look direction)
+ZBackward

Right-handed: +X × +Y = +Z (so forward −Z is “into the screen” in the usual GL view diagram).

Camera and gameplay

Important

An identity camera looks along local −Z. To look toward the origin with identity rotation, place it on +Z; a camera on −Z would look away from the origin.

  • Identity orientation: local +X right, +Y up, −Z forward.
  • Camera.getRight / Actor.get_right / FlyCamera.right = rotated local +X (same as cross(forward, up) when forward is the look direction).
  • getForward / look direction = rotated −Z (math_vector.forward).
  • Ground move basis: yaw about +Y; at yaw 0, forward is (0,0,−1), right is (1,0,0).
  • Camera frustum gizmos (editor overlay) place near/far on local −Z.
  • Look controllers store pitch/yaw degrees as source of truth (FlyCamera, CameraRig, play-mode camera_controller.kawa) and derive the quaternion. Do not round-trip toEuler every look frame — near the pitch clamp that is ill-conditioned in f32.

Euler angles (degrees)

Triples are (pitch, yaw, roll) in degrees, composition on column vectors:

text
R = Ry(yaw) · Rx(pitch) · Rz(roll)
q = qy · qx · qz
ComponentAxisPositive sense (RH, facing −Z)
pitch+XLook up
yaw+YTurn left (CCW from above)
roll+ZBank around the view axis

Yaw-first ordering is what makes this usable for cameras:

  • Yaw is full-range. toEuler reports yaw over (−180°, 180°]; only pitch is limited to [−90°, 90°].
  • Gimbal lock sits at the poles (pitch ±90°), which look controllers already clamp away from.
  • Roll does not steer. Because roll is innermost, it rotates around the local Z axis, so banking never changes where a camera or light points.

Keep yaw as the outer rotation when converting authored Euler values. An order with yaw in the middle can turn |yaw| > 90° into a 180° roll; clearing that roll would flip the view. Runtime look controllers should retain pitch/yaw state as described above.

fromEuler / toEuler must stay inverses. CameraRig.Look / mouse deltas use gameplay sense (turn right / look up) and convert into these euler values.

Quaternions

The runtime type is { w, x, y, z } — Hamilton, scalar-first (math/quaternion.zig).

This is the minority layout in the wider ecosystem: glTF and most DCC/engine formats serialise xyzw scalar-last, and so does the cooked model format (ImportNode.rotation in shinra/src/import/mod.rs, and skeletal animation keyframes). Anything crossing that boundary must swizzle. Scene assets are unaffected — they store rotation_euler degrees, not quaternions.

Rotating a vector uses local axes as columns of toMatrix, so rotateVector(q, forward) is the look direction.

Units

QuantityUnit
Distancemetres (1 world unit = 1 m, matching glTF)
Timeseconds
Masskilograms
Anglesradians everywhere except euler triples and authored/inspector fields, which are degrees

Physics assumes this: tenkai's default gravity is -9.81 on +Y. Authoring content at a different scale silently changes how everything falls, how character motors tune, and how attenuation ranges read.

Projection and clip space

  • CPU builds reverse-Z perspective (finite or infinite far) with NDC z already in [0, 1] (near → 1, far → 0). remap_clip_z is identity.
  • After projection, larger depth buffer values are closer. Depth tests use greater. Clear depth / empty shadow atlas to 0.
  • Metal and D3D12 share the same CPU matrices (no GL −1…+1 remap).
  • Linear G-buffer / Hi-Z depth (meters, −view.z) keeps min=nearer, max=farther. Hardware-depth consumers use reverse-Z ordering.

vs other engines

HikariUnityGodot 4Unreal
HandednessRightLeftRightLeft
Up+Y+Y+Y+Z
Forward−Z+Z−Z+X
DepthReverse-ZVariesDepends on renderer/versionReverse-Z (modern)
PreviousSave / replication wire versionNext Rendering

Documentation follows the current engine checkout.

Snapshot 86f12d68Source docs/systems/coordinate-space.md
On this pageWhy this setWorld axesCamera and gameplayEuler angles (degrees)QuaternionsUnitsProjection and clip spacevs other engines Back to top