@pascal-app/viewer 1.0.0-beta.5 → 1.0.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.
Files changed (190) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/dist/capture/asset-url.d.ts +2 -0
  4. package/dist/capture/asset-url.d.ts.map +1 -0
  5. package/dist/capture/asset-url.js +13 -0
  6. package/dist/capture/capture-runtime.d.ts +43 -0
  7. package/dist/capture/capture-runtime.d.ts.map +1 -0
  8. package/dist/capture/capture-runtime.js +228 -0
  9. package/dist/capture/frame.d.ts +4 -0
  10. package/dist/capture/frame.d.ts.map +1 -0
  11. package/dist/capture/frame.js +21 -0
  12. package/dist/capture/index.d.ts +12 -0
  13. package/dist/capture/index.d.ts.map +1 -0
  14. package/dist/capture/index.js +11 -0
  15. package/dist/capture/layer-visibility.d.ts +5 -0
  16. package/dist/capture/layer-visibility.d.ts.map +1 -0
  17. package/dist/capture/layer-visibility.js +11 -0
  18. package/dist/capture/layers/clay-matcap.d.ts +3 -0
  19. package/dist/capture/layers/clay-matcap.d.ts.map +1 -0
  20. package/dist/capture/layers/clay-matcap.js +26 -0
  21. package/dist/capture/layers/device-motion-layer.d.ts +7 -0
  22. package/dist/capture/layers/device-motion-layer.d.ts.map +1 -0
  23. package/dist/capture/layers/device-motion-layer.js +78 -0
  24. package/dist/capture/layers/point-cloud-layer.d.ts +15 -0
  25. package/dist/capture/layers/point-cloud-layer.d.ts.map +1 -0
  26. package/dist/capture/layers/point-cloud-layer.js +106 -0
  27. package/dist/capture/layers/room-model-layer.d.ts +9 -0
  28. package/dist/capture/layers/room-model-layer.d.ts.map +1 -0
  29. package/dist/capture/layers/room-model-layer.js +71 -0
  30. package/dist/capture/layers/surface-mesh-data.d.ts +9 -0
  31. package/dist/capture/layers/surface-mesh-data.d.ts.map +1 -0
  32. package/dist/capture/layers/surface-mesh-data.js +74 -0
  33. package/dist/capture/layers/surface-mesh-layer.d.ts +7 -0
  34. package/dist/capture/layers/surface-mesh-layer.d.ts.map +1 -0
  35. package/dist/capture/layers/surface-mesh-layer.js +16 -0
  36. package/dist/capture/preview.d.ts +3 -0
  37. package/dist/capture/preview.d.ts.map +1 -0
  38. package/dist/capture/preview.js +2 -0
  39. package/dist/capture/source-state.d.ts +22 -0
  40. package/dist/capture/source-state.d.ts.map +1 -0
  41. package/dist/capture/source-state.js +182 -0
  42. package/dist/capture/stream-rendering.d.ts +14 -0
  43. package/dist/capture/stream-rendering.d.ts.map +1 -0
  44. package/dist/capture/stream-rendering.js +69 -0
  45. package/dist/capture/trajectory.d.ts +20 -0
  46. package/dist/capture/trajectory.d.ts.map +1 -0
  47. package/dist/capture/trajectory.js +77 -0
  48. package/dist/components/viewer/batched-mesh-spike.d.ts +14 -0
  49. package/dist/components/viewer/batched-mesh-spike.d.ts.map +1 -0
  50. package/dist/components/viewer/batched-mesh-spike.js +64 -0
  51. package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
  52. package/dist/components/viewer/frame-limiter.js +4 -3
  53. package/dist/components/viewer/index.d.ts.map +1 -1
  54. package/dist/components/viewer/index.js +70 -62
  55. package/dist/components/viewer/lights.d.ts.map +1 -1
  56. package/dist/components/viewer/lights.js +123 -89
  57. package/dist/components/viewer/perf-monitor.d.ts +6 -1
  58. package/dist/components/viewer/perf-monitor.d.ts.map +1 -1
  59. package/dist/components/viewer/perf-monitor.js +307 -116
  60. package/dist/components/viewer/perf-panel.d.ts +3 -0
  61. package/dist/components/viewer/perf-panel.d.ts.map +1 -0
  62. package/dist/components/viewer/perf-panel.js +178 -0
  63. package/dist/components/viewer/pointer-raycast-layers.d.ts +15 -0
  64. package/dist/components/viewer/pointer-raycast-layers.d.ts.map +1 -0
  65. package/dist/components/viewer/pointer-raycast-layers.js +28 -0
  66. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  67. package/dist/components/viewer/post-processing.js +124 -83
  68. package/dist/components/viewer/registered-systems.d.ts +14 -5
  69. package/dist/components/viewer/registered-systems.d.ts.map +1 -1
  70. package/dist/components/viewer/registered-systems.js +22 -10
  71. package/dist/components/viewer/scene-atmosphere.d.ts +30 -0
  72. package/dist/components/viewer/scene-atmosphere.d.ts.map +1 -0
  73. package/dist/components/viewer/scene-atmosphere.js +89 -0
  74. package/dist/components/viewer/scene-environment.d.ts.map +1 -1
  75. package/dist/components/viewer/scene-environment.js +19 -5
  76. package/dist/components/viewer/scene-ground-replacement.d.ts +5 -0
  77. package/dist/components/viewer/scene-ground-replacement.d.ts.map +1 -0
  78. package/dist/components/viewer/scene-ground-replacement.js +35 -0
  79. package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
  80. package/dist/components/viewer/viewer-camera.js +4 -1
  81. package/dist/components/viewer/viewer-presentations.d.ts +67 -0
  82. package/dist/components/viewer/viewer-presentations.d.ts.map +1 -0
  83. package/dist/components/viewer/viewer-presentations.js +120 -0
  84. package/dist/hooks/use-library-materials-version.d.ts +7 -0
  85. package/dist/hooks/use-library-materials-version.d.ts.map +1 -0
  86. package/dist/hooks/use-library-materials-version.js +10 -0
  87. package/dist/hooks/use-node-events.d.ts.map +1 -1
  88. package/dist/hooks/use-node-events.js +1 -0
  89. package/dist/index.d.ts +15 -6
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +15 -6
  92. package/dist/lib/csg-utils.d.ts +1 -0
  93. package/dist/lib/csg-utils.d.ts.map +1 -1
  94. package/dist/lib/csg-utils.js +6 -1
  95. package/dist/lib/gpu-perf.d.ts +0 -2
  96. package/dist/lib/gpu-perf.d.ts.map +1 -1
  97. package/dist/lib/gpu-perf.js +7 -21
  98. package/dist/lib/layer-pass.d.ts +28 -0
  99. package/dist/lib/layer-pass.d.ts.map +1 -0
  100. package/dist/lib/layer-pass.js +254 -0
  101. package/dist/lib/materials.d.ts +12 -0
  102. package/dist/lib/materials.d.ts.map +1 -1
  103. package/dist/lib/materials.js +51 -17
  104. package/dist/lib/merged-outline-node.d.ts +17 -8
  105. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  106. package/dist/lib/merged-outline-node.js +194 -52
  107. package/dist/lib/perf-actions.d.ts +55 -0
  108. package/dist/lib/perf-actions.d.ts.map +1 -0
  109. package/dist/lib/perf-actions.js +211 -0
  110. package/dist/lib/perf-observers.d.ts +2 -0
  111. package/dist/lib/perf-observers.d.ts.map +1 -0
  112. package/dist/lib/perf-observers.js +17 -0
  113. package/dist/lib/perf-panel-store.d.ts +71 -0
  114. package/dist/lib/perf-panel-store.d.ts.map +1 -0
  115. package/dist/lib/perf-panel-store.js +29 -0
  116. package/dist/lib/perf-tracks.d.ts +43 -0
  117. package/dist/lib/perf-tracks.d.ts.map +1 -0
  118. package/dist/lib/perf-tracks.js +113 -0
  119. package/dist/lib/pointer-events.d.ts +7 -0
  120. package/dist/lib/pointer-events.d.ts.map +1 -0
  121. package/dist/lib/pointer-events.js +680 -0
  122. package/dist/lib/post-processing-resources.d.ts +12 -0
  123. package/dist/lib/post-processing-resources.d.ts.map +1 -0
  124. package/dist/lib/post-processing-resources.js +19 -0
  125. package/dist/lib/renderer-capability.d.ts.map +1 -1
  126. package/dist/lib/renderer-capability.js +4 -2
  127. package/dist/lib/scene-visibility.d.ts +2 -1
  128. package/dist/lib/scene-visibility.d.ts.map +1 -1
  129. package/dist/lib/scene-visibility.js +22 -1
  130. package/dist/store/use-viewer.d.ts +2 -2
  131. package/dist/store/use-viewer.d.ts.map +1 -1
  132. package/dist/systems/ceiling/ceiling-system.js +1 -1
  133. package/dist/systems/door/door-animation-system.d.ts.map +1 -1
  134. package/dist/systems/door/door-animation-system.js +6 -9
  135. package/dist/systems/door/door-system.d.ts.map +1 -1
  136. package/dist/systems/door/door-system.js +13 -2
  137. package/dist/systems/geometry/geometry-system.d.ts.map +1 -1
  138. package/dist/systems/geometry/geometry-system.js +3 -2
  139. package/dist/systems/level/level-system.d.ts.map +1 -1
  140. package/dist/systems/level/level-system.js +1 -1
  141. package/dist/systems/level/level-utils.d.ts +9 -0
  142. package/dist/systems/level/level-utils.d.ts.map +1 -1
  143. package/dist/systems/level/level-utils.js +14 -0
  144. package/dist/systems/perf-action-settle/perf-action-settle-system.d.ts +8 -0
  145. package/dist/systems/perf-action-settle/perf-action-settle-system.d.ts.map +1 -0
  146. package/dist/systems/perf-action-settle/perf-action-settle-system.js +32 -0
  147. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  148. package/dist/systems/roof/roof-system.js +1196 -58
  149. package/dist/systems/scan/scan-system.js +6 -5
  150. package/dist/systems/slab/slab-system.d.ts.map +1 -1
  151. package/dist/systems/slab/slab-system.js +1 -2
  152. package/dist/systems/stair/stair-system.d.ts.map +1 -1
  153. package/dist/systems/stair/stair-system.js +9 -8
  154. package/dist/systems/surface-hole-geometry.d.ts +1 -1
  155. package/dist/systems/surface-hole-geometry.d.ts.map +1 -1
  156. package/dist/systems/surface-hole-geometry.js +1 -1
  157. package/dist/systems/wall/level-miter-cache.d.ts.map +1 -1
  158. package/dist/systems/wall/wall-build-lifecycle.d.ts +9 -0
  159. package/dist/systems/wall/wall-build-lifecycle.d.ts.map +1 -0
  160. package/dist/systems/wall/wall-build-lifecycle.js +74 -0
  161. package/dist/systems/wall/wall-cutout-cache.d.ts +57 -0
  162. package/dist/systems/wall/wall-cutout-cache.d.ts.map +1 -0
  163. package/dist/systems/wall/wall-cutout-cache.js +304 -0
  164. package/dist/systems/wall/wall-cutout.d.ts +12 -1
  165. package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
  166. package/dist/systems/wall/wall-cutout.js +24 -161
  167. package/dist/systems/wall/wall-material-variant.d.ts +31 -0
  168. package/dist/systems/wall/wall-material-variant.d.ts.map +1 -0
  169. package/dist/systems/wall/wall-material-variant.js +10 -0
  170. package/dist/systems/wall/wall-materials.d.ts +6 -0
  171. package/dist/systems/wall/wall-materials.d.ts.map +1 -1
  172. package/dist/systems/wall/wall-materials.js +29 -13
  173. package/dist/systems/wall/wall-placeholder-sweep.d.ts +50 -0
  174. package/dist/systems/wall/wall-placeholder-sweep.d.ts.map +1 -0
  175. package/dist/systems/wall/wall-placeholder-sweep.js +51 -0
  176. package/dist/systems/wall/wall-rebuild-notifications.d.ts +5 -0
  177. package/dist/systems/wall/wall-rebuild-notifications.d.ts.map +1 -0
  178. package/dist/systems/wall/wall-rebuild-notifications.js +23 -0
  179. package/dist/systems/wall/wall-system.d.ts +11 -4
  180. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  181. package/dist/systems/wall/wall-system.js +405 -153
  182. package/dist/systems/window/window-animation-system.d.ts.map +1 -1
  183. package/dist/systems/window/window-animation-system.js +9 -8
  184. package/dist/systems/window/window-system.d.ts +1 -0
  185. package/dist/systems/window/window-system.d.ts.map +1 -1
  186. package/dist/systems/window/window-system.js +16 -2
  187. package/package.json +17 -4
  188. package/dist/lib/polygon-union.d.ts +0 -4
  189. package/dist/lib/polygon-union.d.ts.map +0 -1
  190. package/dist/lib/polygon-union.js +0 -289
@@ -6,6 +6,7 @@ import * as THREE from 'three/webgpu';
6
6
  import { SHADOW_ONLY_LAYER } from '../../lib/layers';
7
7
  import { getSceneTheme } from '../../lib/scene-themes';
8
8
  import useViewer from '../../store/use-viewer';
9
+ import { useSceneAtmosphere } from './scene-atmosphere';
9
10
  // Diagnostic toggle: `?disable=shadows` skips the shadow-map render pass
10
11
  // (which doubles draw calls for every shadow-casting mesh) so you can
11
12
  // isolate how much of the baseline GPU cost is shadows vs. raw geometry.
@@ -61,6 +62,8 @@ export function Lights() {
61
62
  const sceneTheme = useViewer((state) => state.sceneTheme);
62
63
  const theme = getSceneTheme(sceneTheme);
63
64
  const shadows = useViewer((state) => state.shadows);
65
+ const atmosphere = useSceneAtmosphere();
66
+ const lightSlots = useMemo(() => Array.from({ length: atmosphere ? 2 : theme.lights.length }, (_, index) => index), [atmosphere, theme.lights.length]);
64
67
  const lightRefs = useRef([]);
65
68
  const shadowCamera = useRef(null);
66
69
  // Initial ortho half-size; overridden each refresh to fit the building.
@@ -68,7 +71,7 @@ export function Lights() {
68
71
  // Building bounds the shadow frustum is fit to, recomputed on an interval.
69
72
  const shadowFocus = useRef(new THREE.Vector3()); // sphere centre
70
73
  const shadowRadius = useRef(SHADOW_FALLBACK_RADIUS); // sphere radius
71
- const shadowDir = useRef(new THREE.Vector3()); // scratch: per-light direction
74
+ const shadowDir = useRef(new THREE.Vector3()); // scratch: key-light direction
72
75
  const boundsBox = useRef(new THREE.Box3()); // scratch: union AABB
73
76
  const boundsSphere = useRef(new THREE.Sphere()); // scratch: fitted sphere
74
77
  const lastBoundsTime = useRef(-1); // last refresh timestamp (-1 = never)
@@ -83,32 +86,38 @@ export function Lights() {
83
86
  ambColor: new THREE.Color(),
84
87
  }), []);
85
88
  useFrame((state, delta) => {
86
- // clamp delta to avoid huge jumps on tab switch
89
+ // Clamp delta to avoid huge jumps on tab switch.
87
90
  const dt = Math.min(delta, 0.1) * 4;
88
- // Fit each shadow-casting light's frustum to the BUILDING geometry rather
89
- // than the camera. We refresh the union bounds on an interval (cheap enough,
90
- // and bounds only change while editing), fit a sphere, and size + place the
91
- // ortho shadow camera so the building (plus a margin) is fully covered from
92
- // the light's direction. The light DIRECTION stays exactly as the theme
93
- // specifies; only its position/distance and the frustum extents change.
91
+ // Atmosphere directions are stable mutable vectors. Keep both light
92
+ // resources mounted and move them imperatively so time/angle changes never
93
+ // rebuild materials or shadow resources.
94
+ if (atmosphere) {
95
+ for (let index = 0; index < 2; index++) {
96
+ const light = lightRefs.current[index];
97
+ if (!light)
98
+ continue;
99
+ const direction = index === 0 ? atmosphere.sunDirection : atmosphere.moonDirection;
100
+ light.position.copy(direction).multiplyScalar(100);
101
+ light.target.position.set(0, 0, 0);
102
+ light.target.updateMatrixWorld();
103
+ }
104
+ }
105
+ // Fit the single key-light shadow frustum to the BUILDING geometry rather
106
+ // than the camera. The source controls its direction; only its distance and
107
+ // frustum extents are derived here.
94
108
  if (shadows) {
95
109
  const now = state.clock.elapsedTime;
96
110
  if (now - lastBoundsTime.current >= BOUNDS_REFRESH_INTERVAL) {
97
111
  lastBoundsTime.current = now;
98
112
  const box = boundsBox.current.makeEmpty();
99
113
  for (const [id, obj] of sceneRegistry.nodes) {
100
- if (SHADOW_EXCLUDED_TYPES.some((t) => sceneRegistry.byType[t].has(id)))
114
+ if (SHADOW_EXCLUDED_TYPES.some((type) => sceneRegistry.byType[type].has(id)))
101
115
  continue;
102
116
  box.expandByObject(obj);
103
117
  }
104
118
  box.getBoundingSphere(boundsSphere.current);
105
119
  const center = boundsSphere.current.center;
106
120
  const radius = boundsSphere.current.radius;
107
- // Empty scene OR a node with a NaN position/geometry poisoning the union
108
- // box: fall back to the origin with a default radius. The directional
109
- // light's position is derived from `focus`, so a single non-finite mesh
110
- // must NOT be allowed to make `focus`/`radius` NaN — that breaks every
111
- // shadow-casting light's position and renders the whole scene black.
112
121
  const finiteBounds = !box.isEmpty() &&
113
122
  Number.isFinite(center.x) &&
114
123
  Number.isFinite(center.y) &&
@@ -123,33 +132,32 @@ export function Lights() {
123
132
  shadowRadius.current = SHADOW_FALLBACK_RADIUS;
124
133
  }
125
134
  }
126
- const focus = shadowFocus.current;
127
- // Ortho half-extent: the building sphere plus a proportional margin.
128
- const size = shadowRadius.current * SHADOW_MARGIN_SCALE + SHADOW_MARGIN;
129
- // Park the light just outside the sphere so the near plane stays positive
130
- // and the whole building fits between near and far along the light axis.
131
- const distance = size + SHADOW_BACKOFF;
132
- const near = SHADOW_BACKOFF;
133
- const far = distance + size;
134
- for (let index = 0; index < theme.lights.length; index++) {
135
- const config = theme.lights[index];
136
- const light = lightRefs.current[index];
137
- if (!(config?.castShadow && light))
138
- continue;
139
- const [ox, oy, oz] = config.position;
140
- const dir = shadowDir.current.set(ox, oy, oz);
141
- if (dir.lengthSq() === 0)
142
- dir.set(0, 1, 0);
143
- dir.normalize().multiplyScalar(distance);
144
- light.position.set(focus.x + dir.x, focus.y + dir.y, focus.z + dir.z);
135
+ const light = lightRefs.current[0];
136
+ const themeKey = theme.lights[0];
137
+ const castsShadow = atmosphere ? true : Boolean(themeKey?.castShadow);
138
+ if (light && castsShadow) {
139
+ const focus = shadowFocus.current;
140
+ const size = shadowRadius.current * SHADOW_MARGIN_SCALE + SHADOW_MARGIN;
141
+ const distance = size + SHADOW_BACKOFF;
142
+ const near = SHADOW_BACKOFF;
143
+ const far = distance + size;
144
+ if (atmosphere) {
145
+ shadowDir.current.copy(atmosphere.sunDirection);
146
+ }
147
+ else if (themeKey) {
148
+ shadowDir.current.set(...themeKey.position);
149
+ }
150
+ else {
151
+ shadowDir.current.set(0, 1, 0);
152
+ }
153
+ if (shadowDir.current.lengthSq() === 0)
154
+ shadowDir.current.set(0, 1, 0);
155
+ shadowDir.current.normalize().multiplyScalar(distance);
156
+ light.position.copy(focus).add(shadowDir.current);
145
157
  light.target.position.copy(focus);
146
158
  light.target.updateMatrixWorld();
147
- // Resize the ortho frustum to the fitted bounds. The shadow camera is
148
- // the <orthographicCamera attach="shadow-camera"> below.
149
159
  const cam = light.shadow?.camera;
150
160
  if (cam) {
151
- // Shadow-caster-only geometry (hidden roofs/levels in cutaway views)
152
- // is visible to the shadow pass alone — see lib/shadow-only.ts.
153
161
  cam.layers.enable(SHADOW_ONLY_LAYER);
154
162
  cam.left = -size;
155
163
  cam.right = size;
@@ -159,10 +167,10 @@ export function Lights() {
159
167
  cam.far = far;
160
168
  cam.updateProjectionMatrix();
161
169
  if (SHADOW_CAMERA_DEBUG) {
162
- let helper = shadowHelpers.current[index];
170
+ let helper = shadowHelpers.current[0];
163
171
  if (!helper) {
164
172
  helper = new THREE.CameraHelper(cam);
165
- shadowHelpers.current[index] = helper;
173
+ shadowHelpers.current[0] = helper;
166
174
  state.scene.add(helper);
167
175
  }
168
176
  helper.update();
@@ -170,63 +178,89 @@ export function Lights() {
170
178
  }
171
179
  }
172
180
  }
173
- if (!initialized.current) {
174
- for (let index = 0; index < theme.lights.length; index++) {
175
- const config = theme.lights[index];
176
- const light = lightRefs.current[index];
177
- if (!(config && light))
178
- continue;
179
- light.intensity = config.intensity;
180
- light.color.set(config.color);
181
- if (config.castShadow && light.shadow) {
182
- light.shadow.intensity = config.intensity <= 1 ? config.intensity : MAX_SHADOW_INTENSITY;
183
- }
184
- }
185
- if (hemiRef.current && theme.hemi) {
186
- hemiRef.current.intensity = theme.hemi.intensity;
187
- hemiRef.current.color.set(theme.hemi.sky);
188
- hemiRef.current.groundColor.set(theme.hemi.ground);
189
- }
190
- if (ambientRef.current) {
191
- ambientRef.current.intensity = theme.ambient.intensity;
192
- ambientRef.current.color.set(theme.ambient.color);
193
- }
194
- initialized.current = true;
195
- return;
196
- }
197
- for (let index = 0; index < theme.lights.length; index++) {
198
- const config = theme.lights[index];
181
+ for (const index of lightSlots) {
199
182
  const light = lightRefs.current[index];
200
- if (!(config && light))
183
+ if (!light)
201
184
  continue;
202
- light.intensity = THREE.MathUtils.lerp(light.intensity, config.intensity, dt);
203
- let target = lightTargets.current[index];
204
- if (!target) {
205
- target = new THREE.Color();
206
- lightTargets.current[index] = target;
185
+ const config = theme.lights[index];
186
+ const intensity = atmosphere
187
+ ? index === 0
188
+ ? atmosphere.sunIntensity
189
+ : atmosphere.moonIntensity
190
+ : (config?.intensity ?? 0);
191
+ const color = atmosphere
192
+ ? index === 0
193
+ ? atmosphere.sunColor
194
+ : atmosphere.moonColor
195
+ : config?.color;
196
+ if (atmosphere || !initialized.current) {
197
+ light.intensity = intensity;
198
+ if (color)
199
+ light.color.set(color);
207
200
  }
208
- target.set(config.color);
209
- light.color.lerp(target, dt);
210
- if (config.castShadow && light.shadow) {
211
- if (light.shadow.intensity !== undefined) {
212
- light.shadow.intensity = THREE.MathUtils.lerp(light.shadow.intensity, config.intensity <= 1 ? config.intensity : MAX_SHADOW_INTENSITY, dt);
201
+ else {
202
+ light.intensity = THREE.MathUtils.lerp(light.intensity, intensity, dt);
203
+ let target = lightTargets.current[index];
204
+ if (!target) {
205
+ target = new THREE.Color();
206
+ lightTargets.current[index] = target;
213
207
  }
208
+ if (color)
209
+ target.set(color);
210
+ light.color.lerp(target, dt);
211
+ }
212
+ if (index === 0 && light.shadow?.intensity !== undefined) {
213
+ const shadowIntensity = intensity <= 1 ? intensity : MAX_SHADOW_INTENSITY;
214
+ light.shadow.intensity =
215
+ atmosphere || !initialized.current
216
+ ? shadowIntensity
217
+ : THREE.MathUtils.lerp(light.shadow.intensity, shadowIntensity, dt);
214
218
  }
215
219
  }
216
- if (hemiRef.current && theme.hemi) {
217
- hemiRef.current.intensity = THREE.MathUtils.lerp(hemiRef.current.intensity, theme.hemi.intensity, dt);
218
- targets.hemiSky.set(theme.hemi.sky);
219
- hemiRef.current.color.lerp(targets.hemiSky, dt);
220
- targets.hemiGround.set(theme.hemi.ground);
221
- hemiRef.current.groundColor.lerp(targets.hemiGround, dt);
220
+ const hemiIntensity = atmosphere ? atmosphere.hemisphereIntensity : theme.hemi?.intensity;
221
+ const hemiSky = atmosphere ? atmosphere.skyColor : theme.hemi?.sky;
222
+ const hemiGround = atmosphere ? atmosphere.groundColor : theme.hemi?.ground;
223
+ if (hemiRef.current && hemiIntensity !== undefined && hemiSky && hemiGround) {
224
+ if (atmosphere || !initialized.current) {
225
+ hemiRef.current.intensity = hemiIntensity;
226
+ hemiRef.current.color.set(hemiSky);
227
+ hemiRef.current.groundColor.set(hemiGround);
228
+ }
229
+ else {
230
+ hemiRef.current.intensity = THREE.MathUtils.lerp(hemiRef.current.intensity, hemiIntensity, dt);
231
+ targets.hemiSky.set(hemiSky);
232
+ hemiRef.current.color.lerp(targets.hemiSky, dt);
233
+ targets.hemiGround.set(hemiGround);
234
+ hemiRef.current.groundColor.lerp(targets.hemiGround, dt);
235
+ }
222
236
  }
223
237
  if (ambientRef.current) {
224
- ambientRef.current.intensity = THREE.MathUtils.lerp(ambientRef.current.intensity, theme.ambient.intensity, dt);
225
- targets.ambColor.set(theme.ambient.color);
226
- ambientRef.current.color.lerp(targets.ambColor, dt);
238
+ const ambientIntensity = atmosphere ? atmosphere.ambientIntensity : theme.ambient.intensity;
239
+ const ambientColor = atmosphere ? '#ffffff' : theme.ambient.color;
240
+ if (atmosphere || !initialized.current) {
241
+ ambientRef.current.intensity = ambientIntensity;
242
+ ambientRef.current.color.set(ambientColor);
243
+ }
244
+ else {
245
+ ambientRef.current.intensity = THREE.MathUtils.lerp(ambientRef.current.intensity, ambientIntensity, dt);
246
+ targets.ambColor.set(ambientColor);
247
+ ambientRef.current.color.lerp(targets.ambColor, dt);
248
+ }
227
249
  }
228
- });
229
- return (_jsxs(_Fragment, { children: [theme.lights.map((light, index) => (_jsx("directionalLight", { castShadow: Boolean(light.castShadow) && !SHADOWS_DISABLED, position: light.position, ref: (ref) => {
230
- lightRefs.current[index] = ref;
231
- }, "shadow-bias": SHADOW_DEPTH_BIAS, "shadow-mapSize": [1024, 1024], "shadow-normalBias": SHADOW_NORMAL_BIAS, "shadow-radius": 2, children: light.castShadow && !SHADOWS_DISABLED ? (_jsx("orthographicCamera", { attach: "shadow-camera", bottom: -shadowCameraSize, far: 400, left: -shadowCameraSize, near: 1, ref: shadowCamera, right: shadowCameraSize, top: shadowCameraSize })) : null }, `${index}-${light.position.join(',')}`))), theme.hemi ? _jsx("hemisphereLight", { ref: hemiRef }) : null, _jsx("ambientLight", { ref: ambientRef })] }));
250
+ initialized.current = true;
251
+ }, -1);
252
+ const keyCastsShadow = !SHADOWS_DISABLED && (atmosphere ? true : Boolean(theme.lights[0]?.castShadow));
253
+ return (_jsxs(_Fragment, { children: [lightSlots.map((index) => {
254
+ const themeLight = theme.lights[index];
255
+ const direction = atmosphere && index === 0
256
+ ? atmosphere.sunDirection
257
+ : atmosphere && index === 1
258
+ ? atmosphere.moonDirection
259
+ : null;
260
+ return (_jsx("directionalLight", { castShadow: index === 0 && keyCastsShadow, position: direction
261
+ ? [direction.x * 100, direction.y * 100, direction.z * 100]
262
+ : (themeLight?.position ?? [0, 1, 0]), ref: (light) => {
263
+ lightRefs.current[index] = light;
264
+ }, "shadow-bias": SHADOW_DEPTH_BIAS, "shadow-mapSize": [1024, 1024], "shadow-normalBias": SHADOW_NORMAL_BIAS, "shadow-radius": 2, children: index === 0 && keyCastsShadow ? (_jsx("orthographicCamera", { attach: "shadow-camera", bottom: -shadowCameraSize, far: 400, left: -shadowCameraSize, near: 1, ref: shadowCamera, right: shadowCameraSize, top: shadowCameraSize })) : null }, index));
265
+ }), atmosphere || theme.hemi ? _jsx("hemisphereLight", { ref: hemiRef }) : null, _jsx("ambientLight", { ref: ambientRef })] }));
232
266
  }
@@ -1,2 +1,7 @@
1
- export declare const PerfMonitor: () => import("react").JSX.Element;
1
+ /**
2
+ * Headless collector. Runs inside <Canvas> (it needs useFrame + gl.info) and
3
+ * publishes each window's stats to perf-panel-store; the visible panel is
4
+ * <PerfPanel>, mounted outside the canvas — see perf-panel.tsx for why.
5
+ */
6
+ export declare const PerfMonitor: () => null;
2
7
  //# sourceMappingURL=perf-monitor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"perf-monitor.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/perf-monitor.tsx"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,mCAsJvB,CAAA"}
1
+ {"version":3,"file":"perf-monitor.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/perf-monitor.tsx"],"names":[],"mappings":"AA2CA;;;;GAIG;AACH,eAAO,MAAM,WAAW,YAuTvB,CAAA"}