Repository navigation
logic transform
Pure functions on CubeSpec[], decoupled from Blockbench: translation edits from/to/origin directly;
rotation returns CubeSpecs carrying a rotation field that the assembly layer expresses as
Cube.rotation.
export function cloneCubes(cubes: CubeSpec[]): CubeSpec[];
export function translate(cubes: CubeSpec[], offset: Vec3): CubeSpec[];
export function lift(cubes: CubeSpec[], dy: number): CubeSpec[]; // y-translate, positive up// sets rotation.y = angleDeg (ensuring origin), leaves from/to unchanged — Blockbench expresses it via
// Cube.rotation instead of recomputed coordinates
export function rotateY(cubes: CubeSpec[], angleDeg: number, origin: Vec3): CubeSpec[];
// X rotation for the ascending slope; preserves any existing Y rotation (yaw)
export function rotateX(cubes: CubeSpec[], angleDeg: number, origin: Vec3): CubeSpec[];
// rotates a vector by [rx,ry,rz] in X→Y→Z order (Minecraft's Cube.rotation order)
export function rotateVec(v: Vec3, rot: Vec3): Vec3;transformFaceUV transforms a face's UV sampling under a cube rotation — the texture is "glued" to the
volume, so after rotating, the same region stays on the same physical face while its normal/local UV axes
change. For 90°-multiple axis rotations: pure rotation (det>0) keeps the uv box and adds the angle to
face.rotation; reflection (det<0, e.g. side faces when rotating about Z) reverses the uv box's v
(swap v0/v1) to express the mirror — Minecraft's face.rotation only supports 0/90/180/270.
export function transformFaceUV(
dir: CubeFaceDirection,
face: FaceSpec,
rot: Vec3
): { dir: CubeFaceDirection; face: FaceSpec };mirrorPartYz mirrors a part about the YZ plane through its lateral center (xMid) — "right rail = mirror
of left rail" (Create's segment_left / segment_right are mirrors about the track centerline): geometry x
→ 2·xMid − x (from/to swapped), rotation [rx,−ry,−rz], east↔west faces swapped + u-axis reversed +
rotation negated, mesh vertex x reflected + face vertex order reversed. Textures are unchanged; input not
mutated. Mirroring about one's own center is an involution.
export function mirrorPartYz(part: PartModel): PartModel;// bakes 90°-multiple axis-aligned rotations into from/to (plain boxes, no rotation field), so derived
// shapes can add their own group rotation without overwriting the part's own orientation (e.g. a rail's
// built-in [0,-90,0] would otherwise be lost, leaving the rails parallel to the ties). Non-90° rotations
// are kept. Returns a new PartModel with recomputed bbox/xMid.
export function bakePartAxisAligned(part: PartModel): PartModel;
// bakes a −90° Y rotation into every unrotated cube (about `center`) and remaps each face's UV.
// Result: plain boxes without a rotation field, so later rotateY/rotateX composition can't overwrite.
// Direction mapping: north→east, south→west, east→south, west→north; up/down unchanged.
export function bakeRotateY90(cubes: CubeSpec[], center: Vec3): CubeSpec[];rotateMesh bakes a rotation about a pivot into the vertex positions (world′ = pivot + R·(world−pivot),
origin cleared) — required because Blockbench renders a mesh as origin + R(rotation)·vertices, which
differs from the cube convention (Minecraft rotates about the origin with an implicit −origin), so a
shape's group rotation can't be expressed via the mesh's rotation field with world-space vertices.
export function cloneMesh(mesh: MeshSpec): MeshSpec;
export function translateMesh(mesh: MeshSpec, offset: Vec3): MeshSpec;
export function liftMesh(mesh: MeshSpec, dy: number): MeshSpec;
export function rotateMesh(mesh: MeshSpec, rot: Vec3, pivot: Vec3): MeshSpec;