Files
yawn/addons/handles/src/shapes/Cube.ts
T

58 lines
1.8 KiB
TypeScript

import { Mesh, type MeshOptions } from "../Mesh";
import type { Scene } from "../Scene";
export type CubeOptions = Omit<MeshOptions, "geometryId" | "vertexData"> & {
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 },
});
}
}