@treasuryspatial/viewer-kit 0.2.44 → 0.2.50

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.
Files changed (69) hide show
  1. package/dist/autoGenerate.d.ts +1 -0
  2. package/dist/autoGenerate.d.ts.map +1 -1
  3. package/dist/autoGenerate.js +10 -2
  4. package/dist/camera.d.ts +1 -0
  5. package/dist/camera.d.ts.map +1 -1
  6. package/dist/camera.js +8 -1
  7. package/dist/engine/ViewerEngine.d.ts +20 -0
  8. package/dist/engine/ViewerEngine.d.ts.map +1 -1
  9. package/dist/engine/ViewerEngine.js +254 -63
  10. package/dist/engine/types.d.ts +69 -3
  11. package/dist/engine/types.d.ts.map +1 -1
  12. package/dist/exports/download.d.ts +6 -0
  13. package/dist/exports/download.d.ts.map +1 -1
  14. package/dist/exports/download.js +142 -0
  15. package/dist/exports/three-export.d.ts +4 -1
  16. package/dist/exports/three-export.d.ts.map +1 -1
  17. package/dist/exports/three-export.js +138 -4
  18. package/dist/index.d.ts +13 -9
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +5 -4
  21. package/dist/materials/architectural.d.ts +3 -3
  22. package/dist/materials/architectural.d.ts.map +1 -1
  23. package/dist/materials/architectural.js +295 -37
  24. package/dist/materials/catalogue-data.d.ts +15 -0
  25. package/dist/materials/catalogue-data.d.ts.map +1 -1
  26. package/dist/materials/catalogue-data.js +16 -0
  27. package/dist/materials/presets.d.ts +15 -8
  28. package/dist/materials/presets.d.ts.map +1 -1
  29. package/dist/materials/presets.js +140 -39
  30. package/dist/materials/resolve.d.ts +42 -0
  31. package/dist/materials/resolve.d.ts.map +1 -1
  32. package/dist/materials/resolve.js +228 -13
  33. package/dist/materials/types.d.ts +32 -3
  34. package/dist/materials/types.d.ts.map +1 -1
  35. package/dist/presets/defaults.d.ts.map +1 -1
  36. package/dist/presets/defaults.js +17 -1
  37. package/dist/presets/sciencePresets.d.ts.map +1 -1
  38. package/dist/presets/sciencePresets.js +167 -50
  39. package/dist/scene.d.ts +28 -4
  40. package/dist/scene.d.ts.map +1 -1
  41. package/dist/scene.js +196 -31
  42. package/dist/sceneSemanticRegistry.d.ts +64 -0
  43. package/dist/sceneSemanticRegistry.d.ts.map +1 -0
  44. package/dist/sceneSemanticRegistry.js +199 -0
  45. package/dist/sky/scienceSky.d.ts.map +1 -1
  46. package/dist/sky/scienceSky.js +16 -0
  47. package/dist/systems/debugSystem.d.ts +24 -1
  48. package/dist/systems/debugSystem.d.ts.map +1 -1
  49. package/dist/systems/debugSystem.js +324 -77
  50. package/dist/systems/environmentSystem.d.ts +5 -4
  51. package/dist/systems/environmentSystem.d.ts.map +1 -1
  52. package/dist/systems/environmentSystem.js +138 -62
  53. package/dist/systems/lightingSystem.d.ts +10 -1
  54. package/dist/systems/lightingSystem.d.ts.map +1 -1
  55. package/dist/systems/lightingSystem.js +118 -17
  56. package/dist/systems/postfxSystem.d.ts +5 -1
  57. package/dist/systems/postfxSystem.d.ts.map +1 -1
  58. package/dist/systems/postfxSystem.js +84 -1
  59. package/dist/systems/rendererSystem.d.ts.map +1 -1
  60. package/dist/systems/rendererSystem.js +1 -0
  61. package/dist/tsconfig.tsbuildinfo +1 -1
  62. package/dist/uploads/geometry3dm.d.ts.map +1 -1
  63. package/dist/uploads/geometry3dm.js +1 -0
  64. package/dist/uploads/grasshopper.d.ts.map +1 -1
  65. package/dist/uploads/grasshopper.js +63 -5
  66. package/dist/uploads/mesh.js +5 -5
  67. package/dist/uploads/types.d.ts +4 -0
  68. package/dist/uploads/types.d.ts.map +1 -1
  69. package/package.json +3 -3
@@ -2,15 +2,22 @@ import * as THREE from "three";
2
2
  const DEFAULT_EXTRAS = {
3
3
  grid: true,
4
4
  ground: true,
5
- axes: true,
6
- origin: true,
7
- gridOpacity: 0.12,
8
- gridDivisions: 100,
9
- gridSize: 100,
5
+ groundMode: "infinite",
6
+ gridMode: "infinite",
7
+ axes: false,
8
+ shadowHelpers: false,
9
+ origin: false,
10
+ gridUnit: 1,
11
+ gridMajorEvery: 5,
12
+ gridSuperMajorEvery: 10,
13
+ gridOpacity: 0.055,
14
+ gridMajorOpacity: 0.12,
15
+ gridSuperMajorOpacity: 0.2,
16
+ gridSize: 120,
10
17
  groundRoughness: 0.8,
11
18
  groundMetalness: 0.05,
12
19
  lightTarget: [0, 1.5, 0],
13
- originHighlight: true,
20
+ originHighlight: false,
14
21
  originLineColor: 0x94a3b8,
15
22
  originLineLength: 40,
16
23
  originLineThickness: 0.06,
@@ -21,14 +28,27 @@ const DEFAULT_EXTRAS = {
21
28
  offset: 0.4,
22
29
  secondaryOffset: 0.5,
23
30
  },
31
+ outline: false,
32
+ outlineColor: 0x1f2937,
33
+ outlineOpacity: 0.38,
34
+ outlineThresholdAngle: 35,
35
+ outlineDepthTest: true,
24
36
  };
25
37
  const DEFAULT_GRID_SIZE = 100;
26
- const DEFAULT_GRID_DIVISIONS = 100;
27
- const DEFAULT_GRID_OPACITY = 0.12;
28
- const DEFAULT_GRID_HEIGHT_OFFSET = 0.02;
29
- const DEFAULT_GROUND_OFFSET = -0.11;
30
- const HDR_GROUND_SIZE = 30;
31
- const HDR_GRID_SIZE = 30;
38
+ const DEFAULT_GRID_OPACITY = 0.055;
39
+ const DEFAULT_GRID_MAJOR_OPACITY = 0.12;
40
+ const DEFAULT_GRID_SUPER_MAJOR_OPACITY = 0.2;
41
+ const DEFAULT_GRID_UNIT = 1;
42
+ const DEFAULT_GRID_MAJOR_EVERY = 5;
43
+ const DEFAULT_GRID_SUPER_MAJOR_EVERY = 10;
44
+ const MAX_METRIC_GRID_SIZE = 2000;
45
+ const DEFAULT_GRID_HEIGHT_OFFSET = 0.05;
46
+ const DEFAULT_GROUND_OFFSET = -0.08;
47
+ const AO_GROUND_PROXY_CLEARANCE = 0.001;
48
+ const MIN_GRID_GROUND_CLEARANCE = 0.05;
49
+ const MIN_GRID_FLOOR_CLEARANCE = 0.05;
50
+ const INFINITE_GROUND_SIZE = 20000;
51
+ export const AO_DEPTH_PROXY_USER_DATA_KEY = "treasuryAoDepthProxy";
32
52
  const AXIS_COLORS = {
33
53
  x: 0xef4444,
34
54
  y: 0x22c55e,
@@ -176,80 +196,270 @@ function adjustGridColor(groundHex) {
176
196
  adjusted.setHSL(hsl.h, hsl.s, hsl.l);
177
197
  return adjusted.getHex();
178
198
  }
199
+ const clampOpacity = (value) => Math.max(0, Math.min(1, value));
200
+ function buildGridLineSegments(positions, color, opacity) {
201
+ if (positions.length === 0)
202
+ return null;
203
+ const geometry = new THREE.BufferGeometry();
204
+ geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
205
+ const material = new THREE.LineBasicMaterial({
206
+ color,
207
+ transparent: true,
208
+ opacity: clampOpacity(opacity),
209
+ depthTest: true,
210
+ depthWrite: false,
211
+ toneMapped: false,
212
+ });
213
+ const lines = new THREE.LineSegments(geometry, material);
214
+ lines.frustumCulled = false;
215
+ lines.renderOrder = -10;
216
+ return lines;
217
+ }
218
+ function buildMetricGrid(extras, groundColor, requestedSize) {
219
+ const step = Math.max(0.001, extras.gridUnit ?? DEFAULT_GRID_UNIT);
220
+ const majorEvery = Math.max(1, Math.round(extras.gridMajorEvery ?? DEFAULT_GRID_MAJOR_EVERY));
221
+ const superMajorEvery = Math.max(majorEvery, Math.round(extras.gridSuperMajorEvery ?? DEFAULT_GRID_SUPER_MAJOR_EVERY));
222
+ const halfLines = Math.max(1, Math.ceil(Math.min(requestedSize, MAX_METRIC_GRID_SIZE) / (2 * step)));
223
+ const extent = halfLines * step;
224
+ const size = extent * 2;
225
+ const divisions = halfLines * 2;
226
+ const minorColor = extras.gridColorSecondary ?? adjustGridColor(groundColor);
227
+ const majorColor = extras.gridMajorColor ?? extras.gridColor ?? adjustGridColor(groundColor);
228
+ const superMajorColor = extras.gridSuperMajorColor ?? extras.gridColor ?? majorColor;
229
+ const minorOpacity = extras.gridOpacity ?? DEFAULT_GRID_OPACITY;
230
+ const majorOpacity = extras.gridMajorOpacity ?? Math.max(DEFAULT_GRID_MAJOR_OPACITY, minorOpacity * 2.1);
231
+ const superMajorOpacity = extras.gridSuperMajorOpacity ?? Math.max(DEFAULT_GRID_SUPER_MAJOR_OPACITY, majorOpacity * 1.55);
232
+ const minorPositions = [];
233
+ const majorPositions = [];
234
+ const superMajorPositions = [];
235
+ const appendLinePair = (target, coordinate) => {
236
+ target.push(-extent, 0, coordinate, extent, 0, coordinate);
237
+ target.push(coordinate, 0, -extent, coordinate, 0, extent);
238
+ };
239
+ for (let i = -halfLines; i <= halfLines; i += 1) {
240
+ const coordinate = i * step;
241
+ const absIndex = Math.abs(i);
242
+ if (superMajorEvery > 0 && absIndex % superMajorEvery === 0) {
243
+ appendLinePair(superMajorPositions, coordinate);
244
+ }
245
+ else if (majorEvery > 0 && absIndex % majorEvery === 0) {
246
+ appendLinePair(majorPositions, coordinate);
247
+ }
248
+ else {
249
+ appendLinePair(minorPositions, coordinate);
250
+ }
251
+ }
252
+ const group = new THREE.Group();
253
+ group.name = "metric-grid";
254
+ const minor = buildGridLineSegments(minorPositions, minorColor, minorOpacity);
255
+ const major = buildGridLineSegments(majorPositions, majorColor, majorOpacity);
256
+ const superMajor = buildGridLineSegments(superMajorPositions, superMajorColor, superMajorOpacity);
257
+ if (minor)
258
+ group.add(minor);
259
+ if (major)
260
+ group.add(major);
261
+ if (superMajor)
262
+ group.add(superMajor);
263
+ group.renderOrder = -10;
264
+ return { object: group, size, step, divisions, majorEvery, superMajorEvery };
265
+ }
266
+ function hasOwnSceneExtra(preset, key) {
267
+ return Object.prototype.hasOwnProperty.call(preset.sceneExtras ?? {}, key);
268
+ }
269
+ function buildOutlineGroup(root, extras) {
270
+ if (!root || extras.outline !== true)
271
+ return null;
272
+ const group = new THREE.Group();
273
+ const thresholdAngle = extras.outlineThresholdAngle ?? 35;
274
+ const baseMaterial = new THREE.LineBasicMaterial({
275
+ color: extras.outlineColor ?? 0x1f2937,
276
+ transparent: true,
277
+ opacity: extras.outlineOpacity ?? 0.38,
278
+ depthTest: extras.outlineDepthTest !== false,
279
+ depthWrite: false,
280
+ toneMapped: false,
281
+ });
282
+ root.updateMatrixWorld(true);
283
+ root.traverse((object) => {
284
+ const mesh = object;
285
+ if (!mesh.isMesh || !mesh.geometry)
286
+ return;
287
+ const geometry = mesh.geometry;
288
+ const edges = new THREE.EdgesGeometry(geometry, thresholdAngle);
289
+ const line = new THREE.LineSegments(edges, baseMaterial.clone());
290
+ line.matrix.copy(mesh.matrixWorld);
291
+ line.matrixAutoUpdate = false;
292
+ line.renderOrder = 20;
293
+ line.frustumCulled = false;
294
+ group.add(line);
295
+ });
296
+ baseMaterial.dispose();
297
+ return group.children.length > 0 ? group : null;
298
+ }
179
299
  export class DebugSystem {
180
300
  scene;
181
301
  objects = [];
302
+ ground = null;
303
+ groundAoProxy = null;
304
+ grid = null;
305
+ groundInfinite = false;
306
+ gridInfinite = false;
307
+ gridDivisionSize = 1;
308
+ state = {
309
+ groundEnabled: false,
310
+ gridEnabled: false,
311
+ groundY: null,
312
+ gridY: null,
313
+ gridSize: null,
314
+ gridDivisions: null,
315
+ gridStep: null,
316
+ gridMajorEvery: null,
317
+ gridSuperMajorEvery: null,
318
+ groundMode: null,
319
+ gridMode: null,
320
+ };
182
321
  constructor(scene) {
183
322
  this.scene = scene;
184
323
  }
185
- apply(preset, bounds) {
324
+ update(anchor) {
325
+ if (!anchor)
326
+ return;
327
+ if (this.groundInfinite && this.ground) {
328
+ this.ground.position.x = anchor.x;
329
+ this.ground.position.z = anchor.z;
330
+ }
331
+ if (this.groundInfinite && this.groundAoProxy) {
332
+ this.groundAoProxy.position.x = anchor.x;
333
+ this.groundAoProxy.position.z = anchor.z;
334
+ }
335
+ if (this.gridInfinite && this.grid) {
336
+ const snap = Number.isFinite(this.gridDivisionSize) && this.gridDivisionSize > 0 ? this.gridDivisionSize : 1;
337
+ this.grid.position.x = Math.round(anchor.x / snap) * snap;
338
+ this.grid.position.z = Math.round(anchor.z / snap) * snap;
339
+ }
340
+ }
341
+ getState() {
342
+ return { ...this.state };
343
+ }
344
+ apply(preset, bounds, root) {
186
345
  const extras = { ...DEFAULT_EXTRAS, ...(preset.sceneExtras ?? {}) };
187
346
  this.clear();
188
- const skyMode = preset.sky?.mode ?? "gradient";
189
- const isHdr = skyMode === "hdr";
190
347
  const groundEnabled = extras.ground !== false;
191
348
  const gridEnabled = extras.grid !== false;
192
349
  const axesEnabled = extras.axes !== false;
350
+ const shadowHelpersEnabled = extras.shadowHelpers === true;
193
351
  const originEnabled = extras.origin !== false;
194
352
  const groundColor = extras.groundColor ?? 0x2c2f33;
195
- const boundsSize = bounds && !bounds.isEmpty() ? bounds.getSize(new THREE.Vector3()) : null;
353
+ const hasBounds = Boolean(bounds && !bounds.isEmpty());
354
+ const boundsSize = hasBounds ? bounds.getSize(new THREE.Vector3()) : null;
355
+ const boundsMinY = hasBounds && Number.isFinite(bounds.min.y) ? bounds.min.y : 0;
196
356
  const modelSpan = boundsSize ? Math.max(boundsSize.x, boundsSize.z, 1) : null;
197
- const groundScale = isHdr ? (extras.groundAutoScaleHdr ?? 1.25) : (extras.groundAutoScale ?? 2.5);
198
- const gridScale = isHdr
199
- ? (extras.gridAutoScaleHdr ?? extras.groundAutoScaleHdr ?? 1.25)
200
- : (extras.gridAutoScale ?? extras.groundAutoScale ?? 2.5);
201
- const groundSizeDefault = isHdr ? HDR_GROUND_SIZE : DEFAULT_GRID_SIZE;
202
- const gridSizeDefault = isHdr ? HDR_GRID_SIZE : DEFAULT_GRID_SIZE;
203
- const derivedGroundSize = modelSpan ? modelSpan * groundScale : groundSizeDefault;
357
+ // Ground/grid sizing is independent of sky mode. The metric grid uses real-world step
358
+ // size (gridUnit) so HDR-vs-non-HDR proportional scaling no longer adds value, and ground
359
+ // is forced to INFINITE_GROUND_SIZE in infinite mode regardless. Authors who genuinely
360
+ // want a different look under HDR can express it through gridUnit/gridMajorEvery directly.
361
+ const groundScale = extras.groundAutoScale ?? 2.5;
362
+ const gridScale = extras.gridAutoScale ?? extras.groundAutoScale ?? 2.5;
363
+ const derivedGroundSize = modelSpan ? modelSpan * groundScale : DEFAULT_GRID_SIZE;
204
364
  const derivedGridSize = groundEnabled
205
365
  ? (extras.groundSize ?? derivedGroundSize)
206
366
  : modelSpan
207
367
  ? modelSpan * gridScale
208
- : gridSizeDefault;
209
- const groundOffset = extras.groundOffset ?? DEFAULT_GROUND_OFFSET;
210
- const gridHeightOffset = extras.gridHeightOffset ?? DEFAULT_GRID_HEIGHT_OFFSET;
368
+ : DEFAULT_GRID_SIZE;
369
+ const groundOffsetAuthored = hasOwnSceneExtra(preset, "groundOffset");
370
+ const groundOffset = groundOffsetAuthored ? (extras.groundOffset ?? DEFAULT_GROUND_OFFSET) : boundsMinY + DEFAULT_GROUND_OFFSET;
371
+ const defaultGroundOffset = boundsMinY + DEFAULT_GROUND_OFFSET;
372
+ const useContactAoProxy = hasBounds &&
373
+ Number.isFinite(boundsMinY) &&
374
+ Math.abs(groundOffset - defaultGroundOffset) <= 1e-6;
375
+ const groundAoProxyY = useContactAoProxy ? boundsMinY - AO_GROUND_PROXY_CLEARANCE : groundOffset;
376
+ const rawGridHeightOffset = extras.gridHeightOffset ?? DEFAULT_GRID_HEIGHT_OFFSET;
377
+ const gridHeightOffsetFromGround = groundEnabled
378
+ ? Math.max(rawGridHeightOffset, MIN_GRID_GROUND_CLEARANCE)
379
+ : rawGridHeightOffset;
380
+ const gridFloorOffset = Math.max(rawGridHeightOffset, MIN_GRID_FLOOR_CLEARANCE);
381
+ const groundMode = extras.groundMode ?? "infinite";
382
+ const gridMode = extras.gridMode ?? groundMode;
383
+ this.groundInfinite = groundMode === "infinite";
384
+ this.gridInfinite = gridMode === "infinite";
211
385
  if (groundEnabled) {
212
- const size = extras.groundSize ?? derivedGroundSize;
386
+ const size = groundMode === "infinite"
387
+ ? Math.max(extras.groundSize ?? derivedGroundSize, INFINITE_GROUND_SIZE)
388
+ : extras.groundSize ?? derivedGroundSize;
213
389
  const groundGeometry = new THREE.PlaneGeometry(size, size);
214
390
  const groundMaterial = new THREE.MeshStandardMaterial({
215
391
  color: groundColor,
216
- roughness: extras.groundRoughness ?? (isHdr ? 0.6 : 0.8),
217
- metalness: extras.groundMetalness ?? (isHdr ? 0.02 : 0.05),
392
+ roughness: extras.groundRoughness ?? 0.8,
393
+ metalness: extras.groundMetalness ?? 0.05,
218
394
  toneMapped: false,
219
395
  });
220
- groundMaterial.polygonOffset = true;
221
- groundMaterial.polygonOffsetFactor = 1;
222
- groundMaterial.polygonOffsetUnits = 1;
396
+ // Ground draws first (renderOrder=-20) and must never z-fight with the model floor or grid.
397
+ // polygonOffset is view-angle-dependent (slope→0 at top-down), so the visible plane stays
398
+ // depthless and relies on render order. AO gets a separate invisible depth proxy instead.
399
+ groundMaterial.depthWrite = false;
223
400
  const ground = new THREE.Mesh(groundGeometry, groundMaterial);
224
401
  ground.rotation.x = -Math.PI / 2;
225
402
  ground.position.y = groundOffset;
226
403
  ground.receiveShadow = true;
404
+ ground.renderOrder = -20;
405
+ this.ground = ground;
227
406
  this.add(ground);
407
+ const groundAoProxyMaterial = new THREE.MeshBasicMaterial({
408
+ color: 0xffffff,
409
+ toneMapped: false,
410
+ });
411
+ groundAoProxyMaterial.colorWrite = false;
412
+ const groundAoProxy = new THREE.Mesh(groundGeometry.clone(), groundAoProxyMaterial);
413
+ groundAoProxy.rotation.x = -Math.PI / 2;
414
+ groundAoProxy.position.y = groundAoProxyY;
415
+ groundAoProxy.renderOrder = -19;
416
+ groundAoProxy.visible = false;
417
+ groundAoProxy.userData[AO_DEPTH_PROXY_USER_DATA_KEY] = true;
418
+ this.groundAoProxy = groundAoProxy;
419
+ this.add(groundAoProxy);
228
420
  }
229
421
  let lastGridPositionY = 0;
230
- const gridSize = extras.gridSize ?? derivedGridSize;
422
+ const gridSize = Math.max(1, extras.gridSize ?? derivedGridSize);
423
+ let gridDivisionsResolved = null;
424
+ let gridStepResolved = null;
425
+ let gridMajorEveryResolved = null;
426
+ let gridSuperMajorEveryResolved = null;
427
+ let gridSizeResolved = null;
231
428
  if (gridEnabled) {
232
- const gridPrimary = new THREE.Color(extras.gridColor ?? adjustGridColor(groundColor));
233
- const gridSecondary = new THREE.Color(extras.gridColorSecondary ?? gridPrimary.getHex());
234
- const gridDivisions = extras.gridDivisions ?? Math.max(1, gridSize);
235
- const grid = new THREE.GridHelper(gridSize, gridDivisions, gridPrimary, gridSecondary);
236
- const gridY = groundEnabled ? groundOffset + gridHeightOffset : -gridHeightOffset;
429
+ const requestedGridSize = gridMode === "infinite"
430
+ ? Math.max(gridSize, DEFAULT_GRID_SIZE)
431
+ : gridSize;
432
+ const metricGrid = buildMetricGrid(extras, groundColor, requestedGridSize);
433
+ gridDivisionsResolved = metricGrid.divisions;
434
+ gridStepResolved = metricGrid.step;
435
+ gridMajorEveryResolved = metricGrid.majorEvery;
436
+ gridSuperMajorEveryResolved = metricGrid.superMajorEvery;
437
+ gridSizeResolved = metricGrid.size;
438
+ this.gridDivisionSize = metricGrid.step;
439
+ const grid = metricGrid.object;
440
+ const gridPlane = extras.gridPlane ?? (groundEnabled ? "ground" : "floor");
441
+ const gridY = gridPlane === "ground" && groundEnabled
442
+ ? groundOffset + gridHeightOffsetFromGround
443
+ : boundsMinY + gridFloorOffset;
237
444
  grid.position.y = gridY;
238
445
  lastGridPositionY = grid.position.y;
239
- const gridMaterial = grid.material;
240
- const setTransparency = (mat) => {
241
- mat.transparent = true;
242
- mat.opacity = extras.gridOpacity ?? DEFAULT_GRID_OPACITY;
243
- };
244
- if (Array.isArray(gridMaterial)) {
245
- gridMaterial.forEach((mat) => setTransparency(mat));
246
- }
247
- else if (gridMaterial) {
248
- setTransparency(gridMaterial);
249
- }
446
+ this.grid = grid;
250
447
  this.add(grid);
251
448
  }
252
- const originPlaneY = groundEnabled ? groundOffset : lastGridPositionY || -gridHeightOffset;
449
+ this.state = {
450
+ groundEnabled,
451
+ gridEnabled,
452
+ groundY: groundEnabled ? groundOffset : null,
453
+ gridY: gridEnabled ? lastGridPositionY : null,
454
+ gridSize: gridEnabled ? gridSizeResolved : null,
455
+ gridDivisions: gridDivisionsResolved,
456
+ gridStep: gridStepResolved,
457
+ gridMajorEvery: gridMajorEveryResolved,
458
+ gridSuperMajorEvery: gridSuperMajorEveryResolved,
459
+ groundMode,
460
+ gridMode,
461
+ };
462
+ const originPlaneY = gridEnabled ? lastGridPositionY : groundEnabled ? groundOffset : boundsMinY + gridFloorOffset;
253
463
  if (extras.originHighlight !== false) {
254
464
  const originCross = buildOriginCross(extras, gridSize, originPlaneY);
255
465
  this.add(originCross);
@@ -275,6 +485,22 @@ export class DebugSystem {
275
485
  this.add(axes);
276
486
  }
277
487
  }
488
+ if (shadowHelpersEnabled) {
489
+ this.scene.traverse((child) => {
490
+ if (!(child instanceof THREE.DirectionalLight) || !child.castShadow)
491
+ return;
492
+ const lightHelper = new THREE.DirectionalLightHelper(child, 3);
493
+ lightHelper.update();
494
+ this.add(lightHelper);
495
+ if (child.shadow?.camera) {
496
+ this.add(new THREE.CameraHelper(child.shadow.camera));
497
+ }
498
+ });
499
+ }
500
+ const outline = buildOutlineGroup(root, extras);
501
+ if (outline) {
502
+ this.add(outline);
503
+ }
278
504
  }
279
505
  dispose() {
280
506
  this.clear();
@@ -284,40 +510,61 @@ export class DebugSystem {
284
510
  this.objects.push(object);
285
511
  }
286
512
  clear() {
513
+ this.ground = null;
514
+ this.groundAoProxy = null;
515
+ this.grid = null;
516
+ this.groundInfinite = false;
517
+ this.gridInfinite = false;
518
+ this.gridDivisionSize = 1;
519
+ this.state = {
520
+ groundEnabled: false,
521
+ gridEnabled: false,
522
+ groundY: null,
523
+ gridY: null,
524
+ gridSize: null,
525
+ gridDivisions: null,
526
+ gridStep: null,
527
+ gridMajorEvery: null,
528
+ gridSuperMajorEvery: null,
529
+ groundMode: null,
530
+ gridMode: null,
531
+ };
287
532
  this.objects.forEach((object) => {
288
533
  if (object.parent)
289
534
  object.parent.remove(object);
290
- if (object instanceof THREE.Mesh) {
291
- object.geometry.dispose();
292
- const material = object.material;
293
- if (Array.isArray(material)) {
294
- material.forEach((mat) => mat.dispose?.());
295
- }
296
- else {
297
- material.dispose?.();
298
- }
299
- return;
300
- }
301
- if (object instanceof THREE.Line) {
302
- object.geometry.dispose();
303
- const material = object.material;
304
- if (Array.isArray(material)) {
305
- material.forEach((mat) => mat.dispose?.());
535
+ object.traverse((child) => {
536
+ if (child instanceof THREE.Mesh) {
537
+ child.geometry.dispose();
538
+ const material = child.material;
539
+ if (Array.isArray(material)) {
540
+ material.forEach((mat) => mat.dispose?.());
541
+ }
542
+ else {
543
+ material.dispose?.();
544
+ }
545
+ return;
306
546
  }
307
- else {
308
- material?.dispose?.();
547
+ if (child instanceof THREE.Line) {
548
+ child.geometry.dispose();
549
+ const material = child.material;
550
+ if (Array.isArray(material)) {
551
+ material.forEach((mat) => mat.dispose?.());
552
+ }
553
+ else {
554
+ material?.dispose?.();
555
+ }
556
+ return;
309
557
  }
310
- return;
311
- }
312
- if (object instanceof THREE.Sprite) {
313
- const material = object.material;
314
- if (material) {
315
- if (material.map) {
316
- material.map.dispose?.();
558
+ if (child instanceof THREE.Sprite) {
559
+ const material = child.material;
560
+ if (material) {
561
+ if (material.map) {
562
+ material.map.dispose?.();
563
+ }
564
+ material.dispose?.();
317
565
  }
318
- material.dispose?.();
319
566
  }
320
- }
567
+ });
321
568
  });
322
569
  this.objects = [];
323
570
  }
@@ -1,7 +1,7 @@
1
1
  import * as THREE from "three";
2
2
  import type { AssetResolver, RenderPresetDefinition } from "../engine/types";
3
3
  export type EnvironmentState = {
4
- mode: "none" | "gradient" | "hdr" | "cube";
4
+ mode: "none" | "gradient" | "image" | "hdr" | "cube";
5
5
  backgroundEnabled: boolean;
6
6
  lightingEnabled: boolean;
7
7
  };
@@ -13,21 +13,22 @@ export declare class EnvironmentSystem {
13
13
  private currentObjects;
14
14
  private currentBackground;
15
15
  private currentEnvironment;
16
- private gradientSky;
17
- private readonly gradientBaseRadius;
18
16
  private objectUrls;
19
17
  private loadToken;
18
+ private appliedSkySignature;
20
19
  private state;
21
20
  private fallbackGradient;
22
21
  constructor(scene: THREE.Scene, renderer: THREE.WebGLRenderer, assetResolver?: AssetResolver);
23
22
  getState(): EnvironmentState;
24
- update(camera?: THREE.Camera): void;
23
+ update(_camera?: THREE.Camera): void;
25
24
  apply(preset: RenderPresetDefinition): Promise<void>;
26
25
  dispose(): void;
26
+ private static skySignature;
27
27
  private disposeCurrent;
28
28
  private applyGradientSky;
29
29
  private resolveAsset;
30
30
  private applyHdrSky;
31
+ private applyImageSky;
31
32
  private applyCubeSky;
32
33
  private applyRotationToScene;
33
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"environmentSystem.d.ts","sourceRoot":"","sources":["../../src/systems/environmentSystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAA8C,MAAM,iBAAiB,CAAC;AAEzH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3C,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,cAAc,CAAqC;IAE3D,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,iBAAiB,CAAkD;IAC3E,OAAO,CAAC,kBAAkB,CAAkD;IAC5E,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IAC1C,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,SAAS,CAAK;IAEtB,OAAO,CAAC,KAAK,CAAwF;IACrG,OAAO,CAAC,gBAAgB,CAMtB;gBAEU,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,EAAE,aAAa;IAM5F,QAAQ,IAAI,gBAAgB;IAI5B,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI;IAa7B,KAAK,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC1D,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,cAAc;IAsCtB,OAAO,CAAC,gBAAgB;YA+CV,YAAY;YAaZ,WAAW;YAwDX,YAAY;IAuD1B,OAAO,CAAC,oBAAoB;CAY7B"}
1
+ {"version":3,"file":"environmentSystem.d.ts","sourceRoot":"","sources":["../../src/systems/environmentSystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAa,aAAa,EAAE,sBAAsB,EAA8D,MAAM,iBAAiB,CAAC;AAEpJ,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACrD,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,cAAc,CAAqC;IAE3D,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,iBAAiB,CAAkD;IAC3E,OAAO,CAAC,kBAAkB,CAAkD;IAC5E,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,mBAAmB,CAAuB;IAElD,OAAO,CAAC,KAAK,CAAwF;IACrG,OAAO,CAAC,gBAAgB,CAMtB;gBAEU,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,EAAE,aAAa;IAM5F,QAAQ,IAAI,gBAAgB;IAI5B,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI;IAE9B,KAAK,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2D1D,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,MAAM,CAAC,YAAY;IAS3B,OAAO,CAAC,cAAc;IAoCtB,OAAO,CAAC,gBAAgB;YA8CV,YAAY;YAaZ,WAAW;YA0DX,aAAa;YAoEb,YAAY;IAyD1B,OAAO,CAAC,oBAAoB;CAY7B"}