101 lines
3.2 KiB
TypeScript
101 lines
3.2 KiB
TypeScript
|
import {
|
||
|
Mesh,
|
||
|
Nullable,
|
||
|
Scene,
|
||
|
StandardMaterial,
|
||
|
Texture,
|
||
|
} from '@babylonjs/core/Legacy/legacy';
|
||
|
|
||
|
import { adjust, box, subtractMany } from './shapes.js';
|
||
|
|
||
|
export interface SurfaceOptions {
|
||
|
height?: number,
|
||
|
thickness?: number,
|
||
|
texturePath?: string,
|
||
|
};
|
||
|
|
||
|
export function attachTexture(b: Mesh, scene: Scene, texturePath: string | undefined): Mesh {
|
||
|
if (texturePath !== void 0) {
|
||
|
const mat = new StandardMaterial(b.name + "_mat", scene);
|
||
|
mat.diffuseTexture = new Texture(texturePath, scene);
|
||
|
b.material = mat;
|
||
|
}
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
export const DEFAULT_THICKNESS = 0.125;
|
||
|
|
||
|
export async function wall(name: string, length: number, scene: Scene, options: SurfaceOptions = {}): Promise<Mesh> {
|
||
|
return attachTexture(box(name, length, options.height ?? 2.90, options.thickness ?? DEFAULT_THICKNESS),
|
||
|
scene,
|
||
|
options.texturePath);
|
||
|
}
|
||
|
|
||
|
export async function floor(name: string, width: number, depth: number, scene: Scene, options: SurfaceOptions = {}): Promise<Mesh> {
|
||
|
return attachTexture(box(name, width, options.thickness ?? DEFAULT_THICKNESS, depth),
|
||
|
scene,
|
||
|
options.texturePath);
|
||
|
}
|
||
|
|
||
|
export type Wall = {
|
||
|
texture: string,
|
||
|
thickness?: number,
|
||
|
holes: Array<Mesh>,
|
||
|
};
|
||
|
|
||
|
export async function room(name: string, width: number, depth: number, scene: Scene,
|
||
|
floorTexture: string,
|
||
|
ceilingTexture: string,
|
||
|
wall0: Nullable<Wall>,
|
||
|
wall1: Nullable<Wall>,
|
||
|
wall2: Nullable<Wall>,
|
||
|
wall3: Nullable<Wall>): Promise<Mesh> {
|
||
|
const th = (wallDetails: Wall): number => wallDetails.thickness ?? DEFAULT_THICKNESS;
|
||
|
const mkw = async (n: number, width: number, wallDetails: Wall): Promise<Mesh> => {
|
||
|
return adjust(subtractMany,
|
||
|
await wall(`${name}_${n}`, width, scene, {
|
||
|
texturePath: wallDetails.texture,
|
||
|
thickness: wallDetails.thickness,
|
||
|
}),
|
||
|
... wallDetails.holes);
|
||
|
};
|
||
|
|
||
|
const f = await floor(name +"_f", width, depth, scene, { texturePath: floorTexture });
|
||
|
f.position.y = -DEFAULT_THICKNESS / 2;
|
||
|
|
||
|
const c = await floor(name + "_c", width, depth, scene, { texturePath: ceilingTexture });
|
||
|
c.position.y = 2.90 + DEFAULT_THICKNESS / 2;
|
||
|
c.setParent(f);
|
||
|
|
||
|
if (wall0 !== null) {
|
||
|
const w0 = await mkw(0, width, wall0);
|
||
|
w0.position.z = f.scaling.z / 2 + th(wall0) / 2;
|
||
|
w0.setParent(f);
|
||
|
}
|
||
|
|
||
|
if (wall1 !== null) {
|
||
|
const w1 = await mkw(1, depth, wall1);
|
||
|
w1.position.x = f.scaling.x / 2 + th(wall1) / 2;
|
||
|
w1.rotation.y = Math.PI / 2;
|
||
|
w1.setParent(f);
|
||
|
}
|
||
|
|
||
|
if (wall2 !== null) {
|
||
|
const w2 = await mkw(2, width, wall2);
|
||
|
w2.position.z = -(f.scaling.z / 2 + th(wall2) / 2);
|
||
|
w2.rotation.y = Math.PI;
|
||
|
w2.setParent(f);
|
||
|
}
|
||
|
|
||
|
if (wall3 !== null) {
|
||
|
const w3 = await mkw(3, depth, wall3);
|
||
|
w3.position.x = -(f.scaling.x / 2 + th(wall3) / 2);
|
||
|
w3.rotation.y = -Math.PI / 2;
|
||
|
w3.setParent(f);
|
||
|
}
|
||
|
|
||
|
f.position.y = DEFAULT_THICKNESS / 2;
|
||
|
|
||
|
return f;
|
||
|
}
|