@oeave/bakery3 0.1.0 → 0.3.0
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/README.md +10 -10
- package/dist/bake/index.d.ts +3 -3
- package/dist/bake/index.js +4 -4
- package/dist/{bake-DaOlenyx.d.ts → bake-DZ-CJR6f.d.ts} +8 -1
- package/dist/catalog/index.d.ts +5 -5
- package/dist/catalog/index.js +3 -3
- package/dist/{chunk-TGFNQBKC.js → chunk-3T3FJOSD.js} +5 -5
- package/dist/chunk-3T3FJOSD.js.map +1 -0
- package/dist/{chunk-V3QINEEG.js → chunk-62M6XXNX.js} +58 -3
- package/dist/chunk-62M6XXNX.js.map +1 -0
- package/dist/{chunk-ARMTTZXZ.js → chunk-6FAMQZXB.js} +8 -8
- package/dist/chunk-6FAMQZXB.js.map +1 -0
- package/dist/{chunk-54WJDN5R.js → chunk-CSSJRP5W.js} +9 -6
- package/dist/chunk-CSSJRP5W.js.map +1 -0
- package/dist/{chunk-W6WQ5UP7.js → chunk-EN4ROBYQ.js} +32 -5
- package/dist/chunk-EN4ROBYQ.js.map +1 -0
- package/dist/chunk-KZLVTSBI.js +191 -0
- package/dist/chunk-KZLVTSBI.js.map +1 -0
- package/dist/{chunk-MD2U6S4N.js → chunk-LAKXC4WR.js} +218 -142
- package/dist/chunk-LAKXC4WR.js.map +1 -0
- package/dist/{chunk-HQTUFVMM.js → chunk-NEK5TBEH.js} +3 -3
- package/dist/chunk-NEK5TBEH.js.map +1 -0
- package/dist/chunk-OPM2L63B.js +253 -0
- package/dist/chunk-OPM2L63B.js.map +1 -0
- package/dist/{chunk-APBOWWSV.js → chunk-R5IUPOWI.js} +3 -3
- package/dist/chunk-R5IUPOWI.js.map +1 -0
- package/dist/{chunk-6YVQANMW.js → chunk-STRK4SZN.js} +262 -16
- package/dist/chunk-STRK4SZN.js.map +1 -0
- package/dist/{chunk-CX4WTVGH.js → chunk-WLEFNUOH.js} +411 -371
- package/dist/chunk-WLEFNUOH.js.map +1 -0
- package/dist/{chunk-25ZXSVQ3.js → chunk-X6GW43EX.js} +3 -3
- package/dist/{chunk-25ZXSVQ3.js.map → chunk-X6GW43EX.js.map} +1 -1
- package/dist/{chunk-WBIAFIHV.js → chunk-XK35ANPJ.js} +3 -3
- package/dist/{chunk-WBIAFIHV.js.map → chunk-XK35ANPJ.js.map} +1 -1
- package/dist/devtools/index.d.ts +3 -3
- package/dist/devtools/index.js +10 -9
- package/dist/hotspots/index.d.ts +237 -31
- package/dist/hotspots/index.js +1013 -118
- package/dist/hotspots/index.js.map +1 -1
- package/dist/index.d.ts +39 -8
- package/dist/index.js +11 -10
- package/dist/node/index.cjs +266 -141
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +152 -87
- package/dist/node/index.d.ts +27 -6
- package/dist/node/index.js +52 -3
- package/dist/node/index.js.map +1 -1
- package/dist/{prepare-C5qVvaw4.d.ts → prepare-BtjY4G3q.d.ts} +1 -1
- package/dist/presets/index.d.ts +37 -1
- package/dist/presets/index.js +4 -4
- package/dist/presets/index.js.map +1 -1
- package/dist/r3f/index.d.ts +4 -4
- package/dist/r3f/index.js +13 -12
- package/dist/r3f/index.js.map +1 -1
- package/dist/{room-S5TLCK4F.js → room-BM7Z7NKG.js} +6 -6
- package/dist/{room-S5TLCK4F.js.map → room-BM7Z7NKG.js.map} +1 -1
- package/dist/{rooms.gen-vhj6sFW5.d.ts → rooms.gen-DItzBR9k.d.ts} +112 -84
- package/dist/session-NPVBESWA.js +9 -0
- package/dist/{session-YCQS4MRH.js.map → session-NPVBESWA.js.map} +1 -1
- package/dist/{testRun-BIPXaVPb.d.ts → testRun-20OARnQr.d.ts} +12 -3
- package/dist/tsl/index.d.ts +14 -1
- package/dist/tsl/index.js +8 -2
- package/dist/tsl/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-54WJDN5R.js.map +0 -1
- package/dist/chunk-6YVQANMW.js.map +0 -1
- package/dist/chunk-AF5BIELI.js +0 -70
- package/dist/chunk-AF5BIELI.js.map +0 -1
- package/dist/chunk-APBOWWSV.js.map +0 -1
- package/dist/chunk-ARMTTZXZ.js.map +0 -1
- package/dist/chunk-CX4WTVGH.js.map +0 -1
- package/dist/chunk-HQTUFVMM.js.map +0 -1
- package/dist/chunk-MD2U6S4N.js.map +0 -1
- package/dist/chunk-TGFNQBKC.js.map +0 -1
- package/dist/chunk-V3QINEEG.js.map +0 -1
- package/dist/chunk-W6WQ5UP7.js.map +0 -1
- package/dist/session-YCQS4MRH.js +0 -9
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { captureCamera } from './chunk-
|
|
2
|
-
import { protocolVersionFor, SDK_VERSION, QUALITY } from './chunk-
|
|
1
|
+
import { captureCamera } from './chunk-62M6XXNX.js';
|
|
2
|
+
import { protocolVersionFor, SDK_VERSION, QUALITY } from './chunk-R5IUPOWI.js';
|
|
3
3
|
import { BAKERY_NODE_MARKER, builtinFor, tslRuntimeRegistered, toNodeObject } from './chunk-S4AJTLLN.js';
|
|
4
|
-
import {
|
|
5
|
-
import { idOf, shouldExclude, captureFog,
|
|
6
|
-
import { MAX_BAKE_OBJECTS, MAX_BAKE_TEXELS, roomIsPrebaked, roomPrebakeChanges, MAX_BAKE_SIMPLIFY, BAKE_TEXTURE_SIZES, MAX_BAKE_SIMPLIFY_TRIANGLES, BAKE_ATLAS_SIZES } from './chunk-
|
|
4
|
+
import { sha256, environmentSourceFor, isPresetEnvironment } from './chunk-KZLVTSBI.js';
|
|
5
|
+
import { idOf, shouldExclude, captureFog, scenePath, captureLights, captureRuntime, stampIds, captureEnvironmentSettings, excludedItself, readUserData, bakeCandidates, resolveProbe, defaultIncludeIds, quantizeBakeView, bakeBounds, isBakeWrittenUv, ID_KEY } from './chunk-NEK5TBEH.js';
|
|
6
|
+
import { findPresetRooms, roomShownBaked, roomPresetFactsOf, roomPresetSpecOf, roomPresetAssetsOf, MAX_BAKE_OBJECTS, MAX_BAKE_TEXELS, roomIsPrebaked, roomPrebakeChanges, MAX_BAKE_SIMPLIFY, BAKE_TEXTURE_SIZES, MAX_BAKE_SIMPLIFY_TRIANGLES, BAKE_ATLAS_SIZES } from './chunk-EN4ROBYQ.js';
|
|
7
7
|
import { Bakery3Error } from './chunk-3G5QL4F4.js';
|
|
8
|
-
import {
|
|
8
|
+
import { readCameraLookAt, propertyDefinition, CAMERA_PROPERTIES, OBJECT_PROPERTIES, hexToLinear } from './chunk-OPM2L63B.js';
|
|
9
|
+
import { Vector3, Vector2, Matrix4, Quaternion, Color, MeshPhysicalMaterial, MeshStandardMaterial, LinearSRGBColorSpace } from 'three';
|
|
9
10
|
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
|
|
10
11
|
|
|
11
12
|
// src/timeline/easing.ts
|
|
@@ -163,256 +164,6 @@ function normalize(v) {
|
|
|
163
164
|
return length === 0 ? [0, 0, 0] : [v[0] / length, v[1] / length, v[2] / length];
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
// src/timeline/properties.ts
|
|
167
|
-
function hemisphereOf(object) {
|
|
168
|
-
const light = object;
|
|
169
|
-
return light.isHemisphereLight ? light : void 0;
|
|
170
|
-
}
|
|
171
|
-
function sceneOf(object) {
|
|
172
|
-
const scene = object;
|
|
173
|
-
return scene.isScene ? scene : void 0;
|
|
174
|
-
}
|
|
175
|
-
function aimedLight(object) {
|
|
176
|
-
const light = object;
|
|
177
|
-
return (light.isDirectionalLight || light.isSpotLight) && light.target ? light : void 0;
|
|
178
|
-
}
|
|
179
|
-
function materialOf(object) {
|
|
180
|
-
const material = object.material;
|
|
181
|
-
if (!material) return void 0;
|
|
182
|
-
return Array.isArray(material) ? material[0] : material;
|
|
183
|
-
}
|
|
184
|
-
function readVector(v) {
|
|
185
|
-
return v ? [v.x, v.y, v.z] : void 0;
|
|
186
|
-
}
|
|
187
|
-
function scalar(get, set) {
|
|
188
|
-
return {
|
|
189
|
-
size: 1,
|
|
190
|
-
read(object) {
|
|
191
|
-
const material = materialOf(object);
|
|
192
|
-
const value = material ? get(material) : void 0;
|
|
193
|
-
return typeof value === "number" ? [value] : void 0;
|
|
194
|
-
},
|
|
195
|
-
write(object, value) {
|
|
196
|
-
const material = materialOf(object);
|
|
197
|
-
if (material) set(material, value[0]);
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
function colorProperty(pick) {
|
|
202
|
-
return {
|
|
203
|
-
size: 3,
|
|
204
|
-
color: true,
|
|
205
|
-
read(object) {
|
|
206
|
-
const target = pick(object);
|
|
207
|
-
return target ? [target.r, target.g, target.b] : void 0;
|
|
208
|
-
},
|
|
209
|
-
write(object, value) {
|
|
210
|
-
const target = pick(object);
|
|
211
|
-
if (!target) return;
|
|
212
|
-
if (target.setRGB) target.setRGB(value[0], value[1], value[2]);
|
|
213
|
-
else Object.assign(target, { r: value[0], g: value[1], b: value[2] });
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
var OBJECT_PROPERTIES = {
|
|
218
|
-
position: {
|
|
219
|
-
size: 3,
|
|
220
|
-
read: (object) => readVector(object.position),
|
|
221
|
-
write: (object, value) => object.position.set(value[0], value[1], value[2])
|
|
222
|
-
},
|
|
223
|
-
rotation: {
|
|
224
|
-
size: 3,
|
|
225
|
-
channel: "quaternion",
|
|
226
|
-
read: (object) => readVector(
|
|
227
|
-
object.rotation
|
|
228
|
-
),
|
|
229
|
-
write: (object, value) => object.rotation.set(value[0], value[1], value[2])
|
|
230
|
-
},
|
|
231
|
-
scale: {
|
|
232
|
-
size: 3,
|
|
233
|
-
read: (object) => readVector(object.scale),
|
|
234
|
-
write: (object, value) => object.scale.set(value[0], value[1], value[2])
|
|
235
|
-
},
|
|
236
|
-
// A light's own color (the worker drives the lamp, or for an ambient or
|
|
237
|
-
// hemisphere light the dome), and a mesh's material's.
|
|
238
|
-
color: colorProperty(
|
|
239
|
-
(object) => object.isLight ? object.color : materialOf(object)?.color
|
|
240
|
-
),
|
|
241
|
-
emissive: colorProperty((object) => materialOf(object)?.emissive),
|
|
242
|
-
emissiveIntensity: scalar(
|
|
243
|
-
(material) => material.emissiveIntensity,
|
|
244
|
-
(material, value) => {
|
|
245
|
-
material.emissiveIntensity = value;
|
|
246
|
-
}
|
|
247
|
-
),
|
|
248
|
-
roughness: scalar(
|
|
249
|
-
(material) => material.roughness,
|
|
250
|
-
(material, value) => {
|
|
251
|
-
material.roughness = value;
|
|
252
|
-
}
|
|
253
|
-
),
|
|
254
|
-
metalness: scalar(
|
|
255
|
-
(material) => material.metalness,
|
|
256
|
-
(material, value) => {
|
|
257
|
-
material.metalness = value;
|
|
258
|
-
}
|
|
259
|
-
),
|
|
260
|
-
opacity: scalar(
|
|
261
|
-
(material) => material.opacity,
|
|
262
|
-
(material, value) => {
|
|
263
|
-
material.opacity = value;
|
|
264
|
-
if (value < 1 && !material.transparent) {
|
|
265
|
-
material.transparent = true;
|
|
266
|
-
material.needsUpdate = true;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
),
|
|
270
|
-
intensity: {
|
|
271
|
-
size: 1,
|
|
272
|
-
read(object) {
|
|
273
|
-
const light = object;
|
|
274
|
-
return light.isLight && typeof light.intensity === "number" ? [light.intensity] : void 0;
|
|
275
|
-
},
|
|
276
|
-
write(object, value) {
|
|
277
|
-
const light = object;
|
|
278
|
-
if (light.isLight) light.intensity = value[0];
|
|
279
|
-
}
|
|
280
|
-
},
|
|
281
|
-
/** A HemisphereLight's color from below. Its `color` is the sky. */
|
|
282
|
-
groundColor: {
|
|
283
|
-
...colorProperty((object) => hemisphereOf(object)?.groundColor),
|
|
284
|
-
appliesTo: (object) => hemisphereOf(object) !== void 0
|
|
285
|
-
},
|
|
286
|
-
/**
|
|
287
|
-
* The scene's own `environmentIntensity`, on the Scene as a target: the
|
|
288
|
-
* environment's `intensity` channel. It scales the HDRI only, as in three.
|
|
289
|
-
*/
|
|
290
|
-
environmentIntensity: {
|
|
291
|
-
size: 1,
|
|
292
|
-
appliesTo: (object) => sceneOf(object) !== void 0,
|
|
293
|
-
read(object) {
|
|
294
|
-
const value = sceneOf(object)?.environmentIntensity;
|
|
295
|
-
return typeof value === "number" ? [value] : void 0;
|
|
296
|
-
},
|
|
297
|
-
write(object, value) {
|
|
298
|
-
const scene = sceneOf(object);
|
|
299
|
-
if (scene) scene.environmentIntensity = value[0];
|
|
300
|
-
}
|
|
301
|
-
},
|
|
302
|
-
/**
|
|
303
|
-
* The scene's `environmentRotation`, radians, XYZ, as three holds it: the
|
|
304
|
-
* environment's `rotation` channel. Unlike an object's rotation it stays
|
|
305
|
-
* an euler on the wire, because that is what the environment carries.
|
|
306
|
-
*/
|
|
307
|
-
environmentRotation: {
|
|
308
|
-
size: 3,
|
|
309
|
-
appliesTo: (object) => sceneOf(object) !== void 0,
|
|
310
|
-
read: (object) => readVector(sceneOf(object)?.environmentRotation),
|
|
311
|
-
write(object, value) {
|
|
312
|
-
sceneOf(object)?.environmentRotation?.set(
|
|
313
|
-
value[0],
|
|
314
|
-
value[1],
|
|
315
|
-
value[2]
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
},
|
|
319
|
-
/**
|
|
320
|
-
* Where a directional or spot light aims: its `target`'s WORLD position,
|
|
321
|
-
* which is what three aims it at and what the channel carries. Written
|
|
322
|
-
* back through the target's parent, if it has one, so the light points at
|
|
323
|
-
* the same place in the viewport as in the render.
|
|
324
|
-
*/
|
|
325
|
-
target: {
|
|
326
|
-
size: 3,
|
|
327
|
-
appliesTo: (object) => aimedLight(object) !== void 0,
|
|
328
|
-
read(object) {
|
|
329
|
-
const target = aimedLight(object)?.target;
|
|
330
|
-
if (!target) return void 0;
|
|
331
|
-
target.updateMatrixWorld();
|
|
332
|
-
const e = target.matrixWorld.elements;
|
|
333
|
-
return [e[12], e[13], e[14]];
|
|
334
|
-
},
|
|
335
|
-
write(object, value) {
|
|
336
|
-
const target = aimedLight(object)?.target;
|
|
337
|
-
if (!target) return;
|
|
338
|
-
target.position.set(value[0], value[1], value[2]);
|
|
339
|
-
target.parent?.worldToLocal(target.position);
|
|
340
|
-
target.updateMatrixWorld();
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
var CAMERA_PROPERTIES = {
|
|
345
|
-
position: OBJECT_PROPERTIES.position,
|
|
346
|
-
lookAt: {
|
|
347
|
-
size: 3,
|
|
348
|
-
// There is no live "lookAt" to read; the timeline supplies its own center
|
|
349
|
-
// when a keyframe is captured. Returning undefined keeps the panel from
|
|
350
|
-
// offering a capture button that would silently record the wrong thing.
|
|
351
|
-
read: () => void 0,
|
|
352
|
-
// Applied together with position by the timeline, never alone: aiming at a
|
|
353
|
-
// point before moving to the position it was computed for produces one
|
|
354
|
-
// frame of visible swing.
|
|
355
|
-
write: () => void 0
|
|
356
|
-
},
|
|
357
|
-
fov: {
|
|
358
|
-
size: 1,
|
|
359
|
-
read(object) {
|
|
360
|
-
const camera = object;
|
|
361
|
-
return typeof camera.fov === "number" ? [camera.fov] : void 0;
|
|
362
|
-
},
|
|
363
|
-
write(object, value) {
|
|
364
|
-
const camera = object;
|
|
365
|
-
if (typeof camera.fov !== "number") return;
|
|
366
|
-
camera.fov = value[0];
|
|
367
|
-
camera.updateProjectionMatrix?.();
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
function propertyDefinition(target, property) {
|
|
372
|
-
return target === "camera" ? CAMERA_PROPERTIES[property] : OBJECT_PROPERTIES[property];
|
|
373
|
-
}
|
|
374
|
-
function readCameraLookAt(camera, center) {
|
|
375
|
-
camera.updateMatrixWorld();
|
|
376
|
-
const e = camera.matrixWorld.elements;
|
|
377
|
-
const position = [e[12], e[13], e[14]];
|
|
378
|
-
const forward = normalize2([-e[8], -e[9], -e[10]]);
|
|
379
|
-
const distance = Math.hypot(
|
|
380
|
-
position[0] - center[0],
|
|
381
|
-
position[1] - center[1],
|
|
382
|
-
position[2] - center[2]
|
|
383
|
-
) || 1;
|
|
384
|
-
return [
|
|
385
|
-
position[0] + forward[0] * distance,
|
|
386
|
-
position[1] + forward[1] * distance,
|
|
387
|
-
position[2] + forward[2] * distance
|
|
388
|
-
];
|
|
389
|
-
}
|
|
390
|
-
function normalize2(v) {
|
|
391
|
-
const length = Math.hypot(v[0], v[1], v[2]);
|
|
392
|
-
return length === 0 ? [0, 0, -1] : [v[0] / length, v[1] / length, v[2] / length];
|
|
393
|
-
}
|
|
394
|
-
function hexToLinear(hex) {
|
|
395
|
-
const value = hex.trim().replace(/^#/, "");
|
|
396
|
-
const full = value.length === 3 ? value.split("").map((c) => c + c).join("") : value;
|
|
397
|
-
const int = Number.parseInt(full, 16);
|
|
398
|
-
if (!Number.isFinite(int)) return [1, 1, 1];
|
|
399
|
-
return [
|
|
400
|
-
srgbToLinear((int >> 16 & 255) / 255),
|
|
401
|
-
srgbToLinear((int >> 8 & 255) / 255),
|
|
402
|
-
srgbToLinear((int & 255) / 255)
|
|
403
|
-
];
|
|
404
|
-
}
|
|
405
|
-
function srgbToLinear(c) {
|
|
406
|
-
return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);
|
|
407
|
-
}
|
|
408
|
-
function linearToSrgbHex(value) {
|
|
409
|
-
const channel = (v) => {
|
|
410
|
-
const srgb = v < 31308e-7 ? v * 12.92 : 1.055 * Math.pow(Math.max(v, 0), 0.41666) - 0.055;
|
|
411
|
-
return Math.round(Math.max(0, Math.min(1, srgb)) * 255).toString(16).padStart(2, "0");
|
|
412
|
-
};
|
|
413
|
-
return `#${channel(value[0] ?? 0)}${channel(value[1] ?? 0)}${channel(value[2] ?? 0)}`;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
167
|
// src/protocol/animation.ts
|
|
417
168
|
var ENVIRONMENT_CHANNEL_SIZES = {
|
|
418
169
|
intensity: 1,
|
|
@@ -1317,7 +1068,7 @@ var Timeline = class _Timeline {
|
|
|
1317
1068
|
const { at, end } = this.span(options);
|
|
1318
1069
|
for (const [property, raw] of Object.entries(props)) {
|
|
1319
1070
|
const track = this.track(target, property);
|
|
1320
|
-
const value =
|
|
1071
|
+
const value = normalize2(raw, track.size, property);
|
|
1321
1072
|
this.anchor(track, at);
|
|
1322
1073
|
this.insert(track, {
|
|
1323
1074
|
time: end,
|
|
@@ -1337,14 +1088,14 @@ var Timeline = class _Timeline {
|
|
|
1337
1088
|
if (start !== void 0) {
|
|
1338
1089
|
this.insert(track, {
|
|
1339
1090
|
time: at,
|
|
1340
|
-
value:
|
|
1091
|
+
value: normalize2(start, track.size, property)
|
|
1341
1092
|
});
|
|
1342
1093
|
} else {
|
|
1343
1094
|
this.anchor(track, at);
|
|
1344
1095
|
}
|
|
1345
1096
|
this.insert(track, {
|
|
1346
1097
|
time: end,
|
|
1347
|
-
value:
|
|
1098
|
+
value: normalize2(raw, track.size, property),
|
|
1348
1099
|
...options.easing ? { easing: options.easing } : {}
|
|
1349
1100
|
});
|
|
1350
1101
|
}
|
|
@@ -1452,7 +1203,7 @@ var Timeline = class _Timeline {
|
|
|
1452
1203
|
*/
|
|
1453
1204
|
keyframe(target, property, time = this._time, value) {
|
|
1454
1205
|
const track = this.track(target, property);
|
|
1455
|
-
const resolved = value !== void 0 ?
|
|
1206
|
+
const resolved = value !== void 0 ? normalize2(value, track.size, property) : this.live(target, property) ?? this.valueAt(track, time);
|
|
1456
1207
|
if (!resolved) {
|
|
1457
1208
|
throw new Bakery3Error({
|
|
1458
1209
|
code: "InvalidRequest",
|
|
@@ -1925,7 +1676,7 @@ function noCamera(what, bound) {
|
|
|
1925
1676
|
function createTimeline(options = {}) {
|
|
1926
1677
|
return new Timeline(options);
|
|
1927
1678
|
}
|
|
1928
|
-
function
|
|
1679
|
+
function normalize2(value, size, property) {
|
|
1929
1680
|
const flat = flatten(value, size, property);
|
|
1930
1681
|
if (flat && flat.length === size && flat.every((n) => Number.isFinite(n)))
|
|
1931
1682
|
return flat;
|
|
@@ -2936,7 +2687,7 @@ function staticProperties(material) {
|
|
|
2936
2687
|
properties[key] = `#${value.getHexString()}`;
|
|
2937
2688
|
}
|
|
2938
2689
|
};
|
|
2939
|
-
const
|
|
2690
|
+
const scalar = (key, prop) => {
|
|
2940
2691
|
const value = material[prop];
|
|
2941
2692
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2942
2693
|
properties[key] = value;
|
|
@@ -2947,23 +2698,23 @@ function staticProperties(material) {
|
|
|
2947
2698
|
color("sheenColor", "sheenColor");
|
|
2948
2699
|
color("specularColor", "specularColor");
|
|
2949
2700
|
color("attenuationColor", "attenuationColor");
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2701
|
+
scalar("roughness", "roughness");
|
|
2702
|
+
scalar("metalness", "metalness");
|
|
2703
|
+
scalar("emissiveIntensity", "emissiveIntensity");
|
|
2704
|
+
scalar("opacity", "opacity");
|
|
2705
|
+
scalar("alphaTest", "alphaTest");
|
|
2706
|
+
scalar("ior", "ior");
|
|
2707
|
+
scalar("transmission", "transmission");
|
|
2708
|
+
scalar("thickness", "thickness");
|
|
2709
|
+
scalar("attenuationDistance", "attenuationDistance");
|
|
2710
|
+
scalar("clearcoat", "clearcoat");
|
|
2711
|
+
scalar("clearcoatRoughness", "clearcoatRoughness");
|
|
2712
|
+
scalar("sheen", "sheen");
|
|
2713
|
+
scalar("sheenRoughness", "sheenRoughness");
|
|
2714
|
+
scalar("specularIntensity", "specularIntensity");
|
|
2715
|
+
scalar("iridescence", "iridescence");
|
|
2716
|
+
scalar("iridescenceIOR", "iridescenceIOR");
|
|
2717
|
+
scalar("anisotropy", "anisotropy");
|
|
2967
2718
|
if (material.transparent === true) properties.transparent = true;
|
|
2968
2719
|
if (material.side === 2) properties.doubleSided = true;
|
|
2969
2720
|
return properties;
|
|
@@ -3024,6 +2775,175 @@ function describeNodeType(type) {
|
|
|
3024
2775
|
};
|
|
3025
2776
|
return KNOWN[type] ?? `A "${type}"`;
|
|
3026
2777
|
}
|
|
2778
|
+
function fallbackFor(material, object) {
|
|
2779
|
+
const own = material.userData?.bakery3?.fallback;
|
|
2780
|
+
if (isRecord(own)) return { values: own, declaredOn: "material" };
|
|
2781
|
+
const objects = readUserData(object).fallback;
|
|
2782
|
+
if (isRecord(objects)) return { values: objects, declaredOn: "object" };
|
|
2783
|
+
return null;
|
|
2784
|
+
}
|
|
2785
|
+
function objectFallbackId(material, object) {
|
|
2786
|
+
return `${idOf(material)}@${idOf(object)}`;
|
|
2787
|
+
}
|
|
2788
|
+
function fallbackMaterialId(material, object, fallback) {
|
|
2789
|
+
return fallback.declaredOn === "object" ? objectFallbackId(material, object) : idOf(material);
|
|
2790
|
+
}
|
|
2791
|
+
function exporterCannotWrite(material) {
|
|
2792
|
+
const m = material;
|
|
2793
|
+
if (m.isShaderMaterial) return true;
|
|
2794
|
+
return typeof m.color?.toArray !== "function";
|
|
2795
|
+
}
|
|
2796
|
+
function fallbackEmits(values) {
|
|
2797
|
+
if (values.emissive === void 0) return false;
|
|
2798
|
+
const intensity = typeof values.emissiveIntensity === "number" ? values.emissiveIntensity : 1;
|
|
2799
|
+
if (!(intensity > 0)) return false;
|
|
2800
|
+
const color = toColor(values.emissive);
|
|
2801
|
+
return Boolean(color && color.r + color.g + color.b > 0);
|
|
2802
|
+
}
|
|
2803
|
+
function materialStandIns(root) {
|
|
2804
|
+
const shared = /* @__PURE__ */ new Map();
|
|
2805
|
+
const standIns = /* @__PURE__ */ new Map();
|
|
2806
|
+
root.traverse((object) => {
|
|
2807
|
+
if (shouldExclude(object)) return;
|
|
2808
|
+
const drawable = object;
|
|
2809
|
+
if (!(drawable.isMesh || drawable.isLine || drawable.isPoints)) return;
|
|
2810
|
+
if (!drawable.material) return;
|
|
2811
|
+
const list = Array.isArray(drawable.material) ? drawable.material : [drawable.material];
|
|
2812
|
+
const own = /* @__PURE__ */ new Map();
|
|
2813
|
+
let changed = false;
|
|
2814
|
+
const written = list.map((material) => {
|
|
2815
|
+
if (!material) return material;
|
|
2816
|
+
const standIn2 = standInFor(material, object, shared, own);
|
|
2817
|
+
if (standIn2 !== material) changed = true;
|
|
2818
|
+
return standIn2;
|
|
2819
|
+
});
|
|
2820
|
+
if (!changed) return;
|
|
2821
|
+
standIns.set(
|
|
2822
|
+
object,
|
|
2823
|
+
Array.isArray(drawable.material) ? written : written[0]
|
|
2824
|
+
);
|
|
2825
|
+
});
|
|
2826
|
+
return standIns;
|
|
2827
|
+
}
|
|
2828
|
+
function standInFor(material, object, shared, own) {
|
|
2829
|
+
const fallback = fallbackFor(material, object);
|
|
2830
|
+
if (fallback?.declaredOn === "object") {
|
|
2831
|
+
let copy2 = own.get(material);
|
|
2832
|
+
if (!copy2) {
|
|
2833
|
+
copy2 = standIn(
|
|
2834
|
+
material,
|
|
2835
|
+
fallback.values,
|
|
2836
|
+
objectFallbackId(material, object)
|
|
2837
|
+
);
|
|
2838
|
+
own.set(material, copy2);
|
|
2839
|
+
}
|
|
2840
|
+
return copy2;
|
|
2841
|
+
}
|
|
2842
|
+
if (!fallback && !exporterCannotWrite(material)) return material;
|
|
2843
|
+
let copy = shared.get(material);
|
|
2844
|
+
if (!copy) {
|
|
2845
|
+
copy = standIn(material, fallback?.values ?? null, idOf(material));
|
|
2846
|
+
shared.set(material, copy);
|
|
2847
|
+
}
|
|
2848
|
+
return copy;
|
|
2849
|
+
}
|
|
2850
|
+
function standIn(material, fallback, id) {
|
|
2851
|
+
const out = fallback ? fromFallback(fallback) : flatGray();
|
|
2852
|
+
out.name = material.name;
|
|
2853
|
+
out.side = material.side;
|
|
2854
|
+
const userData = {
|
|
2855
|
+
...material.userData,
|
|
2856
|
+
[ID_KEY]: id
|
|
2857
|
+
};
|
|
2858
|
+
if (fallback) {
|
|
2859
|
+
const bakery3 = isRecord(userData.bakery3) ? userData.bakery3 : {};
|
|
2860
|
+
userData.bakery3 = { ...bakery3, fallback };
|
|
2861
|
+
}
|
|
2862
|
+
out.userData = userData;
|
|
2863
|
+
return out;
|
|
2864
|
+
}
|
|
2865
|
+
function flatGray() {
|
|
2866
|
+
const material = new MeshStandardMaterial({ roughness: 1, metalness: 0 });
|
|
2867
|
+
material.color.setRGB(0.8, 0.8, 0.8, LinearSRGBColorSpace);
|
|
2868
|
+
return material;
|
|
2869
|
+
}
|
|
2870
|
+
var NUMBER_FIELDS = [
|
|
2871
|
+
"metalness",
|
|
2872
|
+
"roughness",
|
|
2873
|
+
"clearcoat",
|
|
2874
|
+
"clearcoatRoughness",
|
|
2875
|
+
"transmission",
|
|
2876
|
+
"thickness",
|
|
2877
|
+
"ior",
|
|
2878
|
+
"emissiveIntensity",
|
|
2879
|
+
"opacity",
|
|
2880
|
+
"sheen",
|
|
2881
|
+
"iridescence",
|
|
2882
|
+
"anisotropy"
|
|
2883
|
+
];
|
|
2884
|
+
function fromFallback(values) {
|
|
2885
|
+
const material = new MeshPhysicalMaterial();
|
|
2886
|
+
const color = toColor(values.color);
|
|
2887
|
+
if (color) material.color.copy(color);
|
|
2888
|
+
const emissive = toColor(values.emissive);
|
|
2889
|
+
if (emissive) material.emissive.copy(emissive);
|
|
2890
|
+
const sheenColor = toColor(values.sheenColor);
|
|
2891
|
+
if (sheenColor) material.sheenColor.copy(sheenColor);
|
|
2892
|
+
const target = material;
|
|
2893
|
+
for (const field of NUMBER_FIELDS) {
|
|
2894
|
+
const value = values[field];
|
|
2895
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
2896
|
+
target[field] = value;
|
|
2897
|
+
}
|
|
2898
|
+
if (material.opacity < 1) material.transparent = true;
|
|
2899
|
+
return material;
|
|
2900
|
+
}
|
|
2901
|
+
function toColor(value) {
|
|
2902
|
+
if (typeof value !== "string" && typeof value !== "number" && !value?.isColor)
|
|
2903
|
+
return null;
|
|
2904
|
+
return new Color(value);
|
|
2905
|
+
}
|
|
2906
|
+
function substituteMaterials(exporter, standIns) {
|
|
2907
|
+
let undo = () => {
|
|
2908
|
+
};
|
|
2909
|
+
if (standIns.size === 0) return undo;
|
|
2910
|
+
exporter.register((writer) => {
|
|
2911
|
+
const steps = writer;
|
|
2912
|
+
const name = ["processMeshAsync", "processMesh"].find(
|
|
2913
|
+
(key) => typeof steps[key] === "function"
|
|
2914
|
+
);
|
|
2915
|
+
if (name) {
|
|
2916
|
+
const original = steps[name];
|
|
2917
|
+
steps[name] = function(mesh) {
|
|
2918
|
+
const material = standIns.get(mesh);
|
|
2919
|
+
return original.call(
|
|
2920
|
+
this,
|
|
2921
|
+
material ? Object.create(mesh, {
|
|
2922
|
+
material: { value: material, enumerable: true }
|
|
2923
|
+
}) : mesh
|
|
2924
|
+
);
|
|
2925
|
+
};
|
|
2926
|
+
} else {
|
|
2927
|
+
undo = swapOnScene(standIns);
|
|
2928
|
+
}
|
|
2929
|
+
return {};
|
|
2930
|
+
});
|
|
2931
|
+
return () => undo();
|
|
2932
|
+
}
|
|
2933
|
+
function swapOnScene(standIns) {
|
|
2934
|
+
const originals = [];
|
|
2935
|
+
for (const [object, material] of standIns) {
|
|
2936
|
+
const drawable = object;
|
|
2937
|
+
originals.push({ object: drawable, material: drawable.material });
|
|
2938
|
+
drawable.material = material;
|
|
2939
|
+
}
|
|
2940
|
+
return () => {
|
|
2941
|
+
for (const { object, material } of originals) object.material = material;
|
|
2942
|
+
};
|
|
2943
|
+
}
|
|
2944
|
+
function isRecord(value) {
|
|
2945
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2946
|
+
}
|
|
3027
2947
|
|
|
3028
2948
|
// src/compat/analyze.ts
|
|
3029
2949
|
var DOCS2 = "https://bakery3.com/docs";
|
|
@@ -3031,15 +2951,46 @@ var LARGE_TEXTURE_PX = 4096;
|
|
|
3031
2951
|
var LARGE_TRIANGLE_COUNT = 1e7;
|
|
3032
2952
|
var TRANSLATABLE = /* @__PURE__ */ new Set(["MeshStandardMaterial", "MeshPhysicalMaterial"]);
|
|
3033
2953
|
var APPROXIMATED = {
|
|
3034
|
-
MeshBasicMaterial: "
|
|
3035
|
-
MeshLambertMaterial: "
|
|
3036
|
-
MeshPhongMaterial: "
|
|
3037
|
-
MeshToonMaterial: "
|
|
3038
|
-
MeshMatcapMaterial: "
|
|
3039
|
-
MeshNormalMaterial: "
|
|
3040
|
-
MeshDepthMaterial: "
|
|
3041
|
-
MeshDistanceMaterial: "
|
|
2954
|
+
MeshBasicMaterial: "It shows its color and map unlit, as in the viewport, but it does not light the scene, cast a shadow, or show in reflections or through glass.",
|
|
2955
|
+
MeshLambertMaterial: "It renders as a fully rough, non-metal surface in its color and map.",
|
|
2956
|
+
MeshPhongMaterial: "It renders as a fully rough, non-metal surface in its color and map, like Lambert. Its `shininess` and `specular` are not used, so it has no sharp highlights.",
|
|
2957
|
+
MeshToonMaterial: "It renders as a fully rough, non-metal surface in its color and map, without the cel shading of its `gradientMap`.",
|
|
2958
|
+
MeshMatcapMaterial: "It renders as a fully rough, non-metal surface in its color and map, lit by the scene. The `matcap` texture is not used.",
|
|
2959
|
+
MeshNormalMaterial: "It renders flat gray. It colors a surface by its normals, which is a debug view, not a look.",
|
|
2960
|
+
MeshDepthMaterial: "It renders flat gray. It shows depth, which is a debug view, not a look.",
|
|
2961
|
+
MeshDistanceMaterial: "It renders flat gray. It is made for shadow maps, not for a visible surface."
|
|
3042
2962
|
};
|
|
2963
|
+
var IGNORED = [
|
|
2964
|
+
{
|
|
2965
|
+
name: "alphaMap",
|
|
2966
|
+
used: (m) => isTexture(m.alphaMap) && Boolean(m.transparent || m.alphaTest > 0 || m.alphaHash),
|
|
2967
|
+
fix: "For a cutout, use the alpha channel of `map`."
|
|
2968
|
+
},
|
|
2969
|
+
{
|
|
2970
|
+
name: "bumpMap",
|
|
2971
|
+
used: (m) => isTexture(m.bumpMap) && m.bumpScale !== 0,
|
|
2972
|
+
fix: "Bake bump detail into a `normalMap`."
|
|
2973
|
+
},
|
|
2974
|
+
{
|
|
2975
|
+
name: "displacementMap",
|
|
2976
|
+
used: (m) => isTexture(m.displacementMap) && m.displacementScale !== 0,
|
|
2977
|
+
fix: "Model the shape, or bake the detail into a `normalMap`."
|
|
2978
|
+
},
|
|
2979
|
+
{ name: "specularMap", used: (m) => isTexture(m.specularMap) },
|
|
2980
|
+
{ name: "iridescence", used: (m) => m.iridescence > 0 },
|
|
2981
|
+
{
|
|
2982
|
+
name: "iridescenceMap",
|
|
2983
|
+
used: (m) => m.iridescence > 0 && isTexture(m.iridescenceMap)
|
|
2984
|
+
},
|
|
2985
|
+
{
|
|
2986
|
+
name: "iridescenceThicknessMap",
|
|
2987
|
+
used: (m) => m.iridescence > 0 && isTexture(m.iridescenceThicknessMap)
|
|
2988
|
+
},
|
|
2989
|
+
{
|
|
2990
|
+
name: "dispersion",
|
|
2991
|
+
used: (m) => m.dispersion > 0 && m.transmission > 0
|
|
2992
|
+
}
|
|
2993
|
+
];
|
|
3043
2994
|
function emitsLight(material) {
|
|
3044
2995
|
const m = material;
|
|
3045
2996
|
if (m.isMeshBasicMaterial) return true;
|
|
@@ -3052,6 +3003,7 @@ function emitsLight(material) {
|
|
|
3052
3003
|
function analyzeScene(root) {
|
|
3053
3004
|
const issues = [];
|
|
3054
3005
|
const seenMaterials = /* @__PURE__ */ new Set();
|
|
3006
|
+
const unfaithful = /* @__PURE__ */ new Set();
|
|
3055
3007
|
const seenTextures = /* @__PURE__ */ new Set();
|
|
3056
3008
|
let triangles = 0;
|
|
3057
3009
|
let faithfulTriangles = 0;
|
|
@@ -3085,12 +3037,21 @@ function analyzeScene(root) {
|
|
|
3085
3037
|
});
|
|
3086
3038
|
}
|
|
3087
3039
|
}
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
if (
|
|
3091
|
-
|
|
3040
|
+
const fallback = fallbackFor(material, object);
|
|
3041
|
+
const key = fallback?.declaredOn === "object" ? `${object.uuid}:${material.uuid}` : material.uuid;
|
|
3042
|
+
if (seenMaterials.has(key)) {
|
|
3043
|
+
if (unfaithful.has(key)) objectIsFaithful = false;
|
|
3044
|
+
continue;
|
|
3045
|
+
}
|
|
3046
|
+
seenMaterials.add(key);
|
|
3047
|
+
if (fallback ? fallbackEmits(fallback.values) : emitsLight(material))
|
|
3048
|
+
emitters++;
|
|
3049
|
+
for (const issue of classifyMaterial(material, object, fallback)) {
|
|
3092
3050
|
issues.push(issue);
|
|
3093
|
-
if (issue.severity === "error")
|
|
3051
|
+
if (issue.severity === "error") {
|
|
3052
|
+
objectIsFaithful = false;
|
|
3053
|
+
unfaithful.add(key);
|
|
3054
|
+
}
|
|
3094
3055
|
}
|
|
3095
3056
|
}
|
|
3096
3057
|
if (objectIsFaithful) faithfulTriangles += count;
|
|
@@ -3123,98 +3084,142 @@ function collectFallbacks(root) {
|
|
|
3123
3084
|
const fallbacks = [];
|
|
3124
3085
|
const seen = /* @__PURE__ */ new Set();
|
|
3125
3086
|
root.traverse((object) => {
|
|
3087
|
+
if (shouldExclude(object)) return;
|
|
3126
3088
|
const mesh = object;
|
|
3127
3089
|
if (!mesh.isMesh) return;
|
|
3128
3090
|
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
3129
3091
|
for (const material of materials) {
|
|
3130
|
-
if (!material
|
|
3131
|
-
const
|
|
3132
|
-
if (!
|
|
3133
|
-
|
|
3092
|
+
if (!material) continue;
|
|
3093
|
+
const fallback = fallbackFor(material, object);
|
|
3094
|
+
if (!fallback) continue;
|
|
3095
|
+
const materialId = fallbackMaterialId(material, object, fallback);
|
|
3096
|
+
if (seen.has(materialId)) continue;
|
|
3097
|
+
seen.add(materialId);
|
|
3134
3098
|
fallbacks.push({
|
|
3135
|
-
...
|
|
3136
|
-
materialId
|
|
3099
|
+
...fallback.values,
|
|
3100
|
+
materialId,
|
|
3137
3101
|
type: "physical"
|
|
3138
3102
|
});
|
|
3139
3103
|
}
|
|
3140
3104
|
});
|
|
3141
3105
|
return fallbacks;
|
|
3142
3106
|
}
|
|
3143
|
-
function classifyMaterial(material, object) {
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3107
|
+
function classifyMaterial(material, object, fallback) {
|
|
3108
|
+
if (fallback) {
|
|
3109
|
+
return [
|
|
3110
|
+
{
|
|
3111
|
+
code: "material_fallback_used",
|
|
3112
|
+
severity: "info",
|
|
3113
|
+
message: `${labelOf(material)} renders with your declared fallback.`,
|
|
3114
|
+
path: pathOf(object),
|
|
3115
|
+
materialId: fallbackMaterialId(material, object, fallback),
|
|
3116
|
+
materialName: material.name,
|
|
3117
|
+
materialType: material.type,
|
|
3118
|
+
docs: `${DOCS2}/material-fallbacks`
|
|
3119
|
+
}
|
|
3120
|
+
];
|
|
3121
|
+
}
|
|
3122
|
+
if (isNodeMaterial(material)) {
|
|
3148
3123
|
const extracted = extractMaterialShader(material);
|
|
3149
|
-
|
|
3124
|
+
const issues = extracted.issues.map((issue) => ({
|
|
3150
3125
|
...issue,
|
|
3151
3126
|
path: pathOf(object),
|
|
3152
3127
|
materialId: idOf(material),
|
|
3153
3128
|
materialName: material.name,
|
|
3154
3129
|
materialType: material.type
|
|
3155
3130
|
}));
|
|
3131
|
+
if (!extracted.spec)
|
|
3132
|
+
issues.push(...classicIssues(material, object, classicType(material)));
|
|
3133
|
+
return issues;
|
|
3156
3134
|
}
|
|
3157
|
-
|
|
3158
|
-
return verdict ? [verdict.issue] : [];
|
|
3135
|
+
return classicIssues(material, object, material.type);
|
|
3159
3136
|
}
|
|
3160
|
-
function
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3137
|
+
function classicIssues(material, object, type) {
|
|
3138
|
+
const issues = [];
|
|
3139
|
+
const verdict = classify(material, object, type);
|
|
3140
|
+
if (verdict) issues.push(verdict);
|
|
3141
|
+
if (!exporterCannotWrite(material)) {
|
|
3142
|
+
const ignored = ignoredSlots(material, object);
|
|
3143
|
+
if (ignored) issues.push(ignored);
|
|
3144
|
+
}
|
|
3145
|
+
return issues;
|
|
3146
|
+
}
|
|
3147
|
+
function classify(material, object, type) {
|
|
3148
|
+
if (TRANSLATABLE.has(type)) return null;
|
|
3149
|
+
const about = {
|
|
3150
|
+
path: pathOf(object),
|
|
3151
|
+
materialId: idOf(material),
|
|
3152
|
+
materialName: material.name,
|
|
3153
|
+
materialType: material.type
|
|
3154
|
+
};
|
|
3155
|
+
if (material.isShaderMaterial) {
|
|
3177
3156
|
return {
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
materialId: idOf(material),
|
|
3184
|
-
materialName: material.name,
|
|
3185
|
-
materialType: material.type,
|
|
3186
|
-
docs: `${DOCS2}/material-fallbacks`
|
|
3187
|
-
}
|
|
3157
|
+
code: "material_custom_shader",
|
|
3158
|
+
severity: "error",
|
|
3159
|
+
message: `${labelOf(material)} renders flat gray, because the render cannot run GLSL. Declare a fallback, or port it to TSL.`,
|
|
3160
|
+
...about,
|
|
3161
|
+
docs: `${DOCS2}/material-fallbacks`
|
|
3188
3162
|
};
|
|
3189
3163
|
}
|
|
3190
|
-
const approximation = APPROXIMATED[
|
|
3164
|
+
const approximation = APPROXIMATED[type];
|
|
3191
3165
|
if (approximation) {
|
|
3192
3166
|
return {
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
materialId: idOf(material),
|
|
3199
|
-
materialName: material.name,
|
|
3200
|
-
materialType: material.type,
|
|
3201
|
-
docs: `${DOCS2}/materials`
|
|
3202
|
-
}
|
|
3167
|
+
code: "material_approximated",
|
|
3168
|
+
severity: "warning",
|
|
3169
|
+
message: `${labelOf(material)} is approximated. ${approximation}${emissiveNote(material)}`,
|
|
3170
|
+
...about,
|
|
3171
|
+
docs: `${DOCS2}/materials`
|
|
3203
3172
|
};
|
|
3204
3173
|
}
|
|
3174
|
+
const looks = exporterCannotWrite(material) ? "flat gray" : "as a fully rough, non-metal surface in its color";
|
|
3205
3175
|
return {
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
materialId: idOf(material),
|
|
3212
|
-
materialName: material.name,
|
|
3213
|
-
materialType: material.type,
|
|
3214
|
-
docs: `${DOCS2}/materials`
|
|
3215
|
-
}
|
|
3176
|
+
code: "material_unknown",
|
|
3177
|
+
severity: "error",
|
|
3178
|
+
message: `${labelOf(material)} renders ${looks}, because the render does not support this material. Use MeshStandardMaterial or MeshPhysicalMaterial, or declare a fallback.`,
|
|
3179
|
+
...about,
|
|
3180
|
+
docs: `${DOCS2}/materials`
|
|
3216
3181
|
};
|
|
3217
3182
|
}
|
|
3183
|
+
function emissiveNote(material) {
|
|
3184
|
+
const m = material;
|
|
3185
|
+
if (m.isMeshStandardMaterial || !m.emissive) return "";
|
|
3186
|
+
if (m.emissiveIntensity === void 0 || m.emissiveIntensity === 1) return "";
|
|
3187
|
+
if (m.emissive.r + m.emissive.g + m.emissive.b <= 0) return "";
|
|
3188
|
+
return " Its `emissiveIntensity` is not used, so it glows at intensity 1.";
|
|
3189
|
+
}
|
|
3190
|
+
function ignoredSlots(material, object) {
|
|
3191
|
+
const record2 = material;
|
|
3192
|
+
const ignored = IGNORED.filter((slot) => slot.used(record2));
|
|
3193
|
+
if (!ignored.length) return null;
|
|
3194
|
+
const names = ignored.map((slot) => `\`${slot.name}\``);
|
|
3195
|
+
const list = names.length === 1 ? names[0] : `${names.slice(0, -1).join(", ")} and ${names[names.length - 1]}`;
|
|
3196
|
+
const fixes = ignored.flatMap((slot) => slot.fix ? [slot.fix] : []);
|
|
3197
|
+
return {
|
|
3198
|
+
code: "material_map_ignored",
|
|
3199
|
+
severity: "warning",
|
|
3200
|
+
message: [
|
|
3201
|
+
`${labelOf(material)} uses ${list}, which the render ignores.`,
|
|
3202
|
+
...fixes
|
|
3203
|
+
].join(" "),
|
|
3204
|
+
path: pathOf(object),
|
|
3205
|
+
materialId: idOf(material),
|
|
3206
|
+
materialName: material.name,
|
|
3207
|
+
materialType: material.type,
|
|
3208
|
+
docs: `${DOCS2}/materials#slots-the-render-ignores`
|
|
3209
|
+
};
|
|
3210
|
+
}
|
|
3211
|
+
function classicType(material) {
|
|
3212
|
+
const m = material;
|
|
3213
|
+
if (m.isMeshPhysicalMaterial) return "MeshPhysicalMaterial";
|
|
3214
|
+
if (m.isMeshStandardMaterial) return "MeshStandardMaterial";
|
|
3215
|
+
return material.type.replace(/NodeMaterial$/, "Material");
|
|
3216
|
+
}
|
|
3217
|
+
function labelOf(material) {
|
|
3218
|
+
return `${material.type} "${material.name || "unnamed"}"`;
|
|
3219
|
+
}
|
|
3220
|
+
function isTexture(value) {
|
|
3221
|
+
return Boolean(value?.isTexture);
|
|
3222
|
+
}
|
|
3218
3223
|
var TEXTURE_SLOTS = [
|
|
3219
3224
|
"map",
|
|
3220
3225
|
"normalMap",
|
|
@@ -3268,7 +3273,8 @@ function sceneComplexity(scene, camera) {
|
|
|
3268
3273
|
let objects = 0;
|
|
3269
3274
|
const visit = (object) => {
|
|
3270
3275
|
if (!object.visible) return;
|
|
3271
|
-
|
|
3276
|
+
const shell = Boolean(object.userData?.bakery3RoomShell);
|
|
3277
|
+
if (excludedItself(object) && !rooms.has(object) && !shell) return;
|
|
3272
3278
|
const mesh = object;
|
|
3273
3279
|
if (mesh.isMesh && mesh.geometry?.attributes?.position) {
|
|
3274
3280
|
const position = mesh.geometry.attributes.position;
|
|
@@ -3279,7 +3285,7 @@ function sceneComplexity(scene, camera) {
|
|
|
3279
3285
|
(_, i) => i % 3 === 0 ? position.getX(i / 3 | 0) : i % 3 === 1 ? position.getY(i / 3 | 0) : position.getZ(i / 3 | 0)
|
|
3280
3286
|
);
|
|
3281
3287
|
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
3282
|
-
const emitter = materials.length > 0 && materials.every((material) => material && emitsLight(material));
|
|
3288
|
+
const emitter = !shell && materials.length > 0 && materials.every((material) => material && emitsLight(material));
|
|
3283
3289
|
const base = {
|
|
3284
3290
|
positions,
|
|
3285
3291
|
indices: index?.array ?? null,
|
|
@@ -3297,13 +3303,17 @@ function sceneComplexity(scene, camera) {
|
|
|
3297
3303
|
});
|
|
3298
3304
|
}
|
|
3299
3305
|
} else {
|
|
3300
|
-
objects += 1;
|
|
3306
|
+
if (!shell) objects += 1;
|
|
3301
3307
|
meshes.push({ ...base, matrix: mesh.matrixWorld.elements });
|
|
3302
3308
|
}
|
|
3303
3309
|
}
|
|
3304
3310
|
for (const child of object.children) visit(child);
|
|
3305
3311
|
};
|
|
3306
3312
|
visit(scene);
|
|
3313
|
+
for (const room of rooms) {
|
|
3314
|
+
if (room.visible && roomShownBaked(room))
|
|
3315
|
+
objects += roomPresetFactsOf(room)?.objects ?? 0;
|
|
3316
|
+
}
|
|
3307
3317
|
const eye = camera.getWorldPosition(new Vector3());
|
|
3308
3318
|
return complexityOf(meshes, [eye.x, eye.y, eye.z], objects);
|
|
3309
3319
|
}
|
|
@@ -3354,13 +3364,10 @@ async function captureShaders(root) {
|
|
|
3354
3364
|
const list = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
3355
3365
|
for (const material of list) {
|
|
3356
3366
|
if (!material || seen.has(material.uuid)) continue;
|
|
3367
|
+
if (!isNodeMaterial(material)) continue;
|
|
3368
|
+
if (fallbackFor(material, object)) continue;
|
|
3357
3369
|
seen.add(material.uuid);
|
|
3358
|
-
|
|
3359
|
-
material.userData?.bakery3?.fallback ?? readUserData(object).fallback
|
|
3360
|
-
);
|
|
3361
|
-
if (isNodeMaterial(material) && !hasFallback) {
|
|
3362
|
-
materials.push({ material, path: pathOf2(object) });
|
|
3363
|
-
}
|
|
3370
|
+
materials.push({ material, path: pathOf2(object) });
|
|
3364
3371
|
}
|
|
3365
3372
|
});
|
|
3366
3373
|
for (const { material, path } of materials) {
|
|
@@ -3674,8 +3681,10 @@ async function captureScene(options) {
|
|
|
3674
3681
|
}
|
|
3675
3682
|
function exportGLB(scene) {
|
|
3676
3683
|
const exporter = new GLTFExporter();
|
|
3684
|
+
const standIns = materialStandIns(scene);
|
|
3677
3685
|
const reattach = detachExcluded(scene);
|
|
3678
3686
|
const unmute = muteLightWarnings();
|
|
3687
|
+
const unswap = substituteMaterials(exporter, standIns);
|
|
3679
3688
|
return new Promise((resolve, reject) => {
|
|
3680
3689
|
exporter.parse(
|
|
3681
3690
|
scene,
|
|
@@ -3709,6 +3718,7 @@ function exportGLB(scene) {
|
|
|
3709
3718
|
}
|
|
3710
3719
|
);
|
|
3711
3720
|
}).finally(() => {
|
|
3721
|
+
unswap();
|
|
3712
3722
|
unmute();
|
|
3713
3723
|
reattach();
|
|
3714
3724
|
});
|
|
@@ -3925,7 +3935,7 @@ function presetRoomBake(scene, candidates, include) {
|
|
|
3925
3935
|
const group = rooms[0];
|
|
3926
3936
|
const room = roomPresetSpecOf(group);
|
|
3927
3937
|
if (!room) return null;
|
|
3928
|
-
if (!roomIsPrebaked(room.name, room.lighting)) {
|
|
3938
|
+
if (!roomShownBaked(group) && !roomIsPrebaked(room.name, room.lighting)) {
|
|
3929
3939
|
return {
|
|
3930
3940
|
refused: {
|
|
3931
3941
|
code: "BakeRoomNotPrebaked",
|
|
@@ -4009,15 +4019,31 @@ function isUnder(object, root) {
|
|
|
4009
4019
|
function planBake(scene, camera, settings = {}) {
|
|
4010
4020
|
const quality = settings.quality ?? "standard";
|
|
4011
4021
|
const textureSize = settings.textureSize ?? 1024;
|
|
4012
|
-
|
|
4022
|
+
let candidates = bakeCandidates({ scene });
|
|
4013
4023
|
let include = resolveInclude(candidates, settings);
|
|
4014
4024
|
let preset;
|
|
4015
4025
|
if (settings.room !== "full") {
|
|
4016
|
-
const
|
|
4026
|
+
const hide = revealBakedStands(scene);
|
|
4027
|
+
let seen = candidates;
|
|
4028
|
+
let seenInclude = include;
|
|
4029
|
+
if (hide.length) {
|
|
4030
|
+
try {
|
|
4031
|
+
seen = bakeCandidates({ scene });
|
|
4032
|
+
seenInclude = resolveInclude(seen, settings);
|
|
4033
|
+
} finally {
|
|
4034
|
+
for (const undo of hide) undo();
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
const verdict = presetRoomBake(scene, seen, seenInclude);
|
|
4017
4038
|
if (verdict && "ok" in verdict) {
|
|
4018
4039
|
preset = verdict.ok;
|
|
4040
|
+
candidates = seen;
|
|
4019
4041
|
const keep = /* @__PURE__ */ new Set([...preset.spanIds]);
|
|
4020
|
-
include =
|
|
4042
|
+
include = seenInclude.filter((id) => keep.has(id));
|
|
4043
|
+
if (hide.length) {
|
|
4044
|
+
for (const id of preset.standIds)
|
|
4045
|
+
if (!include.includes(id)) include.push(id);
|
|
4046
|
+
}
|
|
4021
4047
|
}
|
|
4022
4048
|
}
|
|
4023
4049
|
const standIns = resolveSimplify(scene, candidates, settings);
|
|
@@ -4202,7 +4228,8 @@ async function prepareBake(options) {
|
|
|
4202
4228
|
function holdRoomBack(preset, include) {
|
|
4203
4229
|
const undo = [];
|
|
4204
4230
|
const state = preset.group.userData?.bakery3Preset?.roomPreset;
|
|
4205
|
-
if (!state
|
|
4231
|
+
if (!state) return undo;
|
|
4232
|
+
if (!state.standIn && !roomShownBaked(preset.group)) return undo;
|
|
4206
4233
|
const shipping = new Set(
|
|
4207
4234
|
include.filter((id) => preset.standIds.includes(id))
|
|
4208
4235
|
);
|
|
@@ -4224,6 +4251,19 @@ function holdRoomBack(preset, include) {
|
|
|
4224
4251
|
});
|
|
4225
4252
|
return undo;
|
|
4226
4253
|
}
|
|
4254
|
+
function revealBakedStands(scene) {
|
|
4255
|
+
const undo = [];
|
|
4256
|
+
for (const group of findPresetRooms(scene)) {
|
|
4257
|
+
if (!roomShownBaked(group)) continue;
|
|
4258
|
+
const state = group.userData?.bakery3Preset?.roomPreset;
|
|
4259
|
+
if (!state || state.standIn) continue;
|
|
4260
|
+
state.standIn = "stand";
|
|
4261
|
+
undo.push(() => {
|
|
4262
|
+
state.standIn = void 0;
|
|
4263
|
+
});
|
|
4264
|
+
}
|
|
4265
|
+
return undo;
|
|
4266
|
+
}
|
|
4227
4267
|
function developerUv1(candidates, include) {
|
|
4228
4268
|
const wanted = new Set(include);
|
|
4229
4269
|
return candidates.filter((candidate) => {
|
|
@@ -4487,6 +4527,6 @@ function resolveInclude(candidates, settings) {
|
|
|
4487
4527
|
return resolved;
|
|
4488
4528
|
}
|
|
4489
4529
|
|
|
4490
|
-
export {
|
|
4491
|
-
//# sourceMappingURL=chunk-
|
|
4492
|
-
//# sourceMappingURL=chunk-
|
|
4530
|
+
export { Timeline, analyzeScene, aspectOf, bakeQuoteOf, bindTimelineContext, captureScene, createTimeline, extractMaterialShader, isNodeMaterial, outputSize, prepareBake, quoteBake, resolveOutput, sceneComplexity, timelineFromGsap, timelineFromTheatre, tracedTriangles };
|
|
4531
|
+
//# sourceMappingURL=chunk-WLEFNUOH.js.map
|
|
4532
|
+
//# sourceMappingURL=chunk-WLEFNUOH.js.map
|