@pascal-app/viewer 1.0.6 → 1.0.7
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/dist/components/viewer/daylight-atmosphere.d.ts +9 -0
- package/dist/components/viewer/daylight-atmosphere.d.ts.map +1 -0
- package/dist/components/viewer/daylight-atmosphere.js +315 -0
- package/dist/components/viewer/drone-controller.d.ts +15 -0
- package/dist/components/viewer/drone-controller.d.ts.map +1 -0
- package/dist/components/viewer/drone-controller.js +194 -0
- package/dist/components/viewer/glb-interactive.d.ts +4 -18
- package/dist/components/viewer/glb-interactive.d.ts.map +1 -1
- package/dist/components/viewer/glb-interactive.js +32 -268
- package/dist/components/viewer/glb-scene-motion.d.ts +8 -0
- package/dist/components/viewer/glb-scene-motion.d.ts.map +1 -0
- package/dist/components/viewer/glb-scene-motion.js +57 -0
- package/dist/components/viewer/glb-scene.d.ts +3 -1
- package/dist/components/viewer/glb-scene.d.ts.map +1 -1
- package/dist/components/viewer/glb-scene.js +289 -49
- package/dist/components/viewer/glb-selection-callout.d.ts +17 -0
- package/dist/components/viewer/glb-selection-callout.d.ts.map +1 -0
- package/dist/components/viewer/glb-selection-callout.js +54 -0
- package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -1
- package/dist/components/viewer/glb-walkthrough-controller.js +6 -3
- package/dist/components/viewer/index.d.ts +5 -0
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +30 -6
- package/dist/components/viewer/lights.d.ts.map +1 -1
- package/dist/components/viewer/lights.js +192 -5
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +150 -94
- package/dist/components/viewer/scene-environment.js +4 -5
- package/dist/components/viewer/selection-callout.d.ts +51 -0
- package/dist/components/viewer/selection-callout.d.ts.map +1 -0
- package/dist/components/viewer/selection-callout.js +197 -0
- package/dist/components/viewer/use-daylight-rooms.d.ts +13 -0
- package/dist/components/viewer/use-daylight-rooms.d.ts.map +1 -0
- package/dist/components/viewer/use-daylight-rooms.js +236 -0
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
- package/dist/components/viewer/viewer-camera.js +12 -1
- package/dist/index.d.ts +21 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -7
- package/dist/lib/daylight/ground.d.ts +21 -0
- package/dist/lib/daylight/ground.d.ts.map +1 -0
- package/dist/lib/daylight/ground.js +53 -0
- package/dist/lib/daylight/location.d.ts +32 -0
- package/dist/lib/daylight/location.d.ts.map +1 -0
- package/dist/lib/daylight/location.js +74 -0
- package/dist/lib/daylight/look.d.ts +33 -0
- package/dist/lib/daylight/look.d.ts.map +1 -0
- package/dist/lib/daylight/look.js +13 -0
- package/dist/lib/daylight/material-hooks.d.ts +2 -0
- package/dist/lib/daylight/material-hooks.d.ts.map +1 -0
- package/dist/lib/daylight/material-hooks.js +150 -0
- package/dist/lib/daylight/room-context.d.ts +12 -0
- package/dist/lib/daylight/room-context.d.ts.map +1 -0
- package/dist/lib/daylight/room-context.js +53 -0
- package/dist/lib/daylight/room-scene.d.ts +54 -0
- package/dist/lib/daylight/room-scene.d.ts.map +1 -0
- package/dist/lib/daylight/room-scene.js +356 -0
- package/dist/lib/daylight/rooms.d.ts +262 -0
- package/dist/lib/daylight/rooms.d.ts.map +1 -0
- package/dist/lib/daylight/rooms.js +1223 -0
- package/dist/lib/daylight/runtime.d.ts +33 -0
- package/dist/lib/daylight/runtime.d.ts.map +1 -0
- package/dist/lib/daylight/runtime.js +42 -0
- package/dist/lib/daylight/sky.d.ts +26 -0
- package/dist/lib/daylight/sky.d.ts.map +1 -0
- package/dist/lib/daylight/sky.js +217 -0
- package/dist/lib/daylight/solar.d.ts +46 -0
- package/dist/lib/daylight/solar.d.ts.map +1 -0
- package/dist/lib/daylight/solar.js +156 -0
- package/dist/lib/device-tier.d.ts +29 -0
- package/dist/lib/device-tier.d.ts.map +1 -0
- package/dist/lib/device-tier.js +71 -0
- package/dist/lib/dispose-object3d.d.ts.map +1 -1
- package/dist/lib/dispose-object3d.js +4 -2
- package/dist/lib/drone-flight.d.ts +44 -0
- package/dist/lib/drone-flight.d.ts.map +1 -0
- package/dist/lib/drone-flight.js +121 -0
- package/dist/lib/editor-highlight.d.ts +16 -0
- package/dist/lib/editor-highlight.d.ts.map +1 -0
- package/dist/lib/editor-highlight.js +33 -0
- package/dist/lib/foundation-materials.d.ts.map +1 -1
- package/dist/lib/foundation-materials.js +2 -4
- package/dist/lib/glb-merge.d.ts +23 -0
- package/dist/lib/glb-merge.d.ts.map +1 -0
- package/dist/lib/glb-merge.js +184 -0
- package/dist/lib/hardware-geometry.d.ts +21 -0
- package/dist/lib/hardware-geometry.d.ts.map +1 -0
- package/dist/lib/hardware-geometry.js +283 -0
- package/dist/lib/layer-pass.d.ts +2 -0
- package/dist/lib/layer-pass.d.ts.map +1 -1
- package/dist/lib/layer-pass.js +20 -0
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +50 -23
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +7 -1
- package/dist/lib/occlusion-culler.d.ts +34 -0
- package/dist/lib/occlusion-culler.d.ts.map +1 -0
- package/dist/lib/occlusion-culler.js +698 -0
- package/dist/lib/post-processing-resources.d.ts +4 -0
- package/dist/lib/post-processing-resources.d.ts.map +1 -1
- package/dist/lib/post-processing-resources.js +5 -0
- package/dist/lib/readback-rows.d.ts +14 -0
- package/dist/lib/readback-rows.d.ts.map +1 -0
- package/dist/lib/readback-rows.js +31 -0
- package/dist/lib/reveal-pose.d.ts.map +1 -1
- package/dist/lib/reveal-pose.js +3 -0
- package/dist/lib/scene-matrices.d.ts +12 -0
- package/dist/lib/scene-matrices.d.ts.map +1 -0
- package/dist/lib/scene-matrices.js +287 -0
- package/dist/lib/scene-pass-mrt.d.ts +5 -2
- package/dist/lib/scene-pass-mrt.d.ts.map +1 -1
- package/dist/lib/scene-pass-mrt.js +7 -2
- package/dist/lib/scene-themes.d.ts +0 -2
- package/dist/lib/scene-themes.d.ts.map +1 -1
- package/dist/lib/scene-themes.js +0 -2
- package/dist/lib/scene-visibility.d.ts +2 -0
- package/dist/lib/scene-visibility.d.ts.map +1 -1
- package/dist/lib/scene-visibility.js +12 -3
- package/dist/lib/site-surfaces.d.ts +1 -8
- package/dist/lib/site-surfaces.d.ts.map +1 -1
- package/dist/lib/site-surfaces.js +0 -19
- package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
- package/dist/lib/snapshot-pipeline.js +24 -40
- package/dist/lib/texture-reference.d.ts.map +1 -1
- package/dist/lib/texture-reference.js +10 -8
- package/dist/lib/underground-ambiance.d.ts +0 -2
- package/dist/lib/underground-ambiance.d.ts.map +1 -1
- package/dist/lib/underground-ambiance.js +0 -2
- package/dist/store/use-item-light-pool.d.ts +3 -6
- package/dist/store/use-item-light-pool.d.ts.map +1 -1
- package/dist/store/use-item-light-pool.js +12 -0
- package/dist/store/use-viewer.d.ts +72 -15
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +103 -18
- package/dist/systems/ceiling/ceiling-system.d.ts +5 -0
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +11 -1
- package/dist/systems/door/door-system.d.ts.map +1 -1
- package/dist/systems/door/door-system.js +501 -145
- package/dist/systems/door/leaf-profile.d.ts +11 -0
- package/dist/systems/door/leaf-profile.d.ts.map +1 -0
- package/dist/systems/door/leaf-profile.js +140 -0
- package/dist/systems/interactive/callout-actions.d.ts +72 -0
- package/dist/systems/interactive/callout-actions.d.ts.map +1 -0
- package/dist/systems/interactive/callout-actions.js +212 -0
- package/dist/systems/interactive/interactive-system.d.ts +5 -1
- package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
- package/dist/systems/interactive/interactive-system.js +44 -121
- package/dist/systems/interactive/opening-settled.d.ts +16 -0
- package/dist/systems/interactive/opening-settled.d.ts.map +1 -0
- package/dist/systems/interactive/opening-settled.js +53 -0
- package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
- package/dist/systems/item-light/item-light-system.js +22 -214
- package/dist/systems/item-light/pooled-lights.d.ts +70 -0
- package/dist/systems/item-light/pooled-lights.d.ts.map +1 -0
- package/dist/systems/item-light/pooled-lights.js +449 -0
- package/dist/systems/level/level-system.d.ts.map +1 -1
- package/dist/systems/level/level-system.js +19 -1
- package/dist/systems/roof/roof-material-slots.d.ts +14 -0
- package/dist/systems/roof/roof-material-slots.d.ts.map +1 -0
- package/dist/systems/roof/roof-material-slots.js +13 -0
- package/dist/systems/roof/roof-materials.d.ts +25 -2
- package/dist/systems/roof/roof-materials.d.ts.map +1 -1
- package/dist/systems/roof/roof-materials.js +85 -26
- package/dist/systems/roof/roof-system.d.ts +34 -1
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +477 -105
- package/dist/systems/wall/opening-casing-geometry.d.ts +14 -0
- package/dist/systems/wall/opening-casing-geometry.d.ts.map +1 -0
- package/dist/systems/wall/opening-casing-geometry.js +102 -0
- package/dist/systems/wall/opening-cutout-geometry.d.ts +9 -0
- package/dist/systems/wall/opening-cutout-geometry.d.ts.map +1 -1
- package/dist/systems/wall/opening-cutout-geometry.js +7 -3
- package/dist/systems/wall/wall-materials.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.js +28 -35
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +34 -19
- package/dist/systems/wall/wall-t-junctions.d.ts +15 -0
- package/dist/systems/wall/wall-t-junctions.d.ts.map +1 -0
- package/dist/systems/wall/wall-t-junctions.js +149 -0
- package/dist/systems/window/window-animation-system.d.ts +3 -12
- package/dist/systems/window/window-animation-system.d.ts.map +1 -1
- package/dist/systems/window/window-animation-system.js +37 -122
- package/dist/systems/window/window-pose.d.ts +31 -0
- package/dist/systems/window/window-pose.d.ts.map +1 -0
- package/dist/systems/window/window-pose.js +152 -0
- package/dist/systems/window/window-roller-shutter.d.ts +8 -0
- package/dist/systems/window/window-roller-shutter.d.ts.map +1 -0
- package/dist/systems/window/window-roller-shutter.js +64 -0
- package/dist/systems/window/window-system.d.ts +2 -11
- package/dist/systems/window/window-system.d.ts.map +1 -1
- package/dist/systems/window/window-system.js +470 -303
- package/package.json +6 -6
- package/dist/systems/interactive/control-widget.d.ts +0 -10
- package/dist/systems/interactive/control-widget.d.ts.map +0 -1
- package/dist/systems/interactive/control-widget.js +0 -35
- package/dist/systems/interactive/procedural-controls.d.ts +0 -13
- package/dist/systems/interactive/procedural-controls.d.ts.map +0 -1
- package/dist/systems/interactive/procedural-controls.js +0 -17
package/dist/index.js
CHANGED
|
@@ -10,8 +10,12 @@ export { ErrorBoundary } from './components/error-boundary';
|
|
|
10
10
|
// `@pascal-app/nodes/<kind>/renderer.tsx` and are loaded by the registry
|
|
11
11
|
// — no per-kind re-exports needed.
|
|
12
12
|
export { NodeRenderer } from './components/renderers/node-renderer';
|
|
13
|
+
// The generic renderer of a kind that ships `def.geometry`, for a kind's renderer that draws
|
|
14
|
+
// something beside its built group.
|
|
15
|
+
export { ParametricNodeRenderer } from './components/renderers/parametric-node-renderer';
|
|
13
16
|
export { default as Viewer, pendingSceneBuildCount, } from './components/viewer';
|
|
14
17
|
export { default as BVHEcctrl, } from './components/viewer/bvh-ecctrl';
|
|
18
|
+
export { DroneController, } from './components/viewer/drone-controller';
|
|
15
19
|
export { buildGlbInteractiveItems, GlbInteractive, } from './components/viewer/glb-interactive';
|
|
16
20
|
export { buildGlbReferenceNodes, buildGlbReplaceNodes, } from './components/viewer/glb-reference-nodes';
|
|
17
21
|
export { GlbScene, resolveGlbPick, } from './components/viewer/glb-scene';
|
|
@@ -20,6 +24,7 @@ export { DEFAULT_HOVER_STYLES, SSGI_PARAMS, } from './components/viewer/post-pro
|
|
|
20
24
|
export { SceneAtmosphere, useSceneAtmosphere, } from './components/viewer/scene-atmosphere';
|
|
21
25
|
export { SceneEnvironment } from './components/viewer/scene-environment';
|
|
22
26
|
export { claimSceneGround, SceneGroundReplacement, useSceneGroundReplacement, } from './components/viewer/scene-ground-replacement';
|
|
27
|
+
export { SelectionCallout, } from './components/viewer/selection-callout';
|
|
23
28
|
export { applyWalkthroughCameraClipping } from './components/viewer/viewer-camera';
|
|
24
29
|
export { isViewerPresentationTextureBorrowed, markViewerPresentationTextureBorrowed, registerViewerPresentation, ViewerPresentations, viewerPresentationRegistry, } from './components/viewer/viewer-presentations';
|
|
25
30
|
export { useAssetUrl } from './hooks/use-asset-url';
|
|
@@ -33,7 +38,14 @@ export { applyWorldScaleBoxUVs } from './lib/box-uv';
|
|
|
33
38
|
// geometry subtracts pieces against their host. Lives in viewer
|
|
34
39
|
// because three-bvh-csg / three-mesh-bvh are viewer-only deps.
|
|
35
40
|
export { ADDITION, Brush, computeGeometryBoundsTree, csgEvaluator, csgGeometry, csgMaterials, Evaluator, ensureRenderableGeometryAttributes, INTERSECTION, prepareBrushForCSG, SUBTRACTION, } from './lib/csg-utils';
|
|
41
|
+
export { createDaylightGroundMaterial, DAYLIGHT_GROUND, DAYLIGHT_PARCEL, daylightGroundColor, } from './lib/daylight/ground';
|
|
42
|
+
export { requestDeviceLocation, resolveLocation, } from './lib/daylight/location';
|
|
43
|
+
export { isDaylightAtmosphere } from './lib/daylight/look';
|
|
44
|
+
export { WEATHER_COVER } from './lib/daylight/sky';
|
|
45
|
+
export { presetInstant, skyPhase, solarClockInstant, solarClockMinutes, solarPosition, sunEvents, } from './lib/daylight/solar';
|
|
36
46
|
export { disposeObject3DResources } from './lib/dispose-object3d';
|
|
47
|
+
export { createDroneInput, DRONE_SLOW_MULTIPLIER, seedDroneLook, stepDroneFlight, turnFirstPersonLook, } from './lib/drone-flight';
|
|
48
|
+
export { markHighlight, tintEmissive } from './lib/editor-highlight';
|
|
37
49
|
export { BLOCK_MASONRY, concreteMaterial, masonryMaterial, STRUCTURE_COLORS, } from './lib/foundation-materials';
|
|
38
50
|
export { preserveGltfUnlit } from './lib/gltf-unlit';
|
|
39
51
|
export { PERF_OVERLAY_ENABLED } from './lib/gpu-perf';
|
|
@@ -61,16 +73,16 @@ export { createSceneSupportHeightSampler } from './lib/scene-support-height';
|
|
|
61
73
|
export { getSceneTheme, SCENE_THEME_IDS, SCENE_THEMES, } from './lib/scene-themes';
|
|
62
74
|
export { hideFromScene, showInScene, temporarilyShowPresentation, temporarilyShowShadowOnly, } from './lib/scene-visibility';
|
|
63
75
|
export { SCRIPTED_MODEL_FLAG } from './lib/scripted-opening';
|
|
64
|
-
export {
|
|
76
|
+
export { SITE_GROUND, siteGround, siteSurfaces, temporarilyVeilGround, } from './lib/site-surfaces';
|
|
65
77
|
export { createPlainSnapshotPipeline, createSnapshotPipeline, SNAPSHOT_MAX_EDGE, SNAPSHOT_MIME, SNAPSHOT_QUALITY, THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH, } from './lib/snapshot-pipeline';
|
|
66
78
|
export { buildTerrainPerimeterFillGeometry, } from './lib/terrain-perimeter-fill';
|
|
67
79
|
export { getPascalTextureRef, stampPascalTextureRef, textureMapForSlot, } from './lib/texture-reference';
|
|
68
80
|
export { packNormalToRGB, unpackRGBToNormal } from './lib/tsl-compat';
|
|
69
|
-
export { AMBIANCE_SECONDS, ambianceNow, ambianceTarget, easeAmbiance, eyeUnderTheGround, FADE_SECONDS, groundHoleOpenNode, groundHoleOpenNow, stepAmbianceProgress, temporarilyWithoutAmbiance, UNDERGROUND_RIM,
|
|
81
|
+
export { AMBIANCE_SECONDS, ambianceNow, ambianceTarget, easeAmbiance, eyeUnderTheGround, FADE_SECONDS, groundHoleOpenNode, groundHoleOpenNow, stepAmbianceProgress, temporarilyWithoutAmbiance, UNDERGROUND_RIM, undergroundAmbianceNode, } from './lib/underground-ambiance';
|
|
70
82
|
export { createZoneShape, createZoneWallGeometry } from './lib/zone-geometry';
|
|
71
83
|
export { catalogLightSource, useItemLightPool } from './store/use-item-light-pool';
|
|
72
|
-
export {
|
|
73
|
-
export { CEILING_REGION_MESH, CeilingSystem, } from './systems/ceiling/ceiling-system';
|
|
84
|
+
export { applyCountryUnitDefault, DEFAULT_UNDERGROUND_LOOK, default as useViewer, groundVeiled, siteGroundShown, } from './store/use-viewer';
|
|
85
|
+
export { CEILING_CAP_MESH, CEILING_REGION_MESH, CeilingSystem, } from './systems/ceiling/ceiling-system';
|
|
74
86
|
export { createColumnBoxGeometry, createColumnCylinderGeometry, createColumnSphereGeometry, createColumnTorusGeometry, } from './systems/column/column-geometry';
|
|
75
87
|
export { ConstructionReveal, emitRevealPuff, getRetractTurn, getRevealPlanSpeed, getRevealPlanState, getRevealTurn, isNodeRevealing, isRevealAssembling, retractNodes, revealChangedNodeIds, revealClockMs, revealMotionOff, seatLiftedNow, setRevealPreroll, startConstructionReveal, subscribeRevealAssembling, subscribeRevealEvents, subscribeRevealPhases, subscribeRevealTicks, useRevealPending, useRevealPlanActive, useRevealWaiting, } from './systems/construction-reveal/construction-reveal';
|
|
76
88
|
export { DoorAnimationSystem } from './systems/door/door-animation-system';
|
|
@@ -83,20 +95,23 @@ export { ElevatorInteractionSystem } from './systems/elevator/elevator-interacti
|
|
|
83
95
|
export { FloorElevationSystem } from './systems/floor-elevation/floor-elevation-system';
|
|
84
96
|
export { GuideSystem } from './systems/guide/guide-system';
|
|
85
97
|
export { InteractiveSystem } from './systems/interactive/interactive-system';
|
|
98
|
+
export { openingSettled, proceduralSettled } from './systems/interactive/opening-settled';
|
|
86
99
|
export { ScriptedClips, useClipActions, } from './systems/interactive/scripted-clips';
|
|
87
100
|
// Item systems for the registry-driven item definition. ItemSystem
|
|
88
101
|
// applies attachTo-driven transforms each frame; ItemLightSystem
|
|
89
102
|
// manages item-mounted light sources.
|
|
90
103
|
export { ItemSystem } from './systems/item/item-system';
|
|
91
104
|
export { ItemLightSystem } from './systems/item-light/item-light-system';
|
|
105
|
+
export { itemLightsForCapture } from './systems/item-light/pooled-lights';
|
|
92
106
|
export { LevelSystem } from './systems/level/level-system';
|
|
93
107
|
export { EXPLODED_GAP, getLevelPresentationY, presentLevelsForCapture, snapLevelsToTruePositions, } from './systems/level/level-utils';
|
|
94
|
-
export {
|
|
108
|
+
export { ROOF_GABLE_LEFT_MATERIAL_INDEX, ROOF_GABLE_RIGHT_MATERIAL_INDEX, ROOF_HEEL_MATERIAL_INDEX, ROOF_RENDER_MATERIAL_COUNT, } from './systems/roof/roof-material-slots';
|
|
109
|
+
export { getRoofMaterialArray, levelWallCladdingRef, levelWallFaceRef, } from './systems/roof/roof-materials';
|
|
95
110
|
// Generic roof-segment primitives. Kinds that compose CSG against
|
|
96
111
|
// the roof shell (chimney's self-trim, dormer's virtual-segment cut)
|
|
97
112
|
// read these through the public surface. No kind-specific helpers
|
|
98
113
|
// belong here — those live in `@pascal-app/nodes/<kind>/`.
|
|
99
|
-
export { clipDirectRoofGeometryAgainstSiblings, clipGeometryBySegmentTrim, generateRoofSegmentGeometry, getPendingRoofMergeCount, getRoofOuterSurfaceFrameAtPoint, getRoofSegmentBrushes, mapRoofGroupMaterialIndex, ROOF_MATERIAL_SLOT_COUNT, RoofSystem, remapRoofShellFaces, roofCsgDummyMats, } from './systems/roof/roof-system';
|
|
114
|
+
export { clipDirectRoofGeometryAgainstSiblings, clipGeometryBySegmentTrim, generateRoofSegmentGeometry, getPendingRoofMergeCount, getRoofOuterSurfaceFrameAtPoint, getRoofSegmentBrushes, mapRoofGroupMaterialIndex, ROOF_MATERIAL_SLOT_COUNT, RoofSystem, remapRoofShellFaces, roofCsgDummyMats, splitRoofWallBandFaces, } from './systems/roof/roof-system';
|
|
100
115
|
export { ScanSystem } from './systems/scan/scan-system';
|
|
101
116
|
// Pure slab geometry generator — composed into the registry-driven slab
|
|
102
117
|
// definition's `def.geometry` in `@pascal-app/nodes`.
|
|
@@ -116,7 +131,8 @@ export { getMaterialsForWall, getVisibleWallMaterials, } from './systems/wall/wa
|
|
|
116
131
|
// 800+ lines of CSG / mitering logic during Phase 3. These exports are
|
|
117
132
|
// removed in Phase 6 when the legacy mount points are deleted.
|
|
118
133
|
export { drainRebuiltWalls, generateExtrudedWall, getPendingWallRebuildCount, isWallInitialBuildActive, runWallBuildFrame, WallSystem, } from './systems/wall/wall-system';
|
|
119
|
-
export { poseWindowMovingParts, WindowAnimationSystem, } from './systems/window/window-animation-system';
|
|
134
|
+
export { advanceWindowAnimations, poseWindowMovingParts, WindowAnimationSystem, } from './systems/window/window-animation-system';
|
|
135
|
+
export { restoreWindowRollerShutter } from './systems/window/window-roller-shutter';
|
|
120
136
|
export { buildWindowPreviewMesh, WindowSystem } from './systems/window/window-system';
|
|
121
137
|
export { ZoneSystem } from './systems/zone/zone-system';
|
|
122
138
|
export { useImmersiveXRPresentation } from './xr/presentation-context';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { MeshLambertNodeMaterial, MeshStandardNodeMaterial } from 'three/webgpu';
|
|
2
|
+
/** Neutral ground of the colored appearance, and the slightly fresher parcel inside the site. */
|
|
3
|
+
export declare const DAYLIGHT_GROUND = "#a1a1a1";
|
|
4
|
+
export declare const DAYLIGHT_PARCEL = "#afaeaa";
|
|
5
|
+
/**
|
|
6
|
+
* The ground around the parcel: faint squares that stay a few pixels wide at every distance (a
|
|
7
|
+
* mip-like ladder of square sizes, so no shimmer towards the horizon) over long diagonal bands.
|
|
8
|
+
* World-anchored; the horizon blend comes from the atmosphere's fog.
|
|
9
|
+
*/
|
|
10
|
+
export declare function daylightGroundColor(base?: any): any;
|
|
11
|
+
/**
|
|
12
|
+
* A matte daylight ground material: Standard (lit by the sky environment) in rendered shading,
|
|
13
|
+
* Lambert in solid shading, where every surface is Lambert and the sky comes as a hemisphere light.
|
|
14
|
+
* With `horizon` (the atmosphere's horizon radiance), the lit ground blends into the sky with
|
|
15
|
+
* horizontal distance (250 m → 2.6 km) — on the lit output, so the lighting can't band it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createDaylightGroundMaterial(solid: boolean, options?: {
|
|
18
|
+
color?: string;
|
|
19
|
+
horizon?: (direction: any) => any;
|
|
20
|
+
}): MeshLambertNodeMaterial | MeshStandardNodeMaterial;
|
|
21
|
+
//# sourceMappingURL=ground.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ground.d.ts","sourceRoot":"","sources":["../../../src/lib/daylight/ground.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAEhF,iGAAiG;AACjG,eAAO,MAAM,eAAe,YAAY,CAAA;AACxC,eAAO,MAAM,eAAe,YAAY,CAAA;AAKxC;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,GAA4B,GAAG,GAAG,CAc3E;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,OAAO,EACd,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,GAAG,CAAA;CAAO,GAClE,uBAAuB,GAAG,wBAAwB,CAgBpD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { cameraPosition, clamp, color, exp2, floor, fract, fwidth, length, max, mix, normalize, output, positionWorld, sin, smoothstep, vec2, vec4, } from 'three/tsl';
|
|
2
|
+
import { MeshLambertNodeMaterial, MeshStandardNodeMaterial } from 'three/webgpu';
|
|
3
|
+
/** Neutral ground of the colored appearance, and the slightly fresher parcel inside the site. */
|
|
4
|
+
export const DAYLIGHT_GROUND = '#a1a1a1';
|
|
5
|
+
export const DAYLIGHT_PARCEL = '#afaeaa';
|
|
6
|
+
/** Horizontal distance (m) over which the ground fades into the horizon sky. */
|
|
7
|
+
const HORIZON_FADE_NEAR = 250;
|
|
8
|
+
const HORIZON_FADE_FAR = 2600;
|
|
9
|
+
/**
|
|
10
|
+
* The ground around the parcel: faint squares that stay a few pixels wide at every distance (a
|
|
11
|
+
* mip-like ladder of square sizes, so no shimmer towards the horizon) over long diagonal bands.
|
|
12
|
+
* World-anchored; the horizon blend comes from the atmosphere's fog.
|
|
13
|
+
*/
|
|
14
|
+
export function daylightGroundColor(base = color(DAYLIGHT_GROUND)) {
|
|
15
|
+
const p = positionWorld.xz;
|
|
16
|
+
const texel = max(fwidth(p.x), fwidth(p.y));
|
|
17
|
+
const lod = clamp(texel.mul(1.7).mul(4).max(1e-6).log2(), 0, 8);
|
|
18
|
+
const l0 = lod.floor();
|
|
19
|
+
const squares = (level) => {
|
|
20
|
+
const scale = vec2(1.7).div(exp2(level));
|
|
21
|
+
// fract(sin) hash: three's `hash` casts to uint, which collapses every negative cell to one value.
|
|
22
|
+
const cell = floor(p.mul(scale)).add(vec2(level.mul(37), level.mul(11)));
|
|
23
|
+
return fract(sin(cell.dot(vec2(12.9898, 78.233))).mul(43758.5453)).sub(0.5);
|
|
24
|
+
};
|
|
25
|
+
const noise = mix(squares(l0), squares(l0.add(1)), lod.sub(l0)).mul(0.06);
|
|
26
|
+
const bands = sin(p.x.mul(0.31).add(p.y.mul(0.17))).mul(0.02);
|
|
27
|
+
return base.mul(noise.add(bands).add(1));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A matte daylight ground material: Standard (lit by the sky environment) in rendered shading,
|
|
31
|
+
* Lambert in solid shading, where every surface is Lambert and the sky comes as a hemisphere light.
|
|
32
|
+
* With `horizon` (the atmosphere's horizon radiance), the lit ground blends into the sky with
|
|
33
|
+
* horizontal distance (250 m → 2.6 km) — on the lit output, so the lighting can't band it.
|
|
34
|
+
*/
|
|
35
|
+
export function createDaylightGroundMaterial(solid, options = {}) {
|
|
36
|
+
const material = solid
|
|
37
|
+
? new MeshLambertNodeMaterial()
|
|
38
|
+
: new MeshStandardNodeMaterial({ roughness: 0.95, metalness: 0 });
|
|
39
|
+
// The grounds skip the room system (the dilated room map would light a strip of lawn); they
|
|
40
|
+
// still receive the window spill and exterior lamps at night.
|
|
41
|
+
material.userData.noRooms = true;
|
|
42
|
+
if (options.color)
|
|
43
|
+
material.color.set(options.color);
|
|
44
|
+
else
|
|
45
|
+
material.colorNode = daylightGroundColor();
|
|
46
|
+
if (options.horizon) {
|
|
47
|
+
const d = positionWorld.sub(cameraPosition);
|
|
48
|
+
const fade = smoothstep(HORIZON_FADE_NEAR, HORIZON_FADE_FAR, length(d.xz));
|
|
49
|
+
material.fog = false;
|
|
50
|
+
material.outputNode = vec4(mix(output.rgb, options.horizon(normalize(d)), fade), output.a);
|
|
51
|
+
}
|
|
52
|
+
return material;
|
|
53
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the sun is computed for. In order: the site's own geocoded point, a device location the
|
|
3
|
+
* user granted (cached by the host), a coarse guess from the browser's timezone, a mid-latitude
|
|
4
|
+
* default. Never prompts by itself: requesting the device location is a user action.
|
|
5
|
+
*/
|
|
6
|
+
export type LatLng = {
|
|
7
|
+
lat: number;
|
|
8
|
+
lng: number;
|
|
9
|
+
};
|
|
10
|
+
export type LocationSource = 'site' | 'device' | 'timezone' | 'default';
|
|
11
|
+
type SiteLike = {
|
|
12
|
+
parcel?: {
|
|
13
|
+
originLngLat?: readonly [number, number] | null;
|
|
14
|
+
} | null;
|
|
15
|
+
dossier?: {
|
|
16
|
+
point?: {
|
|
17
|
+
lat?: number;
|
|
18
|
+
lng?: number;
|
|
19
|
+
} | null;
|
|
20
|
+
} | null;
|
|
21
|
+
};
|
|
22
|
+
export declare function siteLocation(site: SiteLike | null | undefined): LatLng | null;
|
|
23
|
+
export declare const DEFAULT_LOCATION: LatLng;
|
|
24
|
+
export declare function timezoneLocation(timeZone?: string): LatLng | null;
|
|
25
|
+
export declare function resolveLocation(site: SiteLike | null | undefined, device: LatLng | null | undefined): {
|
|
26
|
+
location: LatLng;
|
|
27
|
+
source: LocationSource;
|
|
28
|
+
};
|
|
29
|
+
/** Ask the browser for the device position (call from a user gesture). */
|
|
30
|
+
export declare function requestDeviceLocation(): Promise<LatLng>;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=location.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../../src/lib/daylight/location.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AACjD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAA;AAEvE,KAAK,QAAQ,GAAG;IACd,MAAM,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;IACnE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CACnE,CAAA;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQ7E;AA6BD,eAAO,MAAM,gBAAgB,EAAE,MAAmC,CAAA;AAElE,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUjE;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,EACjC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAChC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAO9C;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC,CAYvD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the sun is computed for. In order: the site's own geocoded point, a device location the
|
|
3
|
+
* user granted (cached by the host), a coarse guess from the browser's timezone, a mid-latitude
|
|
4
|
+
* default. Never prompts by itself: requesting the device location is a user action.
|
|
5
|
+
*/
|
|
6
|
+
export function siteLocation(site) {
|
|
7
|
+
const origin = site?.parcel?.originLngLat;
|
|
8
|
+
if (origin && Number.isFinite(origin[0]) && Number.isFinite(origin[1]))
|
|
9
|
+
return { lat: origin[1], lng: origin[0] };
|
|
10
|
+
const point = site?.dossier?.point;
|
|
11
|
+
if (point && Number.isFinite(point.lat) && Number.isFinite(point.lng))
|
|
12
|
+
return { lat: point.lat, lng: point.lng };
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
/** A representative city per common IANA zone — only to pick a plausible latitude/longitude. */
|
|
16
|
+
const ZONE_POINTS = {
|
|
17
|
+
'America/New_York': { lat: 40.71, lng: -74.0 },
|
|
18
|
+
'America/Chicago': { lat: 41.88, lng: -87.63 },
|
|
19
|
+
'America/Denver': { lat: 39.74, lng: -104.99 },
|
|
20
|
+
'America/Phoenix': { lat: 33.45, lng: -112.07 },
|
|
21
|
+
'America/Los_Angeles': { lat: 34.05, lng: -118.24 },
|
|
22
|
+
'America/Toronto': { lat: 43.65, lng: -79.38 },
|
|
23
|
+
'America/Vancouver': { lat: 49.28, lng: -123.12 },
|
|
24
|
+
'America/Mexico_City': { lat: 19.43, lng: -99.13 },
|
|
25
|
+
'America/Sao_Paulo': { lat: -23.55, lng: -46.63 },
|
|
26
|
+
'Europe/London': { lat: 51.51, lng: -0.13 },
|
|
27
|
+
'Europe/Paris': { lat: 48.86, lng: 2.35 },
|
|
28
|
+
'Europe/Berlin': { lat: 52.52, lng: 13.4 },
|
|
29
|
+
'Europe/Madrid': { lat: 40.42, lng: -3.7 },
|
|
30
|
+
'Europe/Rome': { lat: 41.9, lng: 12.5 },
|
|
31
|
+
'Europe/Amsterdam': { lat: 52.37, lng: 4.9 },
|
|
32
|
+
'Europe/Stockholm': { lat: 59.33, lng: 18.07 },
|
|
33
|
+
'Asia/Tokyo': { lat: 35.68, lng: 139.69 },
|
|
34
|
+
'Asia/Shanghai': { lat: 31.23, lng: 121.47 },
|
|
35
|
+
'Asia/Singapore': { lat: 1.35, lng: 103.82 },
|
|
36
|
+
'Asia/Dubai': { lat: 25.2, lng: 55.27 },
|
|
37
|
+
'Asia/Kolkata': { lat: 19.08, lng: 72.88 },
|
|
38
|
+
'Australia/Sydney': { lat: -33.87, lng: 151.21 },
|
|
39
|
+
'Pacific/Auckland': { lat: -36.85, lng: 174.76 },
|
|
40
|
+
};
|
|
41
|
+
export const DEFAULT_LOCATION = { lat: 40.71, lng: -74.0 };
|
|
42
|
+
export function timezoneLocation(timeZone) {
|
|
43
|
+
let zone = timeZone;
|
|
44
|
+
if (!zone) {
|
|
45
|
+
try {
|
|
46
|
+
zone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return (zone && ZONE_POINTS[zone]) || null;
|
|
53
|
+
}
|
|
54
|
+
export function resolveLocation(site, device) {
|
|
55
|
+
const fromSite = siteLocation(site);
|
|
56
|
+
if (fromSite)
|
|
57
|
+
return { location: fromSite, source: 'site' };
|
|
58
|
+
if (device)
|
|
59
|
+
return { location: device, source: 'device' };
|
|
60
|
+
const fromZone = timezoneLocation();
|
|
61
|
+
if (fromZone)
|
|
62
|
+
return { location: fromZone, source: 'timezone' };
|
|
63
|
+
return { location: DEFAULT_LOCATION, source: 'default' };
|
|
64
|
+
}
|
|
65
|
+
/** Ask the browser for the device position (call from a user gesture). */
|
|
66
|
+
export function requestDeviceLocation() {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
if (typeof navigator === 'undefined' || !navigator.geolocation) {
|
|
69
|
+
reject(new Error('Geolocation is unavailable'));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
navigator.geolocation.getCurrentPosition((position) => resolve({ lat: position.coords.latitude, lng: position.coords.longitude }), (error) => reject(error), { enableHighAccuracy: false, maximumAge: 24 * 3_600_000, timeout: 10_000 });
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Vector3 } from 'three';
|
|
2
|
+
import type { SceneAtmosphereSource } from '../../components/viewer/scene-atmosphere';
|
|
3
|
+
/** Daylight-specific outputs the post-processing reads (white balance). */
|
|
4
|
+
export type DaylightAtmosphereSource = SceneAtmosphereSource & {
|
|
5
|
+
/** Linear RGB gains: eye-like partial chromatic adaptation to the current illuminant. */
|
|
6
|
+
whiteBalance: Vector3;
|
|
7
|
+
/** The key light's shadow (the sun, or the moon at night): map size per quality tier. */
|
|
8
|
+
shadow: {
|
|
9
|
+
mapSize: number;
|
|
10
|
+
bias: number;
|
|
11
|
+
normalBias: number;
|
|
12
|
+
radius: number;
|
|
13
|
+
};
|
|
14
|
+
/** Sun elevation in degrees (negative at night). */
|
|
15
|
+
elevation: number;
|
|
16
|
+
};
|
|
17
|
+
export declare function isDaylightAtmosphere(source: unknown): source is DaylightAtmosphereSource;
|
|
18
|
+
/** The colored appearance's grade, vignette and bloom (viewport and snapshots alike). */
|
|
19
|
+
export declare const DAYLIGHT_GRADE: {
|
|
20
|
+
contrast: number;
|
|
21
|
+
saturation: number;
|
|
22
|
+
vignette: number;
|
|
23
|
+
};
|
|
24
|
+
export declare const DAYLIGHT_BLOOM: {
|
|
25
|
+
strength: number;
|
|
26
|
+
radius: number;
|
|
27
|
+
softKnee: number;
|
|
28
|
+
};
|
|
29
|
+
/** The daylight look ignores the scene theme: its ink edges are always the light-backdrop ink. */
|
|
30
|
+
export declare const DAYLIGHT_INK_BACKDROP = "#d4d8dc";
|
|
31
|
+
/** Scene-referred daylight grade: white balance, contrast around mid-grey, saturation. */
|
|
32
|
+
export declare function daylightGradeRgb(rgb: any, whiteBalance: any): any;
|
|
33
|
+
//# sourceMappingURL=look.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"look.d.ts","sourceRoot":"","sources":["../../../src/lib/daylight/look.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAEpC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAA;AAErF,2EAA2E;AAC3E,MAAM,MAAM,wBAAwB,GAAG,qBAAqB,GAAG;IAC7D,yFAAyF;IACzF,YAAY,EAAE,OAAO,CAAA;IACrB,yFAAyF;IACzF,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7E,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,wBAAwB,CAExF;AAED,yFAAyF;AACzF,eAAO,MAAM,cAAc;IAAK,QAAQ;IAAQ,UAAU;IAAQ,QAAQ;CAAQ,CAAA;AAClF,eAAO,MAAM,cAAc;IAAK,QAAQ;IAAQ,MAAM;IAAQ,QAAQ;CAAO,CAAA;AAC7E,kGAAkG;AAClG,eAAO,MAAM,qBAAqB,YAAY,CAAA;AAE9C,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,GAAG,GAAG,CAKjE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { saturation, vec3 } from 'three/tsl';
|
|
2
|
+
export function isDaylightAtmosphere(source) {
|
|
3
|
+
return Boolean(source && source.whiteBalance);
|
|
4
|
+
}
|
|
5
|
+
/** The colored appearance's grade, vignette and bloom (viewport and snapshots alike). */
|
|
6
|
+
export const DAYLIGHT_GRADE = { contrast: 1.06, saturation: 1.06, vignette: 0.12 };
|
|
7
|
+
export const DAYLIGHT_BLOOM = { strength: 0.12, radius: 0.18, softKnee: 0.4 };
|
|
8
|
+
/** The daylight look ignores the scene theme: its ink edges are always the light-backdrop ink. */
|
|
9
|
+
export const DAYLIGHT_INK_BACKDROP = '#d4d8dc';
|
|
10
|
+
/** Scene-referred daylight grade: white balance, contrast around mid-grey, saturation. */
|
|
11
|
+
export function daylightGradeRgb(rgb, whiteBalance) {
|
|
12
|
+
return saturation(rgb.max(0).mul(whiteBalance).div(0.18).pow(vec3(DAYLIGHT_GRADE.contrast)).mul(0.18), DAYLIGHT_GRADE.saturation);
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"material-hooks.d.ts","sourceRoot":"","sources":["../../../src/lib/daylight/material-hooks.ts"],"names":[],"mappings":"AAmIA,wBAAgB,4BAA4B,IAAI,IAAI,CA4FnD"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { abs, cameraPosition, clamp, diffuseColor, diffuseRoughness, dot, float, hash, length, materialEmissive, max, mix, normalize, normalWorld, positionWorld, pow, smoothstep, vec3, vec4, } from 'three/tsl';
|
|
2
|
+
import { MeshBasicNodeMaterial, PhysicalLightingModel, MeshStandardNodeMaterial as StandardNodeMaterial, } from 'three/webgpu';
|
|
3
|
+
import { isHighlight } from '../editor-highlight';
|
|
4
|
+
import { SCENE_LAYER } from '../layers';
|
|
5
|
+
import { daylightRooms } from './rooms';
|
|
6
|
+
import { daylightUniforms, isDaylightRenderer } from './runtime';
|
|
7
|
+
/** sRGB 40 / 243 in linear: lo + c·(hi − lo). */
|
|
8
|
+
const ALBEDO_LO = 0.0212;
|
|
9
|
+
const ALBEDO_HI = 0.896;
|
|
10
|
+
function hooked(material, builder) {
|
|
11
|
+
// Physical materials own their lighting model; glass and other transparent surfaces keep theirs.
|
|
12
|
+
return (!material.isMeshPhysicalNodeMaterial &&
|
|
13
|
+
!material.transparent &&
|
|
14
|
+
isDaylightRenderer(builder.renderer));
|
|
15
|
+
}
|
|
16
|
+
function matte(material) {
|
|
17
|
+
return (material.metalness ?? 0) < 0.2 && (material.roughness ?? 1) >= 0.55;
|
|
18
|
+
}
|
|
19
|
+
function emitter(material) {
|
|
20
|
+
return (!material.emissiveNode &&
|
|
21
|
+
!isHighlight(material) &&
|
|
22
|
+
!!material.emissive &&
|
|
23
|
+
material.emissive.getHex() !== 0 &&
|
|
24
|
+
material.emissiveIntensity > 0);
|
|
25
|
+
}
|
|
26
|
+
/** Window/door glass (its slot, live or baked), item glass by material name, or flagged glass. */
|
|
27
|
+
function glass(material, object) {
|
|
28
|
+
if (!material.transparent || material.isMeshPhysicalNodeMaterial)
|
|
29
|
+
return false;
|
|
30
|
+
return (object?.userData?.slotId === 'glass' ||
|
|
31
|
+
material.userData.isGlass === true ||
|
|
32
|
+
/glass/i.test(material.name));
|
|
33
|
+
}
|
|
34
|
+
/** The enhanced viewer's glass: tint, near-mirror roughness, distance/Fresnel opacity, night glow. */
|
|
35
|
+
function tunedGlassNodes() {
|
|
36
|
+
const u = daylightUniforms;
|
|
37
|
+
const V = normalize(cameraPosition.sub(positionWorld));
|
|
38
|
+
const N = normalWorld;
|
|
39
|
+
const fresnel = pow(float(1).sub(abs(dot(N, V))), 5);
|
|
40
|
+
// /next trick: glass gets more opaque + reflective with distance and grazing angle, so façades
|
|
41
|
+
// read as glazing from the street while interiors stay visible up close.
|
|
42
|
+
const far = smoothstep(6, 30, length(cameraPosition.sub(positionWorld)));
|
|
43
|
+
// Night: warm radiance from the lit room behind the pane (strongest from outside / far away).
|
|
44
|
+
const behind = daylightRooms.roomAtNode(positionWorld.sub(N.mul(0.35)));
|
|
45
|
+
const front = daylightRooms.roomAtNode(positionWorld.add(N.mul(0.35)));
|
|
46
|
+
const room = max(behind, front);
|
|
47
|
+
// Pane tint = the room's actual lamp colour (18% towards white), dark when its lamps are off.
|
|
48
|
+
const lampRad = daylightRooms.roomGlowNode(room);
|
|
49
|
+
const tint = mix(lampRad, vec3(lampRad.dot(vec3(0.33))), 0.18);
|
|
50
|
+
// Per-room variation, like a game city: not every window equally bright.
|
|
51
|
+
const variation = mix(0.55, 1.0, hash(float(room).add(7.13)));
|
|
52
|
+
const strength = u.windowGlow
|
|
53
|
+
.mul(u.glowComp)
|
|
54
|
+
.mul(float(1).add(u.windowEmit.mul(1.8)))
|
|
55
|
+
.mul(variation)
|
|
56
|
+
.mul(mix(1.0, 0.35, fresnel))
|
|
57
|
+
.mul(mix(0.25, 1.0, u.cameraOutside))
|
|
58
|
+
.mul(mix(0.4, 1, far));
|
|
59
|
+
return {
|
|
60
|
+
colorNode: u.glassTint,
|
|
61
|
+
roughnessNode: float(0.04),
|
|
62
|
+
metalnessNode: float(0),
|
|
63
|
+
opacityNode: clamp(u.glassOpacity.add(far.mul(0.18)).add(fresnel.mul(0.7)), 0, 0.72),
|
|
64
|
+
emissiveNode: tint.mul(strength).mul(0.9),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
let installed = false;
|
|
68
|
+
export function installDaylightMaterialHooks() {
|
|
69
|
+
if (installed)
|
|
70
|
+
return;
|
|
71
|
+
installed = true;
|
|
72
|
+
const proto = StandardNodeMaterial.prototype;
|
|
73
|
+
const setup = proto.setup;
|
|
74
|
+
proto.setup = function (builder) {
|
|
75
|
+
if (!isDaylightRenderer(builder.renderer) || !glass(this, builder.object))
|
|
76
|
+
return setup.call(this, builder);
|
|
77
|
+
// Build-time only: the tuned glass joins this compile without touching the material.
|
|
78
|
+
const own = this;
|
|
79
|
+
const nodes = tunedGlassNodes();
|
|
80
|
+
const saved = Object.fromEntries(Object.keys(nodes).map((key) => [key, own[key]]));
|
|
81
|
+
Object.assign(own, nodes);
|
|
82
|
+
try {
|
|
83
|
+
return setup.call(this, builder);
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
Object.assign(own, saved);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const setupDiffuseColor = proto.setupDiffuseColor;
|
|
90
|
+
proto.setupDiffuseColor = function (builder) {
|
|
91
|
+
setupDiffuseColor.call(this, builder);
|
|
92
|
+
if (!hooked(this, builder))
|
|
93
|
+
return;
|
|
94
|
+
const rgb = diffuseColor.rgb;
|
|
95
|
+
const clamped = rgb.mul(ALBEDO_HI - ALBEDO_LO).add(ALBEDO_LO);
|
|
96
|
+
diffuseColor.assign(vec4(mix(rgb, clamped, daylightUniforms.albedoClamp), diffuseColor.a));
|
|
97
|
+
};
|
|
98
|
+
const setupVariants = proto.setupVariants;
|
|
99
|
+
proto.setupVariants = function (builder) {
|
|
100
|
+
setupVariants.call(this, builder);
|
|
101
|
+
if (hooked(this, builder) && matte(this))
|
|
102
|
+
diffuseRoughness.assign(daylightUniforms.eon);
|
|
103
|
+
};
|
|
104
|
+
const setupLightingModel = proto.setupLightingModel;
|
|
105
|
+
proto.setupLightingModel = function (builder) {
|
|
106
|
+
if (!hooked(this, builder) || !matte(this))
|
|
107
|
+
return setupLightingModel.call(this, builder);
|
|
108
|
+
// The eighth flag enables EON rough diffuse (fed by `diffuseRoughness` above).
|
|
109
|
+
return new PhysicalLightingModel(false, false, false, false, false, false, false, true);
|
|
110
|
+
};
|
|
111
|
+
const setupLighting = proto.setupLighting;
|
|
112
|
+
proto.setupLighting = function (builder) {
|
|
113
|
+
if (hooked(this, builder) && !this.emissiveNode && isHighlight(this)) {
|
|
114
|
+
// Editor highlights: the tint keeps its on-screen strength whatever the exposure.
|
|
115
|
+
this.emissiveNode = materialEmissive.mul(daylightUniforms.emitterExpInv);
|
|
116
|
+
try {
|
|
117
|
+
return setupLighting.call(this, builder);
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
this.emissiveNode = null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!hooked(this, builder) || !emitter(this))
|
|
124
|
+
return setupLighting.call(this, builder);
|
|
125
|
+
// Build-time only: the emission joins this compile without touching the material.
|
|
126
|
+
// Glowing surfaces (screens, signs; lamps get their own materials): brighter at night, kept
|
|
127
|
+
// out of the night exposure lift.
|
|
128
|
+
const u = daylightUniforms;
|
|
129
|
+
this.emissiveNode = materialEmissive.mul(float(1).add(u.lampLevel.mul(u.emissiveBoost).mul(u.glowComp)));
|
|
130
|
+
try {
|
|
131
|
+
return setupLighting.call(this, builder);
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
this.emissiveNode = null;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
// Unlit scene surfaces: undo the metered exposure (zones and editor overlays are compensated in
|
|
138
|
+
// the post-processing, on their own layers; the sky capture is radiance and keeps it).
|
|
139
|
+
const basic = MeshBasicNodeMaterial.prototype;
|
|
140
|
+
const setupBasicLighting = basic.setupLighting;
|
|
141
|
+
basic.setupLighting = function (builder) {
|
|
142
|
+
const light = setupBasicLighting.call(this, builder);
|
|
143
|
+
const object = builder.object;
|
|
144
|
+
if (!isDaylightRenderer(builder.renderer) ||
|
|
145
|
+
this.userData.daylightSky === true ||
|
|
146
|
+
!object?.layers?.isEnabled(SCENE_LAYER))
|
|
147
|
+
return light;
|
|
148
|
+
return light.mul(daylightUniforms.emitterExpInv);
|
|
149
|
+
};
|
|
150
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type N = any;
|
|
2
|
+
/**
|
|
3
|
+
* The daylight look's scene-pass lighting hooks: room light enters the material lighting as
|
|
4
|
+
* indirect irradiance (`getGI`, × albedo, × contact AO), the room enclosure dims the sky IBL
|
|
5
|
+
* (`getAO`), and outside surfaces receive the window spill and exterior lamps at night.
|
|
6
|
+
*
|
|
7
|
+
* Materials flagged `userData.noRooms` (the grounds) skip the room system: the dilated room
|
|
8
|
+
* map reaches ~20 cm past the walls and would light a strip of lawn.
|
|
9
|
+
*/
|
|
10
|
+
export declare function daylightRoomContext(): N;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=room-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-context.d.ts","sourceRoot":"","sources":["../../../src/lib/daylight/room-context.ts"],"names":[],"mappings":"AAaA,KAAK,CAAC,GAAG,GAAG,CAAA;AAKZ;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,CAAC,CAoCvC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { context, diffuseColor, Fn, If, max, normalWorld, positionWorld, uniform, vec3, } from 'three/tsl';
|
|
2
|
+
import { daylightRooms } from './rooms';
|
|
3
|
+
/** Window spill only: receivers darker than this albedo are lit as if they had it (decal-style). */
|
|
4
|
+
const spillAlbedoFloor = uniform(0.35);
|
|
5
|
+
/**
|
|
6
|
+
* The daylight look's scene-pass lighting hooks: room light enters the material lighting as
|
|
7
|
+
* indirect irradiance (`getGI`, × albedo, × contact AO), the room enclosure dims the sky IBL
|
|
8
|
+
* (`getAO`), and outside surfaces receive the window spill and exterior lamps at night.
|
|
9
|
+
*
|
|
10
|
+
* Materials flagged `userData.noRooms` (the grounds) skip the room system: the dilated room
|
|
11
|
+
* map reaches ~20 cm past the walls and would light a strip of lawn.
|
|
12
|
+
*/
|
|
13
|
+
export function daylightRoomContext() {
|
|
14
|
+
const rooms = daylightRooms;
|
|
15
|
+
const roomNode = rooms.lightingNode();
|
|
16
|
+
const enclosure = roomNode.w;
|
|
17
|
+
const outsideMask = rooms.exteriorMaskNode();
|
|
18
|
+
// GI is later × albedo, so near-black paving would swallow the pools: lift dark receivers for
|
|
19
|
+
// the spill term only (like a light decal).
|
|
20
|
+
const lum = diffuseColor.rgb.dot(vec3(0.2126, 0.7152, 0.0722)).max(1e-3);
|
|
21
|
+
const albedoLift = lum.max(spillAlbedoFloor).div(lum);
|
|
22
|
+
const spill = rooms.exteriorSpillNode(positionWorld, normalWorld).mul(albedoLift);
|
|
23
|
+
const exteriorLamps = rooms.exteriorLampsNode(positionWorld, normalWorld);
|
|
24
|
+
// Inside a room the outside terms are masked to nothing anyway: skip their loops there.
|
|
25
|
+
const outsideLight = Fn(() => {
|
|
26
|
+
const light = vec3(0).toVar();
|
|
27
|
+
If(outsideMask.greaterThan(0), () => {
|
|
28
|
+
light.assign(spill.add(exteriorLamps).mul(outsideMask));
|
|
29
|
+
});
|
|
30
|
+
return light;
|
|
31
|
+
})();
|
|
32
|
+
return context({
|
|
33
|
+
getAO: (input, { material }) => {
|
|
34
|
+
if (material.transparent === true)
|
|
35
|
+
return input;
|
|
36
|
+
if (material.userData.noRooms)
|
|
37
|
+
return input;
|
|
38
|
+
return input !== null ? input.mul(enclosure) : enclosure;
|
|
39
|
+
},
|
|
40
|
+
getGI: (input, { material }) => {
|
|
41
|
+
if (material.transparent === true)
|
|
42
|
+
return input;
|
|
43
|
+
// The lighting model multiplies GI by the AO term again: undo it so room light keeps only
|
|
44
|
+
// the contact AO, and outside terms aren't dimmed by an enclosure they don't sit in.
|
|
45
|
+
let gi;
|
|
46
|
+
if (material.userData.noRooms)
|
|
47
|
+
gi = spill.add(exteriorLamps);
|
|
48
|
+
else
|
|
49
|
+
gi = outsideLight.add(roomNode.xyz).div(max(enclosure, 1e-3));
|
|
50
|
+
return input !== null ? input.add(gi) : gi;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type Object3D, Vector3 } from 'three';
|
|
2
|
+
import type { RoomLamp, RoomSceneInput } from './rooms';
|
|
3
|
+
/**
|
|
4
|
+
* Builds the room system's input from a scene: the live parametric graph (scene registry +
|
|
5
|
+
* node data) or a baked artifact (identity `userData` stamped by the GLB export).
|
|
6
|
+
*/
|
|
7
|
+
/** A lamp as the item-light pools see it (live catalog/procedural items and baked items alike). */
|
|
8
|
+
export type LampFeedLight = {
|
|
9
|
+
key: string;
|
|
10
|
+
color: string;
|
|
11
|
+
distance: number;
|
|
12
|
+
/** Fully-on intensity. */
|
|
13
|
+
peak?: number;
|
|
14
|
+
getWorldPosition: (out: Vector3) => boolean;
|
|
15
|
+
/** The lamp's item: its node id (live) or object (baked). */
|
|
16
|
+
nodeId?: string;
|
|
17
|
+
object?: Object3D;
|
|
18
|
+
/** A spotlight's cone (angle in degrees, full cone; softness = penumbra) and its aim. */
|
|
19
|
+
spot?: {
|
|
20
|
+
direction?: readonly [number, number, number];
|
|
21
|
+
angle?: number;
|
|
22
|
+
softness?: number;
|
|
23
|
+
};
|
|
24
|
+
getWorldDirection?: (out: Vector3) => void;
|
|
25
|
+
};
|
|
26
|
+
type LampFeed = {
|
|
27
|
+
lights: () => Iterable<LampFeedLight>;
|
|
28
|
+
intensity: (light: LampFeedLight) => number;
|
|
29
|
+
};
|
|
30
|
+
/** Item-light pools hand their lamps to the room system while the daylight look is active. */
|
|
31
|
+
export declare const lampFeeds: Set<LampFeed>;
|
|
32
|
+
/** Lamps from every registered feed, in the room system's units. */
|
|
33
|
+
export declare function feedLamps(): RoomLamp[];
|
|
34
|
+
/** Current on/off of a fed lamp (by key). */
|
|
35
|
+
export declare function feedLampOn(key: string): boolean | undefined;
|
|
36
|
+
/** The live parametric scene (registry + node data), or null while it has no zones. */
|
|
37
|
+
export declare function liveRoomScene(virtualLampsOn: boolean): RoomSceneInput | null;
|
|
38
|
+
/** Live level objects in the room system's level order (for explode offsets). */
|
|
39
|
+
export declare function liveLevelObjects(): Object3D[];
|
|
40
|
+
/** How open a live door is (0 closed … 1 fully open), the transient state first. */
|
|
41
|
+
export declare function liveDoorOpenness(id: string): number;
|
|
42
|
+
/** A baked artifact's identity tree (levels, zones, covers, walls, openings), or null. */
|
|
43
|
+
export declare function bakedRoomScene(root: Object3D, virtualLampsOn: boolean): RoomSceneInput | null;
|
|
44
|
+
/**
|
|
45
|
+
* Lamp shades and bulbs follow their own lamp (the enhanced viewer's isolated emitters): each
|
|
46
|
+
* lamp's emissive meshes get private materials whose emission follows that lamp's switch. A light
|
|
47
|
+
* can sit on a child item while the glowing mesh belongs to its parent item: search the item, then
|
|
48
|
+
* its nearest item ancestor. Re-installed if the item swaps its materials.
|
|
49
|
+
*/
|
|
50
|
+
export declare function syncLampEmitters(): void;
|
|
51
|
+
/** The lamps' own materials back (the daylight look left). */
|
|
52
|
+
export declare function restoreLampEmitters(): void;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=room-scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-scene.d.ts","sourceRoot":"","sources":["../../../src/lib/daylight/room-scene.ts"],"names":[],"mappings":"AAQA,OAAO,EAAoD,KAAK,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAKhG,OAAO,KAAK,EAAE,QAAQ,EAAmB,cAAc,EAAY,MAAM,SAAS,CAAA;AAGlF;;;GAGG;AAEH,mGAAmG;AACnG,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gBAAgB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAA;IAC3C,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,yFAAyF;IACzF,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3F,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;CAC3C,CAAA;AAED,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,MAAM,QAAQ,CAAC,aAAa,CAAC,CAAA;IACrC,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,CAAA;CAC5C,CAAA;AAED,8FAA8F;AAC9F,eAAO,MAAM,SAAS,eAAsB,CAAA;AAU5C,oEAAoE;AACpE,wBAAgB,SAAS,IAAI,QAAQ,EAAE,CAuBtC;AAeD,6CAA6C;AAC7C,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAK3D;AAcD,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,cAAc,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAgE5E;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,IAAI,QAAQ,EAAE,CAQ7C;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAanD;AAQD,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CA+E7F;AAiED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CA2CvC;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C"}
|