@pascal-app/viewer 1.0.3 → 1.0.5

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 (276) hide show
  1. package/dist/capture/capture-runtime.js +1 -1
  2. package/dist/components/error-boundary.d.ts.map +1 -1
  3. package/dist/components/renderers/node-renderer.d.ts +1 -1
  4. package/dist/components/renderers/node-renderer.d.ts.map +1 -1
  5. package/dist/components/renderers/node-renderer.js +12 -4
  6. package/dist/components/renderers/parametric-node-renderer.d.ts.map +1 -1
  7. package/dist/components/viewer/bvh-ecctrl.d.ts.map +1 -1
  8. package/dist/components/viewer/frame-limiter.d.ts +1 -0
  9. package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
  10. package/dist/components/viewer/frame-limiter.js +22 -3
  11. package/dist/components/viewer/glb-interactive.d.ts +25 -1
  12. package/dist/components/viewer/glb-interactive.d.ts.map +1 -1
  13. package/dist/components/viewer/glb-interactive.js +253 -86
  14. package/dist/components/viewer/glb-mechanisms.d.ts +10 -0
  15. package/dist/components/viewer/glb-mechanisms.d.ts.map +1 -0
  16. package/dist/components/viewer/glb-mechanisms.js +19 -0
  17. package/dist/components/viewer/glb-reference-nodes.js +1 -1
  18. package/dist/components/viewer/glb-replace-instances.js +1 -1
  19. package/dist/components/viewer/glb-scene.d.ts +45 -27
  20. package/dist/components/viewer/glb-scene.d.ts.map +1 -1
  21. package/dist/components/viewer/glb-scene.js +421 -508
  22. package/dist/components/viewer/glb-walkthrough-controller.d.ts +1 -1
  23. package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -1
  24. package/dist/components/viewer/glb-walkthrough-controller.js +13 -2
  25. package/dist/components/viewer/index.d.ts +24 -1
  26. package/dist/components/viewer/index.d.ts.map +1 -1
  27. package/dist/components/viewer/index.js +111 -37
  28. package/dist/components/viewer/lights.d.ts.map +1 -1
  29. package/dist/components/viewer/lights.js +113 -22
  30. package/dist/components/viewer/perf-monitor.d.ts.map +1 -1
  31. package/dist/components/viewer/perf-monitor.js +6 -0
  32. package/dist/components/viewer/perf-panel.d.ts.map +1 -1
  33. package/dist/components/viewer/perf-panel.js +1 -1
  34. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  35. package/dist/components/viewer/post-processing.js +104 -36
  36. package/dist/components/viewer/registered-systems.d.ts.map +1 -1
  37. package/dist/components/viewer/registered-systems.js +17 -3
  38. package/dist/components/viewer/render-error.d.ts +18 -0
  39. package/dist/components/viewer/render-error.d.ts.map +1 -0
  40. package/dist/components/viewer/render-error.js +29 -0
  41. package/dist/components/viewer/scene-bvh.d.ts.map +1 -1
  42. package/dist/components/viewer/scene-bvh.js +1 -1
  43. package/dist/components/viewer/scene-environment.d.ts.map +1 -1
  44. package/dist/components/viewer/scene-environment.js +31 -11
  45. package/dist/components/viewer/scene-ground-replacement.d.ts +6 -0
  46. package/dist/components/viewer/scene-ground-replacement.d.ts.map +1 -1
  47. package/dist/components/viewer/scene-ground-replacement.js +15 -0
  48. package/dist/components/viewer/selection-manager.d.ts.map +1 -1
  49. package/dist/components/viewer/selection-manager.js +25 -7
  50. package/dist/components/viewer/underground-ambiance.d.ts +9 -0
  51. package/dist/components/viewer/underground-ambiance.d.ts.map +1 -0
  52. package/dist/components/viewer/underground-ambiance.js +105 -0
  53. package/dist/components/viewer/viewer-camera.d.ts +4 -0
  54. package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
  55. package/dist/components/viewer/viewer-camera.js +12 -2
  56. package/dist/components/viewer/viewer-presentations.d.ts.map +1 -1
  57. package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
  58. package/dist/hooks/use-gltf-ktx2.js +2 -0
  59. package/dist/hooks/use-node-events.d.ts.map +1 -1
  60. package/dist/index.d.ts +36 -16
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +34 -19
  63. package/dist/lib/asset-url.d.ts.map +1 -1
  64. package/dist/lib/asset-url.js +7 -1
  65. package/dist/lib/backdrop.d.ts +17 -0
  66. package/dist/lib/backdrop.d.ts.map +1 -1
  67. package/dist/lib/backdrop.js +18 -1
  68. package/dist/lib/construction-dust.d.ts +57 -0
  69. package/dist/lib/construction-dust.d.ts.map +1 -0
  70. package/dist/lib/construction-dust.js +187 -0
  71. package/dist/lib/csg-utils.js +1 -1
  72. package/dist/lib/display-state.d.ts +25 -0
  73. package/dist/lib/display-state.d.ts.map +1 -0
  74. package/dist/lib/display-state.js +1 -0
  75. package/dist/lib/foundation-materials.d.ts +26 -0
  76. package/dist/lib/foundation-materials.d.ts.map +1 -0
  77. package/dist/lib/foundation-materials.js +65 -0
  78. package/dist/lib/gltf-unlit.d.ts +10 -0
  79. package/dist/lib/gltf-unlit.d.ts.map +1 -0
  80. package/dist/lib/gltf-unlit.js +23 -0
  81. package/dist/lib/ground-window.d.ts +33 -0
  82. package/dist/lib/ground-window.d.ts.map +1 -0
  83. package/dist/lib/ground-window.js +114 -0
  84. package/dist/lib/hero-pose.d.ts +13 -3
  85. package/dist/lib/hero-pose.d.ts.map +1 -1
  86. package/dist/lib/hero-pose.js +72 -5
  87. package/dist/lib/ink-edges.d.ts +6 -3
  88. package/dist/lib/ink-edges.d.ts.map +1 -1
  89. package/dist/lib/ink-edges.js +17 -7
  90. package/dist/lib/key-light-override.d.ts +11 -0
  91. package/dist/lib/key-light-override.d.ts.map +1 -0
  92. package/dist/lib/key-light-override.js +14 -0
  93. package/dist/lib/ktx2-loader.d.ts +7 -0
  94. package/dist/lib/ktx2-loader.d.ts.map +1 -1
  95. package/dist/lib/ktx2-loader.js +35 -0
  96. package/dist/lib/layer-pass.d.ts.map +1 -1
  97. package/dist/lib/layers.d.ts +11 -7
  98. package/dist/lib/layers.d.ts.map +1 -1
  99. package/dist/lib/layers.js +16 -6
  100. package/dist/lib/live-frame-hold.d.ts +14 -0
  101. package/dist/lib/live-frame-hold.d.ts.map +1 -0
  102. package/dist/lib/live-frame-hold.js +28 -0
  103. package/dist/lib/materials.d.ts +19 -7
  104. package/dist/lib/materials.d.ts.map +1 -1
  105. package/dist/lib/materials.js +65 -9
  106. package/dist/lib/merged-outline-node.d.ts +5 -0
  107. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  108. package/dist/lib/merged-outline-node.js +80 -2
  109. package/dist/lib/node-top-surface-height.d.ts +6 -0
  110. package/dist/lib/node-top-surface-height.d.ts.map +1 -0
  111. package/dist/lib/node-top-surface-height.js +74 -0
  112. package/dist/lib/perf-probe-state.d.ts +39 -0
  113. package/dist/lib/perf-probe-state.d.ts.map +1 -0
  114. package/dist/lib/perf-probe-state.js +17 -0
  115. package/dist/lib/pointer-events.d.ts +26 -2
  116. package/dist/lib/pointer-events.d.ts.map +1 -1
  117. package/dist/lib/pointer-events.js +99 -12
  118. package/dist/lib/post-processing-resources.d.ts.map +1 -1
  119. package/dist/lib/procedural-emission.d.ts +7 -0
  120. package/dist/lib/procedural-emission.d.ts.map +1 -0
  121. package/dist/lib/procedural-emission.js +54 -0
  122. package/dist/lib/reveal-candidates.d.ts +80 -0
  123. package/dist/lib/reveal-candidates.d.ts.map +1 -0
  124. package/dist/lib/reveal-candidates.js +524 -0
  125. package/dist/lib/reveal-ghost.d.ts +9 -0
  126. package/dist/lib/reveal-ghost.d.ts.map +1 -0
  127. package/dist/lib/reveal-ghost.js +62 -0
  128. package/dist/lib/reveal-pending.d.ts +12 -0
  129. package/dist/lib/reveal-pending.d.ts.map +1 -0
  130. package/dist/lib/reveal-pending.js +12 -0
  131. package/dist/lib/reveal-pose.d.ts +70 -0
  132. package/dist/lib/reveal-pose.d.ts.map +1 -0
  133. package/dist/lib/reveal-pose.js +248 -0
  134. package/dist/lib/reveal-schedule.d.ts +208 -0
  135. package/dist/lib/reveal-schedule.d.ts.map +1 -0
  136. package/dist/lib/reveal-schedule.js +410 -0
  137. package/dist/lib/reveal-texture-scale.d.ts +5 -0
  138. package/dist/lib/reveal-texture-scale.d.ts.map +1 -0
  139. package/dist/lib/reveal-texture-scale.js +113 -0
  140. package/dist/lib/reveal-windows.d.ts +23 -0
  141. package/dist/lib/reveal-windows.d.ts.map +1 -0
  142. package/dist/lib/reveal-windows.js +31 -0
  143. package/dist/lib/reveal-wipe.d.ts +71 -0
  144. package/dist/lib/reveal-wipe.d.ts.map +1 -0
  145. package/dist/lib/reveal-wipe.js +105 -0
  146. package/dist/lib/scene-pass-mrt.d.ts +12 -0
  147. package/dist/lib/scene-pass-mrt.d.ts.map +1 -0
  148. package/dist/lib/scene-pass-mrt.js +23 -0
  149. package/dist/lib/scene-support-height.d.ts +4 -0
  150. package/dist/lib/scene-support-height.d.ts.map +1 -0
  151. package/dist/lib/scene-support-height.js +34 -0
  152. package/dist/lib/scene-themes.d.ts +30 -8
  153. package/dist/lib/scene-themes.d.ts.map +1 -1
  154. package/dist/lib/scene-themes.js +36 -0
  155. package/dist/lib/scene-visibility.d.ts +17 -1
  156. package/dist/lib/scene-visibility.d.ts.map +1 -1
  157. package/dist/lib/scene-visibility.js +53 -3
  158. package/dist/lib/scripted-opening.d.ts +11 -0
  159. package/dist/lib/scripted-opening.d.ts.map +1 -0
  160. package/dist/lib/scripted-opening.js +20 -0
  161. package/dist/lib/site-surfaces.d.ts +32 -0
  162. package/dist/lib/site-surfaces.d.ts.map +1 -0
  163. package/dist/lib/site-surfaces.js +70 -0
  164. package/dist/lib/snapshot-pipeline.d.ts +34 -3
  165. package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
  166. package/dist/lib/snapshot-pipeline.js +247 -117
  167. package/dist/lib/terrain-perimeter-fill.d.ts.map +1 -1
  168. package/dist/lib/terrain-perimeter-fill.js +22 -14
  169. package/dist/lib/tsl-compat.d.ts +2 -2
  170. package/dist/lib/tsl-compat.d.ts.map +1 -1
  171. package/dist/lib/underground-ambiance.d.ts +168 -0
  172. package/dist/lib/underground-ambiance.d.ts.map +1 -0
  173. package/dist/lib/underground-ambiance.js +334 -0
  174. package/dist/lib/zone-geometry.d.ts +11 -0
  175. package/dist/lib/zone-geometry.d.ts.map +1 -0
  176. package/dist/lib/zone-geometry.js +46 -0
  177. package/dist/store/use-item-light-pool.d.ts +14 -10
  178. package/dist/store/use-item-light-pool.d.ts.map +1 -1
  179. package/dist/store/use-item-light-pool.js +52 -26
  180. package/dist/store/use-viewer.d.ts +194 -26
  181. package/dist/store/use-viewer.d.ts.map +1 -1
  182. package/dist/store/use-viewer.js +164 -21
  183. package/dist/systems/ceiling/ceiling-system.d.ts +15 -1
  184. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  185. package/dist/systems/ceiling/ceiling-system.js +88 -6
  186. package/dist/systems/construction-reveal/construction-dust.d.ts +16 -0
  187. package/dist/systems/construction-reveal/construction-dust.d.ts.map +1 -0
  188. package/dist/systems/construction-reveal/construction-dust.js +92 -0
  189. package/dist/systems/construction-reveal/construction-reveal.d.ts +276 -0
  190. package/dist/systems/construction-reveal/construction-reveal.d.ts.map +1 -0
  191. package/dist/systems/construction-reveal/construction-reveal.js +2383 -0
  192. package/dist/systems/construction-reveal/dust-material.d.ts +10 -0
  193. package/dist/systems/construction-reveal/dust-material.d.ts.map +1 -0
  194. package/dist/systems/construction-reveal/dust-material.js +17 -0
  195. package/dist/systems/construction-reveal/ghost-dress.d.ts +10 -0
  196. package/dist/systems/construction-reveal/ghost-dress.d.ts.map +1 -0
  197. package/dist/systems/construction-reveal/ghost-dress.js +24 -0
  198. package/dist/systems/door/door-system.d.ts.map +1 -1
  199. package/dist/systems/door/door-system.js +55 -17
  200. package/dist/systems/elevator/elevator-interaction-system.d.ts +7 -0
  201. package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -1
  202. package/dist/systems/elevator/elevator-interaction-system.js +18 -1
  203. package/dist/systems/floor-elevation/floor-elevation-system.d.ts +3 -1
  204. package/dist/systems/floor-elevation/floor-elevation-system.d.ts.map +1 -1
  205. package/dist/systems/floor-elevation/floor-elevation-system.js +33 -5
  206. package/dist/systems/geometry/geometry-system.d.ts.map +1 -1
  207. package/dist/systems/geometry/geometry-system.js +71 -11
  208. package/dist/systems/interactive/control-widget.d.ts.map +1 -1
  209. package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
  210. package/dist/systems/interactive/interactive-system.js +52 -17
  211. package/dist/systems/interactive/procedural-controls.d.ts +13 -0
  212. package/dist/systems/interactive/procedural-controls.d.ts.map +1 -0
  213. package/dist/systems/interactive/procedural-controls.js +17 -0
  214. package/dist/systems/interactive/scripted-clips.d.ts +19 -0
  215. package/dist/systems/interactive/scripted-clips.d.ts.map +1 -0
  216. package/dist/systems/interactive/scripted-clips.js +134 -0
  217. package/dist/systems/item/item-system.d.ts.map +1 -1
  218. package/dist/systems/item/item-system.js +9 -3
  219. package/dist/systems/item/object-cut-invalidation.d.ts +3 -0
  220. package/dist/systems/item/object-cut-invalidation.d.ts.map +1 -0
  221. package/dist/systems/item/object-cut-invalidation.js +68 -0
  222. package/dist/systems/item-light/item-light-system.d.ts +1 -1
  223. package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
  224. package/dist/systems/item-light/item-light-system.js +48 -53
  225. package/dist/systems/level/level-hold.d.ts +4 -0
  226. package/dist/systems/level/level-hold.d.ts.map +1 -0
  227. package/dist/systems/level/level-hold.js +14 -0
  228. package/dist/systems/level/level-system.d.ts.map +1 -1
  229. package/dist/systems/level/level-system.js +19 -6
  230. package/dist/systems/level/level-utils.d.ts +19 -6
  231. package/dist/systems/level/level-utils.d.ts.map +1 -1
  232. package/dist/systems/level/level-utils.js +68 -9
  233. package/dist/systems/level/shadow-only-levels.d.ts +9 -0
  234. package/dist/systems/level/shadow-only-levels.d.ts.map +1 -0
  235. package/dist/systems/level/shadow-only-levels.js +7 -0
  236. package/dist/systems/roof/__fixtures__/roof-plane-cases.d.ts +103 -0
  237. package/dist/systems/roof/__fixtures__/roof-plane-cases.d.ts.map +1 -0
  238. package/dist/systems/roof/__fixtures__/roof-plane-cases.js +317 -0
  239. package/dist/systems/roof/roof-materials.d.ts +16 -2
  240. package/dist/systems/roof/roof-materials.d.ts.map +1 -1
  241. package/dist/systems/roof/roof-materials.js +64 -31
  242. package/dist/systems/roof/roof-system.d.ts +21 -4
  243. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  244. package/dist/systems/roof/roof-system.js +374 -49
  245. package/dist/systems/slab/slab-system.d.ts +1 -1
  246. package/dist/systems/slab/slab-system.d.ts.map +1 -1
  247. package/dist/systems/slab/slab-system.js +49 -19
  248. package/dist/systems/stair/stair-system.d.ts.map +1 -1
  249. package/dist/systems/stair/stair-system.js +133 -354
  250. package/dist/systems/wall/wall-cutout-cache.d.ts +39 -3
  251. package/dist/systems/wall/wall-cutout-cache.d.ts.map +1 -1
  252. package/dist/systems/wall/wall-cutout-cache.js +141 -19
  253. package/dist/systems/wall/wall-cutout.d.ts +6 -0
  254. package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
  255. package/dist/systems/wall/wall-cutout.js +42 -28
  256. package/dist/systems/wall/wall-finish-data.d.ts +22 -0
  257. package/dist/systems/wall/wall-finish-data.d.ts.map +1 -0
  258. package/dist/systems/wall/wall-finish-data.js +17 -0
  259. package/dist/systems/wall/wall-material-variant.d.ts.map +1 -1
  260. package/dist/systems/wall/wall-materials.d.ts +9 -4
  261. package/dist/systems/wall/wall-materials.d.ts.map +1 -1
  262. package/dist/systems/wall/wall-materials.js +135 -153
  263. package/dist/systems/wall/wall-placeholder-sweep.d.ts.map +1 -1
  264. package/dist/systems/wall/wall-system.d.ts +33 -2
  265. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  266. package/dist/systems/wall/wall-system.js +621 -159
  267. package/dist/systems/window/corner-frame.d.ts +10 -0
  268. package/dist/systems/window/corner-frame.d.ts.map +1 -0
  269. package/dist/systems/window/corner-frame.js +17 -0
  270. package/dist/systems/window/window-system.d.ts +1 -1
  271. package/dist/systems/window/window-system.d.ts.map +1 -1
  272. package/dist/systems/window/window-system.js +71 -27
  273. package/package.json +10 -10
  274. package/dist/systems/fence/fence-system.d.ts +0 -22
  275. package/dist/systems/fence/fence-system.d.ts.map +0 -1
  276. package/dist/systems/fence/fence-system.js +0 -357
@@ -7,5 +7,5 @@ import * as THREE from 'three';
7
7
  * a recessed slab is an open shell (pool), everything else a solid occupying
8
8
  * `[elevation − thickness, elevation]`.
9
9
  */
10
- export declare function generateSlabGeometry(slabNode: SlabNode, context: SlabPolygonContext): THREE.BufferGeometry;
10
+ export declare function generateSlabGeometry(slabNode: SlabNode, context: SlabPolygonContext, platformBaseAt?: (x: number, z: number) => number): THREE.BufferGeometry;
11
11
  //# sourceMappingURL=slab-system.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slab-system.d.ts","sourceRoot":"","sources":["../../../src/systems/slab/slab-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,kBAAkB,EAExB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,kBAAkB,GAC1B,KAAK,CAAC,cAAc,CAItB"}
1
+ {"version":3,"file":"slab-system.d.ts","sourceRoot":"","sources":["../../../src/systems/slab/slab-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,kBAAkB,EAExB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,kBAAkB,EAC3B,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,GAChD,KAAK,CAAC,cAAc,CAItB"}
@@ -11,10 +11,29 @@ import { mergeSurfaceHolePolygons } from '../surface-hole-geometry';
11
11
  * a recessed slab is an open shell (pool), everything else a solid occupying
12
12
  * `[elevation − thickness, elevation]`.
13
13
  */
14
- export function generateSlabGeometry(slabNode, context) {
14
+ export function generateSlabGeometry(slabNode, context, platformBaseAt) {
15
15
  return slabNode.recessed
16
16
  ? generatePoolGeometry(slabNode, context)
17
- : generateSolidSlabGeometry(slabNode, context);
17
+ : generateSolidSlabGeometry(slabNode, context, platformBaseAt);
18
+ }
19
+ /** Rings below this area (m²) have collapsed: a sliver cap would still grow full-height side walls. */
20
+ const MIN_SLAB_REGION_AREA = 1e-6;
21
+ function signedArea2(polygon) {
22
+ let area2 = 0;
23
+ for (let i = 0; i < polygon.length; i++) {
24
+ const j = (i + 1) % polygon.length;
25
+ area2 += polygon[i][0] * polygon[j][1] - polygon[j][0] * polygon[i][1];
26
+ }
27
+ return area2;
28
+ }
29
+ /**
30
+ * A renderable polygon collapses when snapping its edges to wall faces or
31
+ * sibling seams leaves fewer than three points or no area (a threshold strip
32
+ * inside a wall band). Such a slab builds an empty geometry instead of a sliver;
33
+ * a hole or cut region that collapses the same way is skipped.
34
+ */
35
+ function isCollapsedPolygon(polygon) {
36
+ return polygon.length < 3 || Math.abs(signedArea2(polygon)) / 2 < MIN_SLAB_REGION_AREA;
18
37
  }
19
38
  // Earcut normalizes cap triangulation regardless of input winding, but the side
20
39
  // walls below assume a CCW contour (the unflipped quad's right-hand normal faces
@@ -22,12 +41,7 @@ export function generateSlabGeometry(slabNode, context) {
22
41
  // winding, so a CW-drawn slab gets inward-facing walls that FrontSide culls and
23
42
  // the slab reads as see-through from the front. Normalize to CCW first.
24
43
  function ensureCounterClockwisePolygon(polygon) {
25
- let area2 = 0;
26
- for (let i = 0; i < polygon.length; i++) {
27
- const j = (i + 1) % polygon.length;
28
- area2 += polygon[i][0] * polygon[j][1] - polygon[j][0] * polygon[i][1];
29
- }
30
- return area2 < 0 ? [...polygon].reverse() : polygon;
44
+ return signedArea2(polygon) < 0 ? [...polygon].reverse() : polygon;
31
45
  }
32
46
  function isStrictInteriorHole(contour, hole) {
33
47
  return (hole.every((point) => pointInPolygon2D(point, contour, { includeBoundary: false })) &&
@@ -42,7 +56,7 @@ function buildSlabRegions(contour, holes) {
42
56
  const containedHoles = [];
43
57
  const edgeCutouts = [];
44
58
  for (const hole of holes) {
45
- if (hole.length < 3)
59
+ if (isCollapsedPolygon(hole))
46
60
  continue;
47
61
  if (isStrictInteriorHole(contour, hole))
48
62
  containedHoles.push(hole);
@@ -68,13 +82,24 @@ function buildSlabRegions(contour, holes) {
68
82
  * thickness visible from any angle: the two coincident triangles never z-fight
69
83
  * because exactly one faces the camera under FrontSide culling.
70
84
  */
71
- function generateSolidSlabGeometry(slabNode, context) {
85
+ function generateSolidSlabGeometry(slabNode, context, platformBaseAt) {
72
86
  const polygon = ensureCounterClockwisePolygon(getRenderableSlabPolygon(slabNode, context));
73
87
  const elevation = slabNode.elevation ?? 0.05;
74
88
  const thickness = slabNode.thickness ?? 0.05;
75
89
  const bottom = elevation - thickness;
90
+ const bottomAt = (x, z) => platformBaseAt ? Math.min(bottom, platformBaseAt(x, z)) : bottom;
91
+ const sampleRing = (ring) => !platformBaseAt
92
+ ? ring
93
+ : ring.flatMap((a, i) => {
94
+ const b = ring[(i + 1) % ring.length];
95
+ const count = Math.max(1, Math.ceil(Math.hypot(b[0] - a[0], b[1] - a[1]) / 0.25));
96
+ return Array.from({ length: count }, (_, j) => [
97
+ a[0] + ((b[0] - a[0]) * j) / count,
98
+ a[1] + ((b[1] - a[1]) * j) / count,
99
+ ]);
100
+ });
76
101
  const holePolygons = mergeSurfaceHolePolygons(slabNode.holes ?? []);
77
- if (polygon.length < 3)
102
+ if (isCollapsedPolygon(polygon))
78
103
  return new THREE.BufferGeometry();
79
104
  const positions = [];
80
105
  const uvs = [];
@@ -86,10 +111,10 @@ function generateSolidSlabGeometry(slabNode, context) {
86
111
  const addWall = (a, b, flipped) => {
87
112
  const base = positions.length / 3;
88
113
  const len = Math.max(Math.hypot(b.x - a.x, b.y - a.y), 0.001);
89
- positions.push(a.x, bottom, a.y);
90
- uvs.push(0, 0);
91
- positions.push(b.x, bottom, b.y);
92
- uvs.push(len, 0);
114
+ positions.push(a.x, bottomAt(a.x, a.y), a.y);
115
+ uvs.push(0, bottomAt(a.x, a.y) - bottom);
116
+ positions.push(b.x, bottomAt(b.x, b.y), b.y);
117
+ uvs.push(len, bottomAt(b.x, b.y) - bottom);
93
118
  positions.push(b.x, elevation, b.y);
94
119
  uvs.push(len, thickness);
95
120
  positions.push(a.x, elevation, a.y);
@@ -104,10 +129,12 @@ function generateSolidSlabGeometry(slabNode, context) {
104
129
  }
105
130
  };
106
131
  for (const region of buildSlabRegions(polygon, holePolygons)) {
107
- const contour2d = ensureCounterClockwisePolygon(region.contour).map(([x, z]) => new THREE.Vector2(x, z));
132
+ if (isCollapsedPolygon(region.contour))
133
+ continue;
134
+ const contour2d = sampleRing(ensureCounterClockwisePolygon(region.contour)).map(([x, z]) => new THREE.Vector2(x, z));
108
135
  const holes2d = region.holes
109
136
  .filter((h) => h.length >= 3)
110
- .map((h) => h.map(([x, z]) => new THREE.Vector2(x, z)));
137
+ .map((h) => sampleRing(h).map(([x, z]) => new THREE.Vector2(x, z)));
111
138
  // --- Top & bottom caps ---
112
139
  // capPoints order (contour then holes) matches triangulateShape's index space.
113
140
  // UVs reproduce ExtrudeGeometry's WorldUVGenerator mapping (shape-space x,-z)
@@ -128,7 +155,8 @@ function generateSolidSlabGeometry(slabNode, context) {
128
155
  const [a, b, c] = [tri[0], tri[1], tri[2]];
129
156
  // Reversed winding → +Y normal on top; standard winding → -Y on bottom.
130
157
  indices.push(topBase + a, topBase + c, topBase + b);
131
- indices.push(bottomBase + a, bottomBase + b, bottomBase + c);
158
+ if (!platformBaseAt)
159
+ indices.push(bottomBase + a, bottomBase + b, bottomBase + c);
132
160
  }
133
161
  for (let i = 0; i < contour2d.length; i++) {
134
162
  addWall(contour2d[i], contour2d[(i + 1) % contour2d.length], false);
@@ -163,7 +191,7 @@ function generatePoolGeometry(slabNode, context) {
163
191
  const floor = slabNode.elevation ?? 0.05;
164
192
  const depth = Math.max(0, (slabNode.recessedRimElevation ?? 0) - floor);
165
193
  const holePolygons = mergeSurfaceHolePolygons(slabNode.holes ?? []);
166
- if (polygon.length < 3)
194
+ if (isCollapsedPolygon(polygon))
167
195
  return new THREE.BufferGeometry();
168
196
  const positions = [];
169
197
  const uvs = [];
@@ -179,6 +207,8 @@ function generatePoolGeometry(slabNode, context) {
179
207
  uvs.push(u, v);
180
208
  };
181
209
  for (const region of buildSlabRegions(polygon, holePolygons)) {
210
+ if (isCollapsedPolygon(region.contour))
211
+ continue;
182
212
  const contour = ensureCounterClockwisePolygon(region.contour);
183
213
  const floorBase = positions.length / 3;
184
214
  // --- Floor at Y=0 ---
@@ -1 +1 @@
1
- {"version":3,"file":"stair-system.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-system.tsx"],"names":[],"mappings":"AA2BA,eAAO,MAAM,WAAW,YAuGvB,CAAA"}
1
+ {"version":3,"file":"stair-system.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-system.tsx"],"names":[],"mappings":"AAiCA,eAAO,MAAM,WAAW,YAuGvB,CAAA"}