import { Mesh, type MeshOptions } from "../Mesh"; import type { Scene } from "../Scene"; export type CubeOptions = Omit & { size?: number; width?: number; height?: number; depth?: number; }; function dimension(value: number, name: string) { if (!Number.isFinite(value) || value <= 0) throw new RangeError(name); return value / 2; } /** A six-sided mesh with independent vertices and normals for every face. */ export class Cube extends Mesh { constructor(scene: Scene, options: CubeOptions = {}) { const { size = 1, width = size, height = size, depth = size, ...meshOptions } = options; const x = dimension(width, "width"); const y = dimension(height, "height"); const z = dimension(depth, "depth"); const positions = [ [-x, -y, z, x, -y, z, x, y, z, -x, y, z], [x, -y, -z, -x, -y, -z, -x, y, -z, x, y, -z], [x, -y, z, x, -y, -z, x, y, -z, x, y, z], [-x, -y, -z, -x, -y, z, -x, y, z, -x, y, -z], [-x, y, z, x, y, z, x, y, -z, -x, y, -z], [-x, -y, -z, x, -y, -z, x, -y, z, -x, -y, z], ].flat(); const normals = [ [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], [0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1], [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0], [-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0], [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0], [0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0], ].flat(); const uvs = Array.from({ length: 6 }, () => [ 0, 0, 1, 0, 1, 1, 0, 1, ]).flat(); const indices = Array.from({ length: 6 }, (_, face) => { const vertex = face * 4; return [vertex, vertex + 1, vertex + 2, vertex, vertex + 2, vertex + 3]; }).flat(); super(scene, { ...meshOptions, vertexData: { positions, normals, uvs, indices }, }); } }