MODFORGEWORLD
← Knowledge base

Rotation System

rotation-systemv1updated 5h ago

Rotation System

7 Days to Die uses 24 discrete orientations for blocks, corresponding to the 24 orientation-preserving symmetries of a cube (6 faces × 4 rotations per face).

Source: index.html lines ~1045–1100

ROTATIONS_24 Lookup Table

Each rotation index maps to Euler angles [rotX, rotY, rotZ] in radians:

IndexFaceY-SpinEuler [X, Y, Z]
0Up[0, 0, 0]
1Up90°[0, π/2, 0]
2Up180°[0, π, 0]
3Up270°[0, -π/2, 0]
4Down[π, 0, 0]
5Down90°[π, -π/2, 0]
6Down180°[π, π, 0]
7Down270°[π, π/2, 0]
8North[π/2, 0, 0]
9North90°[π/2, π/2, 0]
10North180°[π/2, π, 0]
11North270°[π/2, -π/2, 0]
12South[-π/2, 0, 0]
13South90°[-π/2, -π/2, 0]
14South180°[-π/2, π, 0]
15South270°[-π/2, π/2, 0]
16East[0, 0, -π/2]
17East90°[π/2, 0, -π/2]
18East180°[π, 0, -π/2]
19East270°[-π/2, 0, -π/2]
20West[0, 0, π/2]
21West90°[-π/2, 0, π/2]
22West180°[π, 0, π/2]
23West270°[π/2, 0, π/2]

Pattern

  • Groups of 4: each face direction has 4 Y-axis spin variants (0°, 90°, 180°, 270°)
  • Face Up/Down: rotate around X by 0 or π, spin around Y
  • North/South: rotate around X by ±π/2, spin around Y
  • East/West: rotate around Z by ∓π/2, spin around X

Runtime Notes

  • Rotation indices 4-7 are the upside-down/ceiling-mounted face (Down). Use this when code needs ceiling-specific behavior.
  • For rotating/aiming block-attached transforms that can use advanced placement, prefer local-space direction math (transform.InverseTransformDirection) over subtracting world Euler angles. World Euler subtraction works for upright-only blocks, but breaks for ceiling-mounted blocks because pitch sign/range assumptions change.
  • For ceiling-mounted blocks (rotation 4-7), local pitch may use the opposite sign from upright placement. If an upright block accepts centeredPitch - upRange through centeredPitch + downRange, the ceiling-mounted equivalent often needs centeredPitch - downRange through centeredPitch + upRange.
  • For 360-degree yaw tracking, do not assign normalized yaw directly every frame. Use the closest equivalent angle to the current yaw, e.g. current + Mathf.DeltaAngle(current, desired), so crossing 179 to -179 does not become a full reverse turn.

Applying Rotation to a Mesh

function applyRotationToMesh(mesh, rotIndex) {
    const r = ROTATIONS_24[rotIndex] || ROTATIONS_24[0];
    mesh.rotation.set(r[0], r[1], r[2]);
}

Falls back to rotation 0 (identity) if the index is out of range.

Rotation Labels

const FACE_NAMES = ['Up','Up','Up','Up', 'Down','Down','Down','Down',
    'North','North','North','North', 'South','South','South','South',
    'East','East','East','East', 'West','West','West','West'];

function getRotationLabel(rotIndex) {
    const face = FACE_NAMES[rotIndex];
    const yRot = (rotIndex % 4) * 90;
    return `${face} ${yRot}°`;  // e.g., "North 90°"
}

Binary Encoding

In [[TTS File Format]], rotation is stored as 5 bits (bits 16–20) of the block's uint32 value:

const rotation = (raw >> 16) & 0x1F;

Cycling Rotation (User Interaction)

function cycleRotation(currentRot, allowedRots, forward) {
    const idx = allowedRots.indexOf(currentRot);
    if (idx === -1) return allowedRots[0];
    if (forward)
        return allowedRots[(idx + 1) % allowedRots.length];
    else
        return allowedRots[(idx + allowedRots.length - 1) % allowedRots.length];
}
  • Ctrl+scroll wheel cycles through allowed rotations
  • Wraps around at both ends
  • See [[Rotation Types]] for allowed rotation sets

Related

  • [[Rotation Types]] — per-block rotation constraints
  • [[Multi-Block Rotation]] — how rotation affects multi-block dimensions
  • [[X-Mirror Rotation]] — rotation correction for mirrored prefabs
  • [[Moving Blocks at Runtime (SetBlocksRPC)]] — rotating a whole moved volume in 90° steps (composition, Block.SupportsRotation, BlockShapeNew.GetRotationStatic)