@drawcall/lod 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +83 -2
- package/dist/baked/codec.d.ts +10 -0
- package/dist/baked/codec.js +291 -0
- package/dist/baked/codec.js.map +1 -0
- package/dist/baked/coverage.d.ts +3 -0
- package/dist/baked/coverage.js +45 -0
- package/dist/baked/coverage.js.map +1 -0
- package/dist/baked/index.d.ts +51 -0
- package/dist/baked/index.js +151 -0
- package/dist/baked/index.js.map +1 -0
- package/dist/baked/interior/faces.d.ts +26 -0
- package/dist/baked/interior/faces.js +105 -0
- package/dist/baked/interior/faces.js.map +1 -0
- package/dist/baked/interior/material.d.ts +31 -0
- package/dist/baked/interior/material.js +157 -0
- package/dist/baked/interior/material.js.map +1 -0
- package/dist/baked/interior/rooms.d.ts +22 -0
- package/dist/baked/interior/rooms.js +78 -0
- package/dist/baked/interior/rooms.js.map +1 -0
- package/dist/baked/low.d.ts +20 -0
- package/dist/baked/low.js +75 -0
- package/dist/baked/low.js.map +1 -0
- package/dist/baked/raster.d.ts +20 -0
- package/dist/baked/raster.js +71 -0
- package/dist/baked/raster.js.map +1 -0
- package/dist/baked/transfer.d.ts +36 -0
- package/dist/baked/transfer.js +243 -0
- package/dist/baked/transfer.js.map +1 -0
- package/dist/baked/unwrap.d.ts +9 -0
- package/dist/baked/unwrap.js +167 -0
- package/dist/baked/unwrap.js.map +1 -0
- package/dist/baked/xatlas.d.ts +2 -0
- package/dist/baked/xatlas.js +31 -0
- package/dist/baked/xatlas.js.map +1 -0
- package/dist/bounds.d.ts +33 -0
- package/dist/bounds.js +127 -0
- package/dist/bounds.js.map +1 -0
- package/dist/dispose.d.ts +5 -0
- package/dist/dispose.js +28 -0
- package/dist/dispose.js.map +1 -0
- package/dist/fade.d.ts +44 -0
- package/dist/fade.js +78 -0
- package/dist/fade.js.map +1 -0
- package/dist/impostor/bake/atlas.d.ts +51 -0
- package/dist/impostor/bake/atlas.js +190 -0
- package/dist/impostor/bake/atlas.js.map +1 -0
- package/dist/impostor/bake/index.d.ts +50 -0
- package/dist/impostor/bake/index.js +221 -0
- package/dist/impostor/bake/index.js.map +1 -0
- package/dist/impostor/bake/materials.d.ts +29 -0
- package/dist/impostor/bake/materials.js +156 -0
- package/dist/impostor/bake/materials.js.map +1 -0
- package/dist/impostor/bake/source.d.ts +3 -0
- package/dist/impostor/bake/source.js +23 -0
- package/dist/impostor/bake/source.js.map +1 -0
- package/dist/impostor/cache.d.ts +15 -0
- package/dist/impostor/cache.js +44 -0
- package/dist/impostor/cache.js.map +1 -0
- package/dist/impostor/codec.d.ts +14 -0
- package/dist/impostor/codec.js +137 -0
- package/dist/impostor/codec.js.map +1 -0
- package/dist/impostor/impostor.d.ts +67 -0
- package/dist/impostor/impostor.js +79 -0
- package/dist/impostor/impostor.js.map +1 -0
- package/dist/impostor/mesh/card.d.ts +38 -0
- package/dist/impostor/mesh/card.js +79 -0
- package/dist/impostor/mesh/card.js.map +1 -0
- package/dist/impostor/mesh/index.d.ts +66 -0
- package/dist/impostor/mesh/index.js +174 -0
- package/dist/impostor/mesh/index.js.map +1 -0
- package/dist/impostor/mesh/material.d.ts +63 -0
- package/dist/impostor/mesh/material.js +199 -0
- package/dist/impostor/mesh/material.js.map +1 -0
- package/dist/impostor/mesh/surface.d.ts +63 -0
- package/dist/impostor/mesh/surface.js +162 -0
- package/dist/impostor/mesh/surface.js.map +1 -0
- package/dist/impostor/mesh/textures.d.ts +4 -0
- package/dist/impostor/mesh/textures.js +37 -0
- package/dist/impostor/mesh/textures.js.map +1 -0
- package/dist/impostor/octahedral.d.ts +29 -0
- package/dist/impostor/octahedral.js +83 -0
- package/dist/impostor/octahedral.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/instanced/args.d.ts +20 -0
- package/dist/instanced/args.js +77 -0
- package/dist/instanced/args.js.map +1 -0
- package/dist/instanced/bounds.d.ts +50 -0
- package/dist/instanced/bounds.js +271 -0
- package/dist/instanced/bounds.js.map +1 -0
- package/dist/instanced/dirty.d.ts +12 -0
- package/dist/instanced/dirty.js +61 -0
- package/dist/instanced/dirty.js.map +1 -0
- package/dist/instanced/index.d.ts +116 -0
- package/dist/instanced/index.js +573 -0
- package/dist/instanced/index.js.map +1 -0
- package/dist/instanced/meshes.d.ts +14 -0
- package/dist/instanced/meshes.js +54 -0
- package/dist/instanced/meshes.js.map +1 -0
- package/dist/instanced/select.d.ts +84 -0
- package/dist/instanced/select.js +264 -0
- package/dist/instanced/select.js.map +1 -0
- package/dist/lazy.d.ts +64 -0
- package/dist/lazy.js +187 -0
- package/dist/lazy.js.map +1 -0
- package/dist/levels.d.ts +72 -0
- package/dist/levels.js +146 -0
- package/dist/levels.js.map +1 -0
- package/dist/loader/cache.d.ts +15 -0
- package/dist/loader/cache.js +37 -0
- package/dist/loader/cache.js.map +1 -0
- package/dist/loader/dispose.d.ts +3 -0
- package/dist/loader/dispose.js +25 -0
- package/dist/loader/dispose.js.map +1 -0
- package/dist/loader.d.ts +99 -0
- package/dist/loader.js +234 -0
- package/dist/loader.js.map +1 -0
- package/dist/lod.d.ts +78 -0
- package/dist/lod.js +211 -0
- package/dist/lod.js.map +1 -0
- package/dist/material.d.ts +12 -0
- package/dist/material.js +52 -0
- package/dist/material.js.map +1 -0
- package/dist/pause.d.ts +6 -0
- package/dist/pause.js +20 -0
- package/dist/pause.js.map +1 -0
- package/dist/renderer.d.ts +21 -0
- package/dist/renderer.js +83 -0
- package/dist/renderer.js.map +1 -0
- package/dist/simplify.d.ts +24 -0
- package/dist/simplify.js +148 -0
- package/dist/simplify.js.map +1 -0
- package/dist/source/error.d.ts +14 -0
- package/dist/source/error.js +94 -0
- package/dist/source/error.js.map +1 -0
- package/dist/source/frame.d.ts +11 -0
- package/dist/source/frame.js +25 -0
- package/dist/source/frame.js.map +1 -0
- package/dist/source/shading.d.ts +96 -0
- package/dist/source/shading.js +224 -0
- package/dist/source/shading.js.map +1 -0
- package/dist/source/source.d.ts +23 -0
- package/dist/source/source.js +50 -0
- package/dist/source/source.js.map +1 -0
- package/dist/source/surface.d.ts +31 -0
- package/dist/source/surface.js +110 -0
- package/dist/source/surface.js.map +1 -0
- package/dist/source/texels.d.ts +45 -0
- package/dist/source/texels.js +191 -0
- package/dist/source/texels.js.map +1 -0
- package/dist/source/trace.d.ts +42 -0
- package/dist/source/trace.js +153 -0
- package/dist/source/trace.js.map +1 -0
- package/dist/three.d.ts +55 -0
- package/dist/three.js +103 -0
- package/dist/three.js.map +1 -0
- package/dist/tsl.d.ts +45 -0
- package/dist/tsl.js +99 -0
- package/dist/tsl.js.map +1 -0
- package/dist/view.d.ts +30 -0
- package/dist/view.js +75 -0
- package/dist/view.js.map +1 -0
- package/dist/wind/bounds.d.ts +3 -0
- package/dist/wind/bounds.js +47 -0
- package/dist/wind/bounds.js.map +1 -0
- package/dist/wind/hooks.d.ts +5 -0
- package/dist/wind/hooks.js +3 -0
- package/dist/wind/hooks.js.map +1 -0
- package/dist/wind/index.d.ts +57 -0
- package/dist/wind/index.js +196 -0
- package/dist/wind/index.js.map +1 -0
- package/dist/wind/sway.d.ts +29 -0
- package/dist/wind/sway.js +71 -0
- package/dist/wind/sway.js.map +1 -0
- package/package.json +69 -3
- package/skills/lod/SKILL.md +137 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { BufferAttribute, BufferGeometry, DataTexture, DoubleSide, FrontSide, LinearFilter, LinearMipmapLinearFilter, Mesh, MeshStandardNodeMaterial, Matrix4, NoColorSpace, RGFormat, RGBAFormat, SRGBColorSpace, UnsignedByteType, Vector3, } from "three/webgpu";
|
|
2
|
+
import { boundingBox, forEachMesh } from "../bounds.js";
|
|
3
|
+
import { recordError } from "../levels.js";
|
|
4
|
+
import { sharedRenderer } from "../renderer.js";
|
|
5
|
+
import { readSource } from "../source/source.js";
|
|
6
|
+
import { area } from "../source/surface.js";
|
|
7
|
+
import { mipmaps } from "../source/texels.js";
|
|
8
|
+
import { isImpostorMesh, placeLike } from "../three.js";
|
|
9
|
+
import { renderFaces } from "./interior/faces.js";
|
|
10
|
+
import { InteriorMaterial } from "./interior/material.js";
|
|
11
|
+
import { readBoxes } from "./interior/rooms.js";
|
|
12
|
+
import { layOut, simplified } from "./low.js";
|
|
13
|
+
import { transfer } from "./transfer.js";
|
|
14
|
+
import { keepCoverage } from "./coverage.js";
|
|
15
|
+
/**
|
|
16
|
+
* Bake `source` (in its own space, ignoring its own transform) onto one low-poly mesh with
|
|
17
|
+
* its own textures: base colour (alpha: cut out or not), tangent-space normal and
|
|
18
|
+
* occlusion/roughness/metalness, drawn with a MeshStandardNodeMaterial. The mesh is placed
|
|
19
|
+
* like `source`. Materials are read on the CPU as MeshStandardMaterials (color, map,
|
|
20
|
+
* alphaTest, roughness, metalness, normal and ao maps); emissive, clearcoat, transmission
|
|
21
|
+
* and the like are not baked, and blended transparency bakes opaque: glass in its own
|
|
22
|
+
* colour, or as windows into the rooms of `interior`. Textures must be readable on the
|
|
23
|
+
* CPU (no compressed textures).
|
|
24
|
+
*
|
|
25
|
+
* Nested LODs are baked at their level 0; InstancedMeshes, and the source level of an
|
|
26
|
+
* InstancedLod, once per instance: a field of plants bakes as a whole. Skinned meshes
|
|
27
|
+
* and ImpostorMeshes (which have no surface to read) are refused.
|
|
28
|
+
*
|
|
29
|
+
* For each texel of the low mesh, the outermost source surface along the low mesh's
|
|
30
|
+
* normal is shaded. How far the result is off, the larger of a texel's size and the low
|
|
31
|
+
* surface's distance from the source, sets its default maxPixels in a Lod.
|
|
32
|
+
*
|
|
33
|
+
* Experimental, and slow: it runs on the calling thread, yielding to the page now and
|
|
34
|
+
* then.
|
|
35
|
+
*/
|
|
36
|
+
export async function bakeMesh(source, options = {}) {
|
|
37
|
+
const { interior } = options;
|
|
38
|
+
if (!interior)
|
|
39
|
+
return bake(source, options, null);
|
|
40
|
+
const placement = placementOf(interior, source);
|
|
41
|
+
const boxes = readBoxes(interior, placement);
|
|
42
|
+
// Hidden for the whole bake, which yields: a scene drawing it meanwhile shows it gone.
|
|
43
|
+
const visible = interior.visible;
|
|
44
|
+
interior.visible = false;
|
|
45
|
+
try {
|
|
46
|
+
return await bake(source, options, { object: interior, placement, boxes });
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
interior.visible = visible;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function bake(source, options, interior) {
|
|
53
|
+
forEachMesh(source, (mesh) => {
|
|
54
|
+
if (isImpostorMesh(mesh))
|
|
55
|
+
throw new Error(`bakeMesh: cannot bake an ImpostorMesh ("${mesh.name}"); bake from its source instead`);
|
|
56
|
+
});
|
|
57
|
+
const input = readSource(source, "bakeMesh", "bake");
|
|
58
|
+
const size = options.textureSize ?? (input.cutout ? 512 : 1024);
|
|
59
|
+
if (!Number.isInteger(size) || size < 16)
|
|
60
|
+
throw new Error(`bakeMesh: textureSize must be an integer >= 16, got ${size}`);
|
|
61
|
+
const ratio = options.ratio ?? 0.05;
|
|
62
|
+
if (!(ratio > 0 && ratio <= 1))
|
|
63
|
+
throw new Error(`bakeMesh: ratio must be in (0, 1], got ${ratio}`);
|
|
64
|
+
const low = await layOut(options.low ?? (await simplified(input, ratio)), input, size);
|
|
65
|
+
if (low.raster.covered === 0)
|
|
66
|
+
throw new Error("bakeMesh: the low mesh covers no texel");
|
|
67
|
+
const texelSize = Math.sqrt(area(low) / low.raster.covered);
|
|
68
|
+
const radius = boundingBox(source).getSize(new Vector3()).length() / 2;
|
|
69
|
+
// How far rays search: far enough for every feature the low mesh cut off, never so far
|
|
70
|
+
// that they reach through to the other side of thin parts.
|
|
71
|
+
const reach = Math.min(Math.max(low.widest * 1.25, radius * 0.005), radius * 0.15);
|
|
72
|
+
const maps = await transfer(input, low, reach, texelSize, interior && interior.boxes);
|
|
73
|
+
const geometry = new BufferGeometry();
|
|
74
|
+
geometry.setAttribute("position", new BufferAttribute(low.positions, 3));
|
|
75
|
+
geometry.setAttribute("normal", new BufferAttribute(low.normals, 3));
|
|
76
|
+
geometry.setAttribute("uv", new BufferAttribute(low.uvs, 2));
|
|
77
|
+
geometry.setIndex(new BufferAttribute(low.index, 1));
|
|
78
|
+
geometry.computeBoundingBox();
|
|
79
|
+
geometry.computeBoundingSphere();
|
|
80
|
+
const orm = bakedTexture({ data: maps.orm, width: size, height: size }, NoColorSpace);
|
|
81
|
+
const color = { data: maps.color, width: size, height: size };
|
|
82
|
+
const material = new (interior ? InteriorMaterial : MeshStandardNodeMaterial)({
|
|
83
|
+
// Cut-outs get mips that keep their coverage; else the GPU's are as good.
|
|
84
|
+
map: bakedTexture(color, SRGBColorSpace, input.cutout ? keepCoverage(mipmaps(color, true)) : undefined),
|
|
85
|
+
normalMap: bakedTexture({ data: maps.normal, width: size, height: size }, NoColorSpace),
|
|
86
|
+
aoMap: orm,
|
|
87
|
+
roughnessMap: orm,
|
|
88
|
+
metalnessMap: orm,
|
|
89
|
+
roughness: 1,
|
|
90
|
+
metalness: 1,
|
|
91
|
+
alphaTest: input.cutout ? 0.5 : 0,
|
|
92
|
+
side: input.inputs.some((inputs) => inputs.doubleSided) ? DoubleSide : FrontSide,
|
|
93
|
+
});
|
|
94
|
+
if (interior && material instanceof InteriorMaterial) {
|
|
95
|
+
const { windows } = maps;
|
|
96
|
+
if (!windows.some((value, i) => i % 2 === 0 && value > 0))
|
|
97
|
+
throw new Error("bakeMesh: no glass of the source looks into a room of the interior");
|
|
98
|
+
const { boxes } = interior;
|
|
99
|
+
const faces = await renderFaces(interior.object, interior.placement, boxes, faceSize(size, boxes.length), await sharedRenderer());
|
|
100
|
+
material.furnish({ ...faces, boxes, windows: windowTexture(windows, size) });
|
|
101
|
+
}
|
|
102
|
+
const mesh = new Mesh(geometry, material);
|
|
103
|
+
mesh.name = `${source.name || "object"} baked`;
|
|
104
|
+
placeLike(mesh, source);
|
|
105
|
+
recordError(mesh, Math.max(texelSize, low.error));
|
|
106
|
+
return mesh;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Pixels per side of each room's cube faces: all of them together about as many as one
|
|
110
|
+
* baked map of `size`², within 32..256.
|
|
111
|
+
*/
|
|
112
|
+
const faceSize = (size, rooms) => Math.min(256, Math.max(32, 2 ** Math.floor(Math.log2(size / Math.sqrt(6 * rooms)))));
|
|
113
|
+
/** Where `interior` sits in `source`'s own space: as a child of it, or where it is if inside it. */
|
|
114
|
+
function placementOf(interior, source) {
|
|
115
|
+
let inside = false;
|
|
116
|
+
interior.traverseAncestors((node) => (inside ||= node === source));
|
|
117
|
+
if (!inside) {
|
|
118
|
+
if (interior.matrixAutoUpdate)
|
|
119
|
+
interior.updateMatrix();
|
|
120
|
+
return interior.matrix.clone();
|
|
121
|
+
}
|
|
122
|
+
interior.updateWorldMatrix(true, false);
|
|
123
|
+
return source.matrixWorld.clone().invert().multiply(interior.matrixWorld);
|
|
124
|
+
}
|
|
125
|
+
/** The windows of `transfer`, as a texture: its share is filtered, its rooms read texel by texel. */
|
|
126
|
+
function windowTexture(windows, size) {
|
|
127
|
+
const texture = new DataTexture(windows, size, size, RGFormat, UnsignedByteType);
|
|
128
|
+
texture.minFilter = LinearMipmapLinearFilter;
|
|
129
|
+
texture.magFilter = LinearFilter;
|
|
130
|
+
texture.generateMipmaps = true;
|
|
131
|
+
texture.unpackAlignment = 1;
|
|
132
|
+
texture.needsUpdate = true;
|
|
133
|
+
return texture;
|
|
134
|
+
}
|
|
135
|
+
/** A texture of baked pixels, with `mips` as its mipmaps if given, else the GPU's. */
|
|
136
|
+
function bakedTexture(base, colorSpace, mips) {
|
|
137
|
+
const texture = new DataTexture(new Uint8Array(base.data.buffer), base.width, base.height, RGBAFormat, UnsignedByteType);
|
|
138
|
+
texture.colorSpace = colorSpace;
|
|
139
|
+
texture.minFilter = LinearMipmapLinearFilter;
|
|
140
|
+
texture.magFilter = LinearFilter;
|
|
141
|
+
texture.anisotropy = 4;
|
|
142
|
+
if (mips) {
|
|
143
|
+
texture.mipmaps = mips.map(({ data, width, height }) => ({ data: new Uint8Array(data.buffer), width, height }));
|
|
144
|
+
texture.generateMipmaps = false;
|
|
145
|
+
}
|
|
146
|
+
else
|
|
147
|
+
texture.generateMipmaps = true;
|
|
148
|
+
texture.needsUpdate = true;
|
|
149
|
+
return texture;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/baked/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Box3, DataArrayTexture, Vector3, type Matrix4, type Object3D, type Renderer } from "three/webgpu";
|
|
2
|
+
/**
|
|
3
|
+
* The six faces of a room's cube, in layer order: the direction each looks and its up.
|
|
4
|
+
* Its right is forward × up. The baked material's shader (material.ts) reads this table.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FACES: ReadonlyArray<readonly [forward: Vector3, up: Vector3]>;
|
|
7
|
+
/** What each room shows, per cube face: see `renderFaces`. */
|
|
8
|
+
export interface Faces {
|
|
9
|
+
/** the light each room reflects under white ambient light of irradiance π: its colours */
|
|
10
|
+
response: DataArrayTexture;
|
|
11
|
+
/** the light each room gives off itself (emissive and unlit materials); null when none does */
|
|
12
|
+
glow: DataArrayTexture | null;
|
|
13
|
+
/** how far each face's view reaches past its edges: tan of half its field of view */
|
|
14
|
+
span: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Render each room of `interior` (placed in the source's space by `placement`) from its
|
|
18
|
+
* box's centre, six square `size`-pixel views, with the exterior hidden and the other
|
|
19
|
+
* rooms shown, seen through doorways: once in white ambient light and once in none. The difference is how the room
|
|
20
|
+
* responds to light, which the baked material scales by the light reaching its windows;
|
|
21
|
+
* what shows without light is the room's glow. Layer room × 6 + face of each result,
|
|
22
|
+
* sRGB, rows bottom-up: (u, v) = (0.5, 0.5) + 0.5 × (x, y) / (z × span), with x, y and z
|
|
23
|
+
* along the face's right, up and forward. Each view reaches a texel past its edges, so
|
|
24
|
+
* filtering at a face's border reads the neighbouring face's content.
|
|
25
|
+
*/
|
|
26
|
+
export declare function renderFaces(interior: Object3D, placement: Matrix4, boxes: readonly Box3[], size: number, renderer: Renderer): Promise<Faces>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { AmbientLight, Box3, DataArrayTexture, LinearFilter, LinearMipmapLinearFilter, MathUtils, PerspectiveCamera, SRGBColorSpace, Scene, RenderTarget, UnsignedByteType, Vector3, } from "three/webgpu";
|
|
2
|
+
import { showDetail } from "../../bounds.js";
|
|
3
|
+
import { pause } from "../../pause.js";
|
|
4
|
+
import { borrow, readBytes } from "../../renderer.js";
|
|
5
|
+
import { linearToSrgb, srgbToLinear } from "../../source/texels.js";
|
|
6
|
+
/**
|
|
7
|
+
* The six faces of a room's cube, in layer order: the direction each looks and its up.
|
|
8
|
+
* Its right is forward × up. The baked material's shader (material.ts) reads this table.
|
|
9
|
+
*/
|
|
10
|
+
export const FACES = [
|
|
11
|
+
[new Vector3(1, 0, 0), new Vector3(0, 1, 0)],
|
|
12
|
+
[new Vector3(-1, 0, 0), new Vector3(0, 1, 0)],
|
|
13
|
+
[new Vector3(0, 1, 0), new Vector3(0, 0, -1)],
|
|
14
|
+
[new Vector3(0, -1, 0), new Vector3(0, 0, 1)],
|
|
15
|
+
[new Vector3(0, 0, 1), new Vector3(0, 1, 0)],
|
|
16
|
+
[new Vector3(0, 0, -1), new Vector3(0, 1, 0)],
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Render each room of `interior` (placed in the source's space by `placement`) from its
|
|
20
|
+
* box's centre, six square `size`-pixel views, with the exterior hidden and the other
|
|
21
|
+
* rooms shown, seen through doorways: once in white ambient light and once in none. The difference is how the room
|
|
22
|
+
* responds to light, which the baked material scales by the light reaching its windows;
|
|
23
|
+
* what shows without light is the room's glow. Layer room × 6 + face of each result,
|
|
24
|
+
* sRGB, rows bottom-up: (u, v) = (0.5, 0.5) + 0.5 × (x, y) / (z × span), with x, y and z
|
|
25
|
+
* along the face's right, up and forward. Each view reaches a texel past its edges, so
|
|
26
|
+
* filtering at a face's border reads the neighbouring face's content.
|
|
27
|
+
*/
|
|
28
|
+
export async function renderFaces(interior, placement, boxes, size, renderer) {
|
|
29
|
+
const copy = interior.clone();
|
|
30
|
+
copy.matrixAutoUpdate = false;
|
|
31
|
+
copy.matrix.copy(placement);
|
|
32
|
+
copy.visible = true;
|
|
33
|
+
showDetail(copy);
|
|
34
|
+
// At π, three's Lambert (albedo / π) shows a surface in its own colour.
|
|
35
|
+
const ambient = new AmbientLight(0xffffff, Math.PI);
|
|
36
|
+
const scene = new Scene().add(copy, ambient);
|
|
37
|
+
scene.updateMatrixWorld(true);
|
|
38
|
+
const span = 1 + 2 / size;
|
|
39
|
+
const camera = new PerspectiveCamera(MathUtils.radToDeg(2 * Math.atan(span)), 1);
|
|
40
|
+
camera.matrixAutoUpdate = false;
|
|
41
|
+
camera.layers.enableAll();
|
|
42
|
+
const target = new RenderTarget(size, size, { type: UnsignedByteType, colorSpace: SRGBColorSpace, depthBuffer: true });
|
|
43
|
+
const face = size * size * 4;
|
|
44
|
+
const lit = new Uint8Array(face * 6 * boxes.length);
|
|
45
|
+
const glow = new Uint8Array(face * 6 * boxes.length);
|
|
46
|
+
const right = new Vector3();
|
|
47
|
+
const back = new Vector3();
|
|
48
|
+
const centre = new Vector3();
|
|
49
|
+
const extent = new Vector3();
|
|
50
|
+
const shoot = async (into) => {
|
|
51
|
+
const restore = borrow(renderer, target);
|
|
52
|
+
try {
|
|
53
|
+
renderer.clear(true, true, true);
|
|
54
|
+
renderer.render(scene, camera);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
restore();
|
|
58
|
+
}
|
|
59
|
+
into.set(await readBytes(renderer, target, 0));
|
|
60
|
+
};
|
|
61
|
+
// Far enough to see through doorways into any other room.
|
|
62
|
+
const reach = boxes
|
|
63
|
+
.reduce((all, box) => all.union(box), new Box3())
|
|
64
|
+
.getSize(extent)
|
|
65
|
+
.length() * 2;
|
|
66
|
+
try {
|
|
67
|
+
for (const [i, box] of boxes.entries()) {
|
|
68
|
+
camera.near = box.getSize(extent).length() * 1e-3;
|
|
69
|
+
camera.far = reach;
|
|
70
|
+
camera.updateProjectionMatrix();
|
|
71
|
+
box.getCenter(centre);
|
|
72
|
+
for (const [f, [forward, up]] of FACES.entries()) {
|
|
73
|
+
camera.matrix.makeBasis(right.crossVectors(forward, up), up, back.copy(forward).negate()).setPosition(centre);
|
|
74
|
+
camera.updateMatrixWorld(true);
|
|
75
|
+
const at = (i * 6 + f) * face;
|
|
76
|
+
ambient.visible = true;
|
|
77
|
+
await shoot(lit.subarray(at, at + face));
|
|
78
|
+
ambient.visible = false;
|
|
79
|
+
await shoot(glow.subarray(at, at + face));
|
|
80
|
+
}
|
|
81
|
+
await pause();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
target.dispose();
|
|
86
|
+
}
|
|
87
|
+
// Light adds up in linear values: response = lit - glow.
|
|
88
|
+
for (let i = 0; i < lit.length; i++) {
|
|
89
|
+
if (i % 4 === 3)
|
|
90
|
+
continue;
|
|
91
|
+
lit[i] = linearToSrgb(Math.max(0, (SRGB_TO_LINEAR[lit[i] ?? 0] ?? 0) - (SRGB_TO_LINEAR[glow[i] ?? 0] ?? 0))) * 255 + 0.5;
|
|
92
|
+
}
|
|
93
|
+
return { response: layers(lit, size, boxes.length), glow: glow.some((v, i) => i % 4 !== 3 && v > 0) ? layers(glow, size, boxes.length) : null, span };
|
|
94
|
+
}
|
|
95
|
+
const SRGB_TO_LINEAR = Float32Array.from({ length: 256 }, (_, i) => srgbToLinear(i / 255));
|
|
96
|
+
function layers(data, size, rooms) {
|
|
97
|
+
const texture = new DataArrayTexture(data, size, size, rooms * 6);
|
|
98
|
+
texture.colorSpace = SRGBColorSpace;
|
|
99
|
+
texture.minFilter = LinearMipmapLinearFilter;
|
|
100
|
+
texture.magFilter = LinearFilter;
|
|
101
|
+
texture.generateMipmaps = true;
|
|
102
|
+
texture.needsUpdate = true;
|
|
103
|
+
return texture;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=faces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"faces.js","sourceRoot":"","sources":["../../../src/baked/interior/faces.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Matrix4, MeshStandardNodeMaterial, PhysicalLightingModel, type Box3, type DataTexture, type Object3D } from "three/webgpu";
|
|
2
|
+
import { type Faces } from "./faces.js";
|
|
3
|
+
/** What a baked material needs to look into its rooms. */
|
|
4
|
+
export interface Rooms extends Faces {
|
|
5
|
+
boxes: readonly Box3[];
|
|
6
|
+
/**
|
|
7
|
+
* per baked texel: R the room of the nearest window + 1, read texel by texel; G the share
|
|
8
|
+
* of the room that shows, filtered
|
|
9
|
+
*/
|
|
10
|
+
windows: DataTexture;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Tell `mesh`, if it shows rooms, that its geometry was moved by `placement` out of the
|
|
14
|
+
* source's space: InstancedLod draws copies of its templates' geometry placed in the
|
|
15
|
+
* instance's space.
|
|
16
|
+
*/
|
|
17
|
+
export declare function placeInterior(mesh: Object3D, placement: Matrix4): void;
|
|
18
|
+
/**
|
|
19
|
+
* A baked level's material that shows `rooms` through its windows. The rooms' textures
|
|
20
|
+
* go with it.
|
|
21
|
+
*/
|
|
22
|
+
export declare class InteriorMaterial extends MeshStandardNodeMaterial {
|
|
23
|
+
readonly isInteriorMaterial = true;
|
|
24
|
+
rooms: Rooms | null;
|
|
25
|
+
/** Each room's box: its min, then its max. */
|
|
26
|
+
private bounds;
|
|
27
|
+
/** Show `rooms` through the windows. */
|
|
28
|
+
furnish(rooms: Rooms): this;
|
|
29
|
+
setupLightingModel(): PhysicalLightingModel;
|
|
30
|
+
copy(source: InteriorMaterial): this;
|
|
31
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { InterpolationSamplingType, Matrix4, MeshStandardNodeMaterial, PhysicalLightingModel, StorageBufferAttribute, } from "three/webgpu";
|
|
2
|
+
import { If, cameraPosition, cameraProjectionMatrix, cameraWorldMatrix, clamp, cross, dFdx, dFdy, dot, float, int, ivec2, length, log2, mat4, materialEnvIntensity, max, min, modelWorldMatrix, normalize, pmremTexture, positionGeometry, positionWorld, select, sign, step, texture, textureLoad, uniform, uv, varying, vec2, vec3, vec4, } from "three/tsl";
|
|
3
|
+
import { instanceMatrixOf } from "../../fade.js";
|
|
4
|
+
import { isScene } from "../../three.js";
|
|
5
|
+
import { affine, column, contextNode, isNodeOf, isOrthographic, roomBounds } from "../../tsl.js";
|
|
6
|
+
import { FACES } from "./faces.js";
|
|
7
|
+
/** Per mesh: where its geometry's space sits in the source's, when an InstancedLod moved the geometry (see `placeInterior`). */
|
|
8
|
+
const spaces = new WeakMap();
|
|
9
|
+
const identity = new Matrix4();
|
|
10
|
+
const space = uniform(new Matrix4()).onObjectUpdate(({ object }) => (object && spaces.get(object)) ?? identity);
|
|
11
|
+
/**
|
|
12
|
+
* Tell `mesh`, if it shows rooms, that its geometry was moved by `placement` out of the
|
|
13
|
+
* source's space: InstancedLod draws copies of its templates' geometry placed in the
|
|
14
|
+
* instance's space.
|
|
15
|
+
*/
|
|
16
|
+
export function placeInterior(mesh, placement) {
|
|
17
|
+
spaces.set(mesh, placement.clone().invert());
|
|
18
|
+
}
|
|
19
|
+
function flat(node) {
|
|
20
|
+
return varying(node).setInterpolation(InterpolationSamplingType.FLAT);
|
|
21
|
+
}
|
|
22
|
+
/** `vectors[index]`, for an index known only in the shader. */
|
|
23
|
+
function pick(vectors, index) {
|
|
24
|
+
return vectors.reduceRight((rest, v, i) => select(index.equal(i), vec3(v.x, v.y, v.z), rest), vec3(0, 0, 0));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A baked level's material that shows `rooms` through its windows. The rooms' textures
|
|
28
|
+
* go with it.
|
|
29
|
+
*/
|
|
30
|
+
export class InteriorMaterial extends MeshStandardNodeMaterial {
|
|
31
|
+
isInteriorMaterial = true;
|
|
32
|
+
rooms = null;
|
|
33
|
+
/** Each room's box: its min, then its max. */
|
|
34
|
+
bounds = null;
|
|
35
|
+
/** Show `rooms` through the windows. */
|
|
36
|
+
furnish(rooms) {
|
|
37
|
+
const bounds = new StorageBufferAttribute(Float32Array.from(rooms.boxes.flatMap((box) => [...box.min.toArray(), 0, ...box.max.toArray(), 0])), 4);
|
|
38
|
+
this.rooms = rooms;
|
|
39
|
+
this.bounds = bounds;
|
|
40
|
+
this.addEventListener("dispose", () => {
|
|
41
|
+
rooms.response.dispose();
|
|
42
|
+
rooms.glow?.dispose();
|
|
43
|
+
rooms.windows.dispose();
|
|
44
|
+
bounds.dispose();
|
|
45
|
+
});
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
setupLightingModel() {
|
|
49
|
+
return this.rooms && this.bounds ? new InteriorLighting(this.rooms, this.bounds) : super.setupLightingModel();
|
|
50
|
+
}
|
|
51
|
+
copy(source) {
|
|
52
|
+
super.copy(source);
|
|
53
|
+
this.rooms = source.rooms;
|
|
54
|
+
this.bounds = source.bounds;
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The room is lit by indirect light only: the sun's direct light, which walls and roof
|
|
60
|
+
* would block, is left out. Ambient light, light probes and hemisphere lights are taken at
|
|
61
|
+
* the window; the environment, as three lights the real room's walls, at the wall the
|
|
62
|
+
* view ray meets. Its glow adds on top. Glass shows the room by its share, under its own
|
|
63
|
+
* reflection: three's specular term carries the Fresnel.
|
|
64
|
+
*/
|
|
65
|
+
class InteriorLighting extends PhysicalLightingModel {
|
|
66
|
+
rooms;
|
|
67
|
+
bounds;
|
|
68
|
+
constructor(rooms,
|
|
69
|
+
/** see `InteriorMaterial.bounds` */
|
|
70
|
+
bounds) {
|
|
71
|
+
super();
|
|
72
|
+
this.rooms = rooms;
|
|
73
|
+
this.bounds = bounds;
|
|
74
|
+
}
|
|
75
|
+
// After three's lights and before it sums them: by `finish` the sum is made.
|
|
76
|
+
start(builder) {
|
|
77
|
+
super.start(builder);
|
|
78
|
+
const { rooms } = this;
|
|
79
|
+
const irradiance = contextNode(builder, "irradiance");
|
|
80
|
+
const directDiffuse = contextNode(builder, "reflectedLight", "directDiffuse");
|
|
81
|
+
const indirectDiffuse = contextNode(builder, "reflectedLight", "indirectDiffuse");
|
|
82
|
+
if (!isNodeOf(irradiance, "vec3", builder) || !isNodeOf(directDiffuse, "vec3", builder) || !isNodeOf(indirectDiffuse, "vec3", builder))
|
|
83
|
+
throw new Error("bakeMesh: three's lighting is not made of vec3s");
|
|
84
|
+
const count = rooms.boxes.length;
|
|
85
|
+
const boxes = roomBounds(this.bounds);
|
|
86
|
+
const faceSize = rooms.response.image.width;
|
|
87
|
+
const [width, height] = [rooms.windows.image.width, rooms.windows.image.height];
|
|
88
|
+
// The view ray in the source's space, and the source's space to world.
|
|
89
|
+
const instance = instanceMatrixOf(builder.object);
|
|
90
|
+
const toWorld = affine((instance ? modelWorldMatrix.mul(instance) : modelWorldMatrix).mul(affineInverse(space)));
|
|
91
|
+
const back = column(cameraWorldMatrix, 2).xyz;
|
|
92
|
+
const worldRay = select(isOrthographic(cameraProjectionMatrix), back.negate(), positionWorld.sub(cameraPosition));
|
|
93
|
+
const point = varying(space.mul(vec4(positionGeometry, 1)).xyz);
|
|
94
|
+
const ray = varying(toWorld.solve(worldRay));
|
|
95
|
+
const [x, y, z] = toWorld.normalColumns.map(flat);
|
|
96
|
+
if (!x || !y || !z)
|
|
97
|
+
throw new Error("bakeMesh: a normal matrix has three columns");
|
|
98
|
+
const share = texture(rooms.windows, uv()).g;
|
|
99
|
+
const texel = ivec2(clamp(uv().mul(vec2(width, height)), vec2(0, 0), vec2(width - 1, height - 1)));
|
|
100
|
+
// The room's number, 0 for none, as a float: the box's index is clamped to a room.
|
|
101
|
+
const room = float(textureLoad(rooms.windows, texel).r.mul(255).add(0.5).floor()).toVar();
|
|
102
|
+
const box = int(clamp(room.sub(1), 0, count - 1)).toVar();
|
|
103
|
+
const low = boxes.element(box.mul(2)).xyz;
|
|
104
|
+
const high = boxes.element(box.mul(2).add(1)).xyz;
|
|
105
|
+
const unit = normalize(ray);
|
|
106
|
+
// Nudged off zero, so each axis has a crossing.
|
|
107
|
+
const direction = unit
|
|
108
|
+
.add(vec3(1, 1, 1)
|
|
109
|
+
.sub(step(vec3(1e-30, 1e-30, 1e-30), unit.abs()))
|
|
110
|
+
.mul(1e-6))
|
|
111
|
+
.toVar();
|
|
112
|
+
const far = low.sub(point).div(direction).max(high.sub(point).div(direction)).toVar();
|
|
113
|
+
// The box is intersected for every texel, so the derivatives that pick the cube's mip
|
|
114
|
+
// level are defined across window edges.
|
|
115
|
+
const exit = point.add(direction.mul(max(min(far.x, min(far.y, far.z)), 0))).toVar();
|
|
116
|
+
const footprint = max(length(dFdx(exit)), length(dFdy(exit)));
|
|
117
|
+
If(room.greaterThan(0).and(share.greaterThan(0)), () => {
|
|
118
|
+
const wall = exit.sub(low.add(high).mul(0.5));
|
|
119
|
+
const a = wall.abs();
|
|
120
|
+
const face = select(a.x.greaterThanEqual(a.y).and(a.x.greaterThanEqual(a.z)), select(wall.x.greaterThanEqual(0), int(0), int(1)), select(a.y.greaterThanEqual(a.z), select(wall.y.greaterThanEqual(0), int(2), int(3)), select(wall.z.greaterThanEqual(0), int(4), int(5)))).toVar();
|
|
121
|
+
const forward = pick(FACES.map(([f]) => f), face);
|
|
122
|
+
const up = pick(FACES.map(([, u]) => u), face);
|
|
123
|
+
const depth = max(dot(wall, forward), 1e-6).mul(rooms.span);
|
|
124
|
+
const at = vec2(dot(wall, cross(forward, up)), dot(wall, up))
|
|
125
|
+
.div(depth)
|
|
126
|
+
.mul(0.5)
|
|
127
|
+
.add(0.5);
|
|
128
|
+
const layer = box.mul(6).add(face);
|
|
129
|
+
const level = log2(max(footprint.mul(0.5 * faceSize).div(depth), 1e-6));
|
|
130
|
+
const inward = select(far.x.lessThanEqual(min(far.y, far.z)), vec3(sign(direction.x).negate(), 0, 0), select(far.y.lessThanEqual(far.z), vec3(0, sign(direction.y).negate(), 0), vec3(0, 0, sign(direction.z).negate())));
|
|
131
|
+
const wallNormal = normalize(x.mul(inward.x).add(y.mul(inward.y)).add(z.mul(inward.z)));
|
|
132
|
+
const environment = environmentOf(builder.object);
|
|
133
|
+
const ibl = environment ? pmremTexture(environment, wallNormal, float(1)).rgb.mul(Math.PI).mul(materialEnvIntensity) : vec3(0, 0, 0);
|
|
134
|
+
const light = irradiance.add(ibl);
|
|
135
|
+
let shown = texture(rooms.response, at).depth(layer).level(level).rgb.mul(light).div(Math.PI);
|
|
136
|
+
if (rooms.glow)
|
|
137
|
+
shown = shown.add(texture(rooms.glow, at).depth(layer).level(level).rgb);
|
|
138
|
+
const keep = share.oneMinus();
|
|
139
|
+
directDiffuse.assign(directDiffuse.mul(keep));
|
|
140
|
+
indirectDiffuse.assign(indirectDiffuse.mul(keep).add(shown.mul(share)));
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/** The environment of the scene `object` is in, if any. */
|
|
145
|
+
function environmentOf(object) {
|
|
146
|
+
let root = object;
|
|
147
|
+
while (root.parent)
|
|
148
|
+
root = root.parent;
|
|
149
|
+
return isScene(root) ? root.environment : null;
|
|
150
|
+
}
|
|
151
|
+
/** The inverse of an affine `m`, as a matrix: the linear part's inverse and the translation undone. */
|
|
152
|
+
function affineInverse(m) {
|
|
153
|
+
const inverse = affine(m);
|
|
154
|
+
const solve = (v) => vec4(inverse.solve(v), 0);
|
|
155
|
+
return mat4(solve(vec3(1, 0, 0)), solve(vec3(0, 1, 0)), solve(vec3(0, 0, 1)), vec4(inverse.unproject(vec3(0, 0, 0)), 1));
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=material.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"material.js","sourceRoot":"","sources":["../../../src/baked/interior/material.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Box3, Vector3, type Matrix4, type Object3D } from "three/webgpu";
|
|
2
|
+
/**
|
|
3
|
+
* The boxes of `interior`'s rooms, in the source's own space: one per direct child, the
|
|
4
|
+
* bounds of what it draws. `placement` puts the interior in the source's space.
|
|
5
|
+
*
|
|
6
|
+
* Lights are refused: wherever the source draws they would be scene lights, so every
|
|
7
|
+
* switch to or from it changes the scene's light count (and recompiles every lit
|
|
8
|
+
* material), and an InstancedLod's templates light nothing. Lamps glow with emissive
|
|
9
|
+
* materials instead.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readBoxes(interior: Object3D, placement: Matrix4): Box3[];
|
|
12
|
+
/**
|
|
13
|
+
* How far behind glass a room may begin: half the thinnest room's smallest side. A wall
|
|
14
|
+
* between glass and room is thinner than any room; a ray that met no room within half a
|
|
15
|
+
* room's size is not looking into one through this glass.
|
|
16
|
+
*/
|
|
17
|
+
export declare function windowDepth(boxes: readonly Box3[]): number;
|
|
18
|
+
/**
|
|
19
|
+
* The room a ray from `origin` along unit `direction` is in or enters first within
|
|
20
|
+
* `far`: the room behind a window. -1 for none.
|
|
21
|
+
*/
|
|
22
|
+
export declare function roomAlong(boxes: readonly Box3[], origin: Vector3, direction: Vector3, far: number): number;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Box3, Ray, Vector3 } from "three/webgpu";
|
|
2
|
+
import { forEachVertex } from "../../bounds.js";
|
|
3
|
+
import { isLight } from "../../three.js";
|
|
4
|
+
/** Most rooms an interior may have: six faces each in texture arrays of at most 256 layers. */
|
|
5
|
+
const MAX_ROOMS = 42;
|
|
6
|
+
/** Share of the smaller box two rooms may overlap by: walls that meet, not rooms inside rooms. */
|
|
7
|
+
const OVERLAP = 0.02;
|
|
8
|
+
/**
|
|
9
|
+
* The boxes of `interior`'s rooms, in the source's own space: one per direct child, the
|
|
10
|
+
* bounds of what it draws. `placement` puts the interior in the source's space.
|
|
11
|
+
*
|
|
12
|
+
* Lights are refused: wherever the source draws they would be scene lights, so every
|
|
13
|
+
* switch to or from it changes the scene's light count (and recompiles every lit
|
|
14
|
+
* material), and an InstancedLod's templates light nothing. Lamps glow with emissive
|
|
15
|
+
* materials instead.
|
|
16
|
+
*/
|
|
17
|
+
export function readBoxes(interior, placement) {
|
|
18
|
+
interior.traverse((node) => {
|
|
19
|
+
if (isLight(node))
|
|
20
|
+
throw new Error(`bakeMesh: the interior has a light ("${node.name}"); give lamps emissive materials instead`);
|
|
21
|
+
});
|
|
22
|
+
const rooms = interior.children;
|
|
23
|
+
if (rooms.length === 0)
|
|
24
|
+
throw new Error("bakeMesh: the interior has no rooms: each direct child of it is one room");
|
|
25
|
+
if (rooms.length > MAX_ROOMS)
|
|
26
|
+
throw new Error(`bakeMesh: the interior has ${rooms.length} rooms, at most ${MAX_ROOMS} are supported`);
|
|
27
|
+
const boxes = rooms.map((room, i) => {
|
|
28
|
+
if (room.matrixAutoUpdate)
|
|
29
|
+
room.updateMatrix();
|
|
30
|
+
const matrix = placement.clone().multiply(room.matrix);
|
|
31
|
+
const box = new Box3();
|
|
32
|
+
forEachVertex(room, (p) => box.expandByPoint(p.applyMatrix4(matrix)));
|
|
33
|
+
if (box.isEmpty())
|
|
34
|
+
throw new Error(`bakeMesh: room ${i} ("${room.name}") of the interior draws nothing`);
|
|
35
|
+
return box;
|
|
36
|
+
});
|
|
37
|
+
boxes.forEach((a, i) => boxes.slice(i + 1).forEach((b, k) => {
|
|
38
|
+
const shared = volume(a.clone().intersect(b));
|
|
39
|
+
if (shared > OVERLAP * Math.min(volume(a), volume(b)))
|
|
40
|
+
throw new Error(`bakeMesh: rooms ${i} ("${rooms[i]?.name}") and ${i + k + 1} ("${rooms[i + k + 1]?.name}") of the interior overlap: each room fills a box of its own`);
|
|
41
|
+
}));
|
|
42
|
+
return boxes;
|
|
43
|
+
}
|
|
44
|
+
function volume(box) {
|
|
45
|
+
if (box.isEmpty())
|
|
46
|
+
return 0;
|
|
47
|
+
const { x, y, z } = box.getSize(new Vector3());
|
|
48
|
+
return x * y * z;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* How far behind glass a room may begin: half the thinnest room's smallest side. A wall
|
|
52
|
+
* between glass and room is thinner than any room; a ray that met no room within half a
|
|
53
|
+
* room's size is not looking into one through this glass.
|
|
54
|
+
*/
|
|
55
|
+
export function windowDepth(boxes) {
|
|
56
|
+
const size = new Vector3();
|
|
57
|
+
return Math.min(...boxes.map((box) => Math.min(...box.getSize(size).toArray()))) / 2;
|
|
58
|
+
}
|
|
59
|
+
const ray = new Ray();
|
|
60
|
+
const enter = new Vector3();
|
|
61
|
+
/**
|
|
62
|
+
* The room a ray from `origin` along unit `direction` is in or enters first within
|
|
63
|
+
* `far`: the room behind a window. -1 for none.
|
|
64
|
+
*/
|
|
65
|
+
export function roomAlong(boxes, origin, direction, far) {
|
|
66
|
+
ray.set(origin, direction);
|
|
67
|
+
let nearest = -1;
|
|
68
|
+
let best = far;
|
|
69
|
+
boxes.forEach((box, i) => {
|
|
70
|
+
const distance = box.containsPoint(origin) ? 0 : ray.intersectBox(box, enter)?.distanceTo(origin);
|
|
71
|
+
if (distance === undefined || distance > best)
|
|
72
|
+
return;
|
|
73
|
+
best = distance;
|
|
74
|
+
nearest = i;
|
|
75
|
+
});
|
|
76
|
+
return nearest;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=rooms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rooms.js","sourceRoot":"","sources":["../../../src/baked/interior/rooms.ts"],"names":[],"mappings":"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"}
|