@pascal-app/viewer 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -21
- 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-replace-instances.d.ts +6 -3
- package/dist/components/viewer/glb-replace-instances.d.ts.map +1 -1
- package/dist/components/viewer/glb-replace-instances.js +5 -4
- 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 +5 -1
- package/dist/components/viewer/glb-scene.d.ts.map +1 -1
- package/dist/components/viewer/glb-scene.js +290 -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 +38 -10
- 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/registered-systems.d.ts.map +1 -1
- package/dist/components/viewer/registered-systems.js +2 -2
- 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/unsupported-gpu-fallback.d.ts.map +1 -1
- package/dist/components/viewer/unsupported-gpu-fallback.js +21 -1
- 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 +278 -0
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
- package/dist/components/viewer/viewer-camera.js +12 -1
- package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
- package/dist/hooks/use-gltf-ktx2.js +2 -1
- package/dist/index.d.ts +26 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -8
- package/dist/lib/asset-url.d.ts +0 -1
- package/dist/lib/asset-url.d.ts.map +1 -1
- package/dist/lib/asset-url.js +3 -3
- 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 +54 -0
- package/dist/lib/daylight/room-map.d.ts +124 -0
- package/dist/lib/daylight/room-map.d.ts.map +1 -0
- package/dist/lib/daylight/room-map.js +630 -0
- package/dist/lib/daylight/room-scene.d.ts +56 -0
- package/dist/lib/daylight/room-scene.d.ts.map +1 -0
- package/dist/lib/daylight/room-scene.js +391 -0
- package/dist/lib/daylight/rooms.d.ts +292 -0
- package/dist/lib/daylight/rooms.d.ts.map +1 -0
- package/dist/lib/daylight/rooms.js +1268 -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/ktx2-loader.d.ts.map +1 -1
- package/dist/lib/ktx2-loader.js +2 -1
- 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/measurement-label.d.ts +4 -0
- package/dist/lib/measurement-label.d.ts.map +1 -0
- package/dist/lib/measurement-label.js +54 -0
- package/dist/lib/measurement-presentation.d.ts +5 -0
- package/dist/lib/measurement-presentation.d.ts.map +1 -0
- package/dist/lib/measurement-presentation.js +8 -0
- 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/pointer-events.d.ts.map +1 -1
- package/dist/lib/pointer-events.js +3 -3
- 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 +13 -10
- 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/lib/viewer-config.d.ts +21 -0
- package/dist/lib/viewer-config.d.ts.map +1 -0
- package/dist/lib/viewer-config.js +21 -0
- package/dist/lib/viewer-preference-storage.d.ts +7 -0
- package/dist/lib/viewer-preference-storage.d.ts.map +1 -0
- package/dist/lib/viewer-preference-storage.js +23 -0
- 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 +62 -59
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +106 -19
- 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/elevator/elevator-interaction-system.d.ts +16 -2
- package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -1
- package/dist/systems/elevator/elevator-interaction-system.js +41 -8
- package/dist/systems/geometry/geometry-status.d.ts +8 -0
- package/dist/systems/geometry/geometry-status.d.ts.map +1 -0
- package/dist/systems/geometry/geometry-status.js +24 -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 +582 -168
- 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 +11 -0
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +86 -25
- 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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pointer-events.d.ts","sourceRoot":"","sources":["../../src/lib/pointer-events.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pointer-events.d.ts","sourceRoot":"","sources":["../../src/lib/pointer-events.ts"],"names":[],"mappings":"AAmCA,OAAO,EACL,MAAM,IAAI,eAAe,EAGzB,KAAK,YAAY,EAMjB,KAAK,SAAS,EAEf,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,+FAA+F;AAC/F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAA;AAmC5E,0GAA0G;AAC1G,wBAAgB,eAAe,CAAC,CAAC,SAAS,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAGlF;AAYD,wBAAgB,mBAAmB,CACjC,MAAM,SAA8D,EACpE,YAAY,CAAC,EAAE,uBAAuB,GACrC,OAAO,eAAe,CAIxB;AAiED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,KAAK,CAAC,QAAQ,EACtB,QAAQ,GAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,GAAG,SAA2C,GACxF,OAAO,CAST;AAMD,KAAK,mBAAmB,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAA;AAmC3D;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,MAAM,EAAE,KAAK,CAAC,QAAQ,EACtB,IAAI,EAAE,mBAAmB,GACxB,KAAK,CAAC,YAAY,EAAE,CAiBtB;AA+GD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,EAChB,YAAY,CAAC,EAAE,uBAAuB,GACrC,YAAY,CAAC,WAAW,CAAC,CAmB3B"}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* Ray collection is cached; camera-drag moves are throttled before stock dispatch.
|
|
27
27
|
* The throttle is a vendored-manager policy; dev ?stockEvents uses untouched R3F.
|
|
28
28
|
*/
|
|
29
|
-
import { sceneRegistry, useScene } from '@pascal-app/core';
|
|
29
|
+
import { isDevelopmentBuild, isDevelopmentOutsideTests, sceneRegistry, useScene, } from '@pascal-app/core';
|
|
30
30
|
import { events as createWebEvents, getRootState, } from '@react-three/fiber';
|
|
31
31
|
import * as THREE from 'three';
|
|
32
32
|
import { acceleratedRaycast } from 'three-mesh-bvh';
|
|
@@ -63,7 +63,7 @@ function isSupportedRaycast(raycast) {
|
|
|
63
63
|
raycast[pureRaycast] === true);
|
|
64
64
|
}
|
|
65
65
|
export function choosePointerEvents(search = typeof window !== 'undefined' ? window.location.search : '', onBreadcrumb) {
|
|
66
|
-
return
|
|
66
|
+
return isDevelopmentBuild() && new URLSearchParams(search).has('stockEvents')
|
|
67
67
|
? createWebEvents
|
|
68
68
|
: (store) => createPascalPointerEvents(store, onBreadcrumb);
|
|
69
69
|
}
|
|
@@ -443,7 +443,7 @@ function createEvents(store, onBreadcrumb) {
|
|
|
443
443
|
stats.fallbackEvents++;
|
|
444
444
|
stats.lastFallbackReason = reason;
|
|
445
445
|
if (unsupported &&
|
|
446
|
-
|
|
446
|
+
isDevelopmentOutsideTests() &&
|
|
447
447
|
!warnedRaycastNames.has(reason.fnName)) {
|
|
448
448
|
warnedRaycastNames.add(reason.fnName);
|
|
449
449
|
console.warn(`[pointer-events] Stock fallback for raycast "${reason.fnName}" on ${reason.objectType} "${reason.objectName}". Use markPureRaycast only after verifying it appends hits without reading prior hits or mutating scene/query state.`);
|
|
@@ -3,6 +3,10 @@ import type { LayerPassIndex } from './layer-pass';
|
|
|
3
3
|
export declare class PostProcessingResources {
|
|
4
4
|
layerIndex: LayerPassIndex | null;
|
|
5
5
|
readonly passes: PassNode[];
|
|
6
|
+
/** Effect nodes (AO, temporal AA, bloom) owning render targets. */
|
|
7
|
+
readonly effects: Array<{
|
|
8
|
+
dispose(): void;
|
|
9
|
+
}>;
|
|
6
10
|
outline: {
|
|
7
11
|
dispose(): void;
|
|
8
12
|
} | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-processing-resources.d.ts","sourceRoot":"","sources":["../../src/lib/post-processing-resources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAIlD,qBAAa,uBAAuB;IAClC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAO;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAK;IAChC,OAAO,EAAE;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,GAAG,IAAI,CAAO;IAC1C,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAO;IAEtC,OAAO,
|
|
1
|
+
{"version":3,"file":"post-processing-resources.d.ts","sourceRoot":"","sources":["../../src/lib/post-processing-resources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAIlD,qBAAa,uBAAuB;IAClC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAO;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAK;IAChC,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAC,CAAK;IACjD,OAAO,EAAE;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,GAAG,IAAI,CAAO;IAC1C,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAO;IAEtC,OAAO,SAWN;CACF"}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
export class PostProcessingResources {
|
|
4
4
|
layerIndex = null;
|
|
5
5
|
passes = [];
|
|
6
|
+
/** Effect nodes (AO, temporal AA, bloom) owning render targets. */
|
|
7
|
+
effects = [];
|
|
6
8
|
outline = null;
|
|
7
9
|
pipeline = null;
|
|
8
10
|
dispose() {
|
|
@@ -11,6 +13,9 @@ export class PostProcessingResources {
|
|
|
11
13
|
for (const pass of this.passes)
|
|
12
14
|
pass.dispose();
|
|
13
15
|
this.passes.length = 0;
|
|
16
|
+
for (const effect of this.effects)
|
|
17
|
+
effect.dispose();
|
|
18
|
+
this.effects.length = 0;
|
|
14
19
|
this.outline?.dispose();
|
|
15
20
|
this.outline = null;
|
|
16
21
|
this.pipeline?.dispose();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An RGBA8 render-target readback as tightly packed, top-down rows (what
|
|
3
|
+
* `ImageData` wants). Three shapes come back:
|
|
4
|
+
* - WebGPU, three before r187: top-down, each row padded to 256 bytes when
|
|
5
|
+
* width × 4 isn't already a multiple of 256.
|
|
6
|
+
* - WebGPU, three r187+: top-down and already tight (three strips the padding).
|
|
7
|
+
* - WebGL2 fallback (iOS Chrome, etc.): tight but bottom-up (the framebuffer
|
|
8
|
+
* convention).
|
|
9
|
+
* The WebGPU padding is settled by the buffer's exact length, not assumed:
|
|
10
|
+
* depadding a tight buffer (or reading a padded one tight) walks every row
|
|
11
|
+
* sideways and shears the frame into horizontal streaks.
|
|
12
|
+
*/
|
|
13
|
+
export declare function readbackRows(pixels: Uint8Array, width: number, height: number, isWebGPU: boolean): Uint8ClampedArray;
|
|
14
|
+
//# sourceMappingURL=readback-rows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readback-rows.d.ts","sourceRoot":"","sources":["../../src/lib/readback-rows.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,GAChB,iBAAiB,CAsBnB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** WebGPU's `copyTextureToBuffer` aligns every row to this many bytes. */
|
|
2
|
+
const WEBGPU_ROW_ALIGNMENT = 256;
|
|
3
|
+
/**
|
|
4
|
+
* An RGBA8 render-target readback as tightly packed, top-down rows (what
|
|
5
|
+
* `ImageData` wants). Three shapes come back:
|
|
6
|
+
* - WebGPU, three before r187: top-down, each row padded to 256 bytes when
|
|
7
|
+
* width × 4 isn't already a multiple of 256.
|
|
8
|
+
* - WebGPU, three r187+: top-down and already tight (three strips the padding).
|
|
9
|
+
* - WebGL2 fallback (iOS Chrome, etc.): tight but bottom-up (the framebuffer
|
|
10
|
+
* convention).
|
|
11
|
+
* The WebGPU padding is settled by the buffer's exact length, not assumed:
|
|
12
|
+
* depadding a tight buffer (or reading a padded one tight) walks every row
|
|
13
|
+
* sideways and shears the frame into horizontal streaks.
|
|
14
|
+
*/
|
|
15
|
+
export function readbackRows(pixels, width, height, isWebGPU) {
|
|
16
|
+
const tightBytesPerRow = width * 4;
|
|
17
|
+
const tightTotal = tightBytesPerRow * height;
|
|
18
|
+
const paddedBytesPerRow = Math.ceil(tightBytesPerRow / WEBGPU_ROW_ALIGNMENT) * WEBGPU_ROW_ALIGNMENT;
|
|
19
|
+
const stride = isWebGPU && pixels.byteLength === paddedBytesPerRow * height
|
|
20
|
+
? paddedBytesPerRow
|
|
21
|
+
: tightBytesPerRow;
|
|
22
|
+
if (isWebGPU && stride === tightBytesPerRow) {
|
|
23
|
+
return new Uint8ClampedArray(pixels.buffer, pixels.byteOffset, Math.min(pixels.byteLength, tightTotal));
|
|
24
|
+
}
|
|
25
|
+
const rows = new Uint8ClampedArray(tightTotal);
|
|
26
|
+
for (let row = 0; row < height; row++) {
|
|
27
|
+
const source = (isWebGPU ? row : height - 1 - row) * stride;
|
|
28
|
+
rows.set(pixels.subarray(source, source + tightBytesPerRow), row * tightBytesPerRow);
|
|
29
|
+
}
|
|
30
|
+
return rows;
|
|
31
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reveal-pose.d.ts","sourceRoot":"","sources":["../../src/lib/reveal-pose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAsB,KAAK,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"reveal-pose.d.ts","sourceRoot":"","sources":["../../src/lib/reveal-pose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAsB,KAAK,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAyDhD,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,SAAI,GAAG,IAAI,CAW9F;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,QAAQ,EAChB,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,GAAG,SAAI,GACN,IAAI,CAKN;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAQtD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAEvD;AAGD,qEAAqE;AACrE,eAAO,MAAM,SAAS,OAAO,CAAA;AAU7B,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAE/D,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,6GAA6G;IAC7G,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAKD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,WAAW,EAClB,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,MAAM,EACd,GAAG,GAAE,gBAAoD,EACzD,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAgDlB;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IACjD,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAID,eAAO,MAAM,gBAAgB,MAAM,CAAA;AACnC,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAOnC;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,WAAW,EAClB,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,MAAM,EACd,GAAG,GAAE,iBAAiE,GACrE,iBAAiB,CAmCnB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAQtD,CAAA;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAGtE;AAKD,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,GAAE,IAAiB,GAAG,IAAI,CAgB9E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAMlE"}
|
package/dist/lib/reveal-pose.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Box3, Matrix4, Vector3 } from 'three';
|
|
2
2
|
import { clearRevealWipe } from './reveal-wipe';
|
|
3
|
+
import { setMatrixPosed } from './scene-matrices';
|
|
3
4
|
const poses = new WeakMap();
|
|
4
5
|
const step = new Matrix4();
|
|
5
6
|
const glideStep = new Matrix4();
|
|
@@ -35,6 +36,7 @@ export function setRevealPose(object, pivot, scale, lift = 0) {
|
|
|
35
36
|
pose = { pivot: new Vector3(), scale: new Vector3(), lift: 0, glide: null };
|
|
36
37
|
poses.set(object, pose);
|
|
37
38
|
object.updateMatrix = updateRevealedMatrix;
|
|
39
|
+
setMatrixPosed(object, true);
|
|
38
40
|
}
|
|
39
41
|
pose.pivot.copy(pivot);
|
|
40
42
|
pose.scale.copy(scale);
|
|
@@ -59,6 +61,7 @@ export function clearRevealPose(object) {
|
|
|
59
61
|
if (!poses.delete(object))
|
|
60
62
|
return;
|
|
61
63
|
delete object.updateMatrix;
|
|
64
|
+
setMatrixPosed(object, false);
|
|
62
65
|
if (object.matrixAutoUpdate)
|
|
63
66
|
object.updateMatrix();
|
|
64
67
|
object.matrixWorldNeedsUpdate = true;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Object3D } from 'three';
|
|
2
|
+
/** Marks `object` as composing its matrix from more than its TRS, or no longer (`false`). */
|
|
3
|
+
export declare function setMatrixPosed(object: Object3D, on: boolean): void;
|
|
4
|
+
/** Whether `object` is hidden only because this render set it aside (outline proxies read this). */
|
|
5
|
+
export declare function isSetAsideForRender(object: Object3D): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Runs `render` with the scene's matrices updated once beforehand, three's per-render update off,
|
|
8
|
+
* and the subtrees no pass draws set aside, so every pass sees the same, already current, matrices
|
|
9
|
+
* and walks only what it can draw.
|
|
10
|
+
*/
|
|
11
|
+
export declare function renderWithSceneMatrices<T>(scene: Object3D, render: () => T): T;
|
|
12
|
+
//# sourceMappingURL=scene-matrices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-matrices.d.ts","sourceRoot":"","sources":["../../src/lib/scene-matrices.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,QAAQ,EAAE,MAAM,OAAO,CAAA;AAuP5E,6FAA6F;AAC7F,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI,CASlE;AAqCD,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAE7D;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CA0B9E"}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Object3D } from 'three';
|
|
2
|
+
import { getLayoutRevision, isLayoutObserved } from './layer-pass';
|
|
3
|
+
import { BATCHED_LAYER, SHADOW_ONLY_LAYER } from './layers';
|
|
4
|
+
/**
|
|
5
|
+
* The frame's one walk over the scene graph before it renders: matrices, recomputing only what
|
|
6
|
+
* changed, and the subtrees no pass of this frame can draw.
|
|
7
|
+
*
|
|
8
|
+
* three's `updateMatrixWorld` recomposes every object's local matrix and multiplies every world
|
|
9
|
+
* matrix each time it runs, and every `renderer.render` of the scene runs it again (prepass,
|
|
10
|
+
* scene pass, layer passes, shadows). Editor scenes hold ~10k objects, almost all static, so that
|
|
11
|
+
* was ~13 ms a frame. Here each object remembers the inputs its matrices were last built from —
|
|
12
|
+
* position, quaternion, scale and pivot (or the local matrix itself when `matrixAutoUpdate` is
|
|
13
|
+
* off) and its parent — and is rebuilt only when one differs, or when its parent's world matrix
|
|
14
|
+
* was. The results are the same as three's: a write to `position` is seen the same frame.
|
|
15
|
+
*
|
|
16
|
+
* Every pass also walks the whole graph to find what to draw, and most of an editor scene is not
|
|
17
|
+
* drawable by the color passes: batched originals live on the batched layer, a soloed level's
|
|
18
|
+
* objects on the shadow-only layer. The same walk finds the top-most subtrees with nothing a pass
|
|
19
|
+
* can draw this frame, and they are hidden for the render alone, so three never enters them.
|
|
20
|
+
* Shadow-only content counts as drawable when a light's shadow map renders this frame. Picking,
|
|
21
|
+
* outlines and bounds run outside the render and see the scene unchanged.
|
|
22
|
+
*
|
|
23
|
+
* Those set-aside subtrees are not walked again while nothing could change what they hold: no
|
|
24
|
+
* observed mask write or child insertion or removal anywhere (LayerPassIndex's revision), no move
|
|
25
|
+
* of their parent, and at least every {@link FULL_WALK_FRAMES} frames regardless. Their matrices
|
|
26
|
+
* (picking reads them) are brought up to date on the next full walk.
|
|
27
|
+
*
|
|
28
|
+
* Objects that override `updateMatrixWorld` (cameras, skinned meshes, audio, some helpers) are
|
|
29
|
+
* handed to their own method, which brings their subtree up to date the way three would; they and
|
|
30
|
+
* their subtrees always count as drawable.
|
|
31
|
+
*/
|
|
32
|
+
const BASE_UPDATE_MATRIX_WORLD = Object3D.prototype.updateMatrixWorld;
|
|
33
|
+
const MATRIX = 16;
|
|
34
|
+
const FULL_WALK_FRAMES = 30;
|
|
35
|
+
/** Layers some pass of the frame may draw: everything but the batched originals'. */
|
|
36
|
+
const COLOR_LAYERS = ~((1 << BATCHED_LAYER) | (1 << SHADOW_ONLY_LAYER));
|
|
37
|
+
const SHADOW_LAYERS = 1 << SHADOW_ONLY_LAYER;
|
|
38
|
+
/** Bit 1: holds something a color pass draws. Bit 2: something only a shadow pass draws. */
|
|
39
|
+
const COLOR = 1;
|
|
40
|
+
const SHADOW = 2;
|
|
41
|
+
const MEMO = Symbol('pascal:scene-matrices');
|
|
42
|
+
function memoOf(object) {
|
|
43
|
+
let memo = object[MEMO];
|
|
44
|
+
if (!memo) {
|
|
45
|
+
memo = {
|
|
46
|
+
local: new Float64Array(MATRIX).fill(Number.NaN),
|
|
47
|
+
parent: undefined,
|
|
48
|
+
holds: 0,
|
|
49
|
+
idle: false,
|
|
50
|
+
drawn: isDrawn(object),
|
|
51
|
+
custom: object.updateMatrixWorld !== BASE_UPDATE_MATRIX_WORLD,
|
|
52
|
+
};
|
|
53
|
+
object[MEMO] = memo;
|
|
54
|
+
}
|
|
55
|
+
return memo;
|
|
56
|
+
}
|
|
57
|
+
/** Whether `object`'s TRS (and pivot) differ from what its matrix was last composed from. */
|
|
58
|
+
function trsChanged(object, local) {
|
|
59
|
+
const { position: p, quaternion: q, scale: s } = object;
|
|
60
|
+
const pivot = object.pivot ?? null;
|
|
61
|
+
const px = pivot ? pivot.x : Number.NaN;
|
|
62
|
+
const py = pivot ? pivot.y : Number.NaN;
|
|
63
|
+
const pz = pivot ? pivot.z : Number.NaN;
|
|
64
|
+
if (local[0] === p.x &&
|
|
65
|
+
local[1] === p.y &&
|
|
66
|
+
local[2] === p.z &&
|
|
67
|
+
local[3] === q.x &&
|
|
68
|
+
local[4] === q.y &&
|
|
69
|
+
local[5] === q.z &&
|
|
70
|
+
local[6] === q.w &&
|
|
71
|
+
local[7] === s.x &&
|
|
72
|
+
local[8] === s.y &&
|
|
73
|
+
local[9] === s.z &&
|
|
74
|
+
// NaN marks "no pivot"; Object.is matches it to itself.
|
|
75
|
+
Object.is(local[10], px) &&
|
|
76
|
+
Object.is(local[11], py) &&
|
|
77
|
+
Object.is(local[12], pz)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
local[0] = p.x;
|
|
81
|
+
local[1] = p.y;
|
|
82
|
+
local[2] = p.z;
|
|
83
|
+
local[3] = q.x;
|
|
84
|
+
local[4] = q.y;
|
|
85
|
+
local[5] = q.z;
|
|
86
|
+
local[6] = q.w;
|
|
87
|
+
local[7] = s.x;
|
|
88
|
+
local[8] = s.y;
|
|
89
|
+
local[9] = s.z;
|
|
90
|
+
local[10] = px;
|
|
91
|
+
local[11] = py;
|
|
92
|
+
local[12] = pz;
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
/** Whether a hand-set local matrix differs from the one the world matrix was last built from. */
|
|
96
|
+
function matrixChanged(matrix, local) {
|
|
97
|
+
const e = matrix.elements;
|
|
98
|
+
let changed = false;
|
|
99
|
+
for (let i = 0; i < MATRIX; i++) {
|
|
100
|
+
if (local[i] !== e[i]) {
|
|
101
|
+
local[i] = e[i];
|
|
102
|
+
changed = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return changed;
|
|
106
|
+
}
|
|
107
|
+
/** Objects a pass draws or collects itself; groups and plain nodes only hold them. */
|
|
108
|
+
function isDrawn(o) {
|
|
109
|
+
return (o.isMesh === true ||
|
|
110
|
+
o.isLine === true ||
|
|
111
|
+
o.isPoints === true ||
|
|
112
|
+
o.isSprite === true ||
|
|
113
|
+
o.isLight === true ||
|
|
114
|
+
o.isLOD === true ||
|
|
115
|
+
o.isClippingGroup === true ||
|
|
116
|
+
o.isBundleGroup === true);
|
|
117
|
+
}
|
|
118
|
+
function update(object, force, walk) {
|
|
119
|
+
const memo = memoOf(object);
|
|
120
|
+
if (memo.custom) {
|
|
121
|
+
object.updateMatrixWorld(force);
|
|
122
|
+
memo.holds = COLOR | SHADOW;
|
|
123
|
+
return memo.holds;
|
|
124
|
+
}
|
|
125
|
+
// What this walk compares decides, not `matrixWorldNeedsUpdate`: other code's
|
|
126
|
+
// `updateWorldMatrix(true, …)` raises that flag up whole ancestor chains every frame while
|
|
127
|
+
// recomputing the same values, and honouring it forced the entire graph each frame.
|
|
128
|
+
let changed = force;
|
|
129
|
+
if (posed.size > 0 && posed.has(object)) {
|
|
130
|
+
object.updateMatrix();
|
|
131
|
+
changed = true;
|
|
132
|
+
}
|
|
133
|
+
else if (object.matrixAutoUpdate) {
|
|
134
|
+
// A matrix kept by hand earlier left 16 numbers here; TRS uses the first 13.
|
|
135
|
+
if (trsChanged(object, memo.local)) {
|
|
136
|
+
object.updateMatrix();
|
|
137
|
+
changed = true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else if (matrixChanged(object.matrix, memo.local)) {
|
|
141
|
+
changed = true;
|
|
142
|
+
}
|
|
143
|
+
// A set-aside subtree that has not itself moved holds what it held; what is inside changes
|
|
144
|
+
// drawability only through a mask or child event, which forces a full walk.
|
|
145
|
+
if (walk.skipIdle && memo.idle && !changed && memo.parent === object.parent)
|
|
146
|
+
return memo.holds;
|
|
147
|
+
if (memo.parent !== object.parent) {
|
|
148
|
+
memo.parent = object.parent;
|
|
149
|
+
changed = true;
|
|
150
|
+
}
|
|
151
|
+
if (changed) {
|
|
152
|
+
if (object.matrixWorldAutoUpdate === true) {
|
|
153
|
+
if (object.parent === null)
|
|
154
|
+
object.matrixWorld.copy(object.matrix);
|
|
155
|
+
else
|
|
156
|
+
object.matrixWorld.multiplyMatrices(object.parent.matrixWorld, object.matrix);
|
|
157
|
+
}
|
|
158
|
+
force = true;
|
|
159
|
+
}
|
|
160
|
+
object.matrixWorldNeedsUpdate = false;
|
|
161
|
+
let all = 0;
|
|
162
|
+
if (memo.drawn) {
|
|
163
|
+
const mask = object.layers.mask;
|
|
164
|
+
if (mask & COLOR_LAYERS)
|
|
165
|
+
all |= COLOR;
|
|
166
|
+
if (mask & SHADOW_LAYERS)
|
|
167
|
+
all |= SHADOW;
|
|
168
|
+
const light = object;
|
|
169
|
+
if (light.isLight && light.castShadow && light.shadow) {
|
|
170
|
+
walk.shadowLights.push(light);
|
|
171
|
+
if (light.shadow.autoUpdate || light.shadow.needsUpdate)
|
|
172
|
+
walk.shadowPending = true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const children = object.children;
|
|
176
|
+
for (let i = 0; i < children.length; i++)
|
|
177
|
+
all |= update(children[i], force, walk);
|
|
178
|
+
// Children's results decide which of them to set aside: those with nothing, under a parent
|
|
179
|
+
// that holds something (the parent's own parent sets the parent aside otherwise).
|
|
180
|
+
if (all !== 0) {
|
|
181
|
+
for (let i = 0; i < children.length; i++) {
|
|
182
|
+
const child = children[i];
|
|
183
|
+
const childMemo = child[MEMO];
|
|
184
|
+
if (!childMemo)
|
|
185
|
+
continue;
|
|
186
|
+
const held = childMemo.holds;
|
|
187
|
+
const aside = all & COLOR ? !(held & COLOR) : !(held & SHADOW);
|
|
188
|
+
childMemo.idle = aside;
|
|
189
|
+
if (!aside)
|
|
190
|
+
continue;
|
|
191
|
+
if (!(held & SHADOW))
|
|
192
|
+
walk.shadowIdle.push(child);
|
|
193
|
+
if (all & COLOR)
|
|
194
|
+
walk.colorIdle.push(child);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
memo.holds = all;
|
|
198
|
+
return all;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Objects whose `updateMatrix` composes a pose that moves on its own (a construction reveal, an
|
|
202
|
+
* agent's glide: reveal-pose.ts) — their TRS stays put, so they recompose every frame.
|
|
203
|
+
*/
|
|
204
|
+
const posed = new Set();
|
|
205
|
+
/** Marks `object` as composing its matrix from more than its TRS, or no longer (`false`). */
|
|
206
|
+
export function setMatrixPosed(object, on) {
|
|
207
|
+
if (on) {
|
|
208
|
+
posed.add(object);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
posed.delete(object);
|
|
212
|
+
// Its last posed matrix is not what its TRS gives: rebuild on the next walk.
|
|
213
|
+
const memo = object[MEMO];
|
|
214
|
+
if (memo)
|
|
215
|
+
memo.local[0] = Number.NaN;
|
|
216
|
+
}
|
|
217
|
+
let lastRevision = -1;
|
|
218
|
+
let framesSinceFull = 0;
|
|
219
|
+
/**
|
|
220
|
+
* Brings every matrix under `root` up to date, rebuilding only those whose inputs changed.
|
|
221
|
+
* Returns what it found: the subtrees nothing of this frame draws, and the shadow casting lights.
|
|
222
|
+
*/
|
|
223
|
+
function updateSceneMatrices(root) {
|
|
224
|
+
const skipIdle = isLayoutObserved(root) &&
|
|
225
|
+
getLayoutRevision() === lastRevision &&
|
|
226
|
+
framesSinceFull < FULL_WALK_FRAMES;
|
|
227
|
+
framesSinceFull = skipIdle ? framesSinceFull + 1 : 0;
|
|
228
|
+
const walk = {
|
|
229
|
+
colorIdle: [],
|
|
230
|
+
shadowIdle: [],
|
|
231
|
+
shadowPending: false,
|
|
232
|
+
skipIdle,
|
|
233
|
+
shadowLights: [],
|
|
234
|
+
};
|
|
235
|
+
update(root, false, walk);
|
|
236
|
+
lastRevision = getLayoutRevision();
|
|
237
|
+
if (walk.shadowPending && skipIdle) {
|
|
238
|
+
// Shadow-only content skipped while color-idle must be current before a shadow pass draws it.
|
|
239
|
+
framesSinceFull = FULL_WALK_FRAMES;
|
|
240
|
+
return updateSceneMatrices(root);
|
|
241
|
+
}
|
|
242
|
+
return walk;
|
|
243
|
+
}
|
|
244
|
+
/** The shadow map each light had after the last render. */
|
|
245
|
+
const shadowMaps = new WeakMap();
|
|
246
|
+
const hidden = new Set();
|
|
247
|
+
/** Whether `object` is hidden only because this render set it aside (outline proxies read this). */
|
|
248
|
+
export function isSetAsideForRender(object) {
|
|
249
|
+
return hidden.has(object);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Runs `render` with the scene's matrices updated once beforehand, three's per-render update off,
|
|
253
|
+
* and the subtrees no pass draws set aside, so every pass sees the same, already current, matrices
|
|
254
|
+
* and walks only what it can draw.
|
|
255
|
+
*/
|
|
256
|
+
export function renderWithSceneMatrices(scene, render) {
|
|
257
|
+
const walk = updateSceneMatrices(scene);
|
|
258
|
+
const idle = walk.shadowPending ? walk.shadowIdle : walk.colorIdle;
|
|
259
|
+
hidden.clear();
|
|
260
|
+
for (const object of idle) {
|
|
261
|
+
if (!object.visible)
|
|
262
|
+
continue;
|
|
263
|
+
object.visible = false;
|
|
264
|
+
hidden.add(object);
|
|
265
|
+
}
|
|
266
|
+
const auto = scene.matrixWorldAutoUpdate;
|
|
267
|
+
scene.matrixWorldAutoUpdate = false;
|
|
268
|
+
try {
|
|
269
|
+
return render();
|
|
270
|
+
}
|
|
271
|
+
finally {
|
|
272
|
+
scene.matrixWorldAutoUpdate = auto;
|
|
273
|
+
for (const object of hidden)
|
|
274
|
+
object.visible = true;
|
|
275
|
+
hidden.clear();
|
|
276
|
+
// A light whose shadow map was (re)built during the render drew it without what this frame
|
|
277
|
+
// set aside (a shadow node rebuilt with the pipeline): draw it whole next frame.
|
|
278
|
+
for (const light of walk.shadowLights) {
|
|
279
|
+
const map = light.shadow.map;
|
|
280
|
+
if (shadowMaps.get(light) === map)
|
|
281
|
+
continue;
|
|
282
|
+
shadowMaps.set(light, map);
|
|
283
|
+
if (map)
|
|
284
|
+
light.shadow.needsUpdate = true;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { mrt } from 'three/tsl';
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Per-pixel weights. R: screen-space AO/GI applies (unlit assets already contain their lighting
|
|
4
|
+
* and must not be lit again). G: the pixel feeds the bloom (not editor highlights, see `markHighlight`).
|
|
5
|
+
*/
|
|
6
|
+
export declare function sceneLightingMask(): import("three/webgpu").JoinNode<"vec4">;
|
|
4
7
|
/**
|
|
5
8
|
* The scene pass's attachments. three blends `output` by the material and leaves every other
|
|
6
9
|
* attachment unblended, so a transparent draw overwrites the whole of what it covers in the normals
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-pass-mrt.d.ts","sourceRoot":"","sources":["../../src/lib/scene-pass-mrt.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,GAAG,EAAiB,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"scene-pass-mrt.d.ts","sourceRoot":"","sources":["../../src/lib/scene-pass-mrt.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,GAAG,EAAiB,MAAM,WAAW,CAAA;AAO5D;;;GAGG;AACH,wBAAgB,iBAAiB,4CAMhC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,kCAK9D"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { MaterialBlending } from 'three';
|
|
2
2
|
import { diffuseColor, mrt, uniform, vec4 } from 'three/tsl';
|
|
3
3
|
import { BlendMode } from 'three/webgpu';
|
|
4
|
+
import { isHighlight } from './editor-highlight';
|
|
4
5
|
import { importedUnlitMaterial } from './gltf-unlit';
|
|
5
6
|
const materialBlend = new BlendMode(MaterialBlending);
|
|
6
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Per-pixel weights. R: screen-space AO/GI applies (unlit assets already contain their lighting
|
|
9
|
+
* and must not be lit again). G: the pixel feeds the bloom (not editor highlights, see `markHighlight`).
|
|
10
|
+
*/
|
|
7
11
|
export function sceneLightingMask() {
|
|
8
12
|
const weight = uniform(1).onObjectUpdate(({ material }) => importedUnlitMaterial(material) ? 0 : 1);
|
|
9
|
-
|
|
13
|
+
const bloomWeight = uniform(1).onObjectUpdate(({ material }) => (isHighlight(material) ? 0 : 1));
|
|
14
|
+
return vec4(weight, bloomWeight, 0, diffuseColor.a);
|
|
10
15
|
}
|
|
11
16
|
/**
|
|
12
17
|
* The scene pass's attachments. three blends `output` by the material and leaves every other
|
|
@@ -44,8 +44,6 @@ export declare const UNDERGROUND_PALETTE: {
|
|
|
44
44
|
readonly vignette: '#0c0c0c';
|
|
45
45
|
/** The thin rim along the cut of the hole in the ground, from above. */
|
|
46
46
|
readonly rim: '#3c3c3c';
|
|
47
|
-
/** The grade ring under the ground: a light rim where the ground meets the level. */
|
|
48
|
-
readonly ring: '#b4b4b4';
|
|
49
47
|
/** The sky light's tint (ambient and hemisphere pulled toward it under the ground). */
|
|
50
48
|
readonly tint: '#c8c8c8';
|
|
51
49
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-themes.d.ts","sourceRoot":"","sources":["../../src/lib/scene-themes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAErE,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IAIZ,UAAU,EAAE,OAAO,GAAG,MAAM,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAIlB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAI7B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IACzD,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;IACxE,mBAAmB,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAA;IACtE,cAAc,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAA;CACjD,CAAA;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,gBAAgB,GAAG,UAAU,CAUhG;AAED,eAAO,MAAM,YAAY,EAAE,UAAU,EAoMpC,CAAA;AAED,eAAO,MAAM,eAAe,UAAwC,CAAA;AAIpE,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,CAEpD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;IAC9B,8EAA8E;aAC9E,UAAU,EAAE,SAAS;IACrB,yCAAyC;aACzC,IAAI,EAAE,SAAS;IACf,iDAAiD;aACjD,GAAG,EAAE,SAAS;aACd,OAAO,EAAE,SAAS;IAClB,6CAA6C;aAC7C,QAAQ,EAAE,SAAS;IACnB,wEAAwE;aACxE,GAAG,EAAE,SAAS;IACd,
|
|
1
|
+
{"version":3,"file":"scene-themes.d.ts","sourceRoot":"","sources":["../../src/lib/scene-themes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAErE,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IAIZ,UAAU,EAAE,OAAO,GAAG,MAAM,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAIlB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAI7B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IACzD,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;IACxE,mBAAmB,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAA;IACtE,cAAc,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAA;CACjD,CAAA;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,gBAAgB,GAAG,UAAU,CAUhG;AAED,eAAO,MAAM,YAAY,EAAE,UAAU,EAoMpC,CAAA;AAED,eAAO,MAAM,eAAe,UAAwC,CAAA;AAIpE,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,CAEpD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;IAC9B,8EAA8E;aAC9E,UAAU,EAAE,SAAS;IACrB,yCAAyC;aACzC,IAAI,EAAE,SAAS;IACf,iDAAiD;aACjD,GAAG,EAAE,SAAS;aACd,OAAO,EAAE,SAAS;IAClB,6CAA6C;aAC7C,QAAQ,EAAE,SAAS;IACnB,wEAAwE;aACxE,GAAG,EAAE,SAAS;IACd,uFAAuF;aACvF,IAAI,EAAE,SAAS;CACP,CAAA"}
|
package/dist/lib/scene-themes.js
CHANGED
|
@@ -231,8 +231,6 @@ export const UNDERGROUND_PALETTE = {
|
|
|
231
231
|
vignette: '#0c0c0c',
|
|
232
232
|
/** The thin rim along the cut of the hole in the ground, from above. */
|
|
233
233
|
rim: '#3c3c3c',
|
|
234
|
-
/** The grade ring under the ground: a light rim where the ground meets the level. */
|
|
235
|
-
ring: '#b4b4b4',
|
|
236
234
|
/** The sky light's tint (ambient and hemisphere pulled toward it under the ground). */
|
|
237
235
|
tint: '#c8c8c8',
|
|
238
236
|
};
|
|
@@ -13,6 +13,8 @@ export type HiddenReason = 'isolated' | 'shadow-only' | 'batched' | 'wall-batche
|
|
|
13
13
|
export declare function hideFromScene(obj: Object3D, reason: HiddenReason): void;
|
|
14
14
|
/** Drops `reason`, restoring the mask `obj` had before the first one arrived. */
|
|
15
15
|
export declare function showInScene(obj: Object3D, reason: HiddenReason): void;
|
|
16
|
+
/** The reasons `obj` is held off the scene layer, if any. */
|
|
17
|
+
export declare function heldReasons(obj: Object3D): ReadonlySet<HiddenReason> | undefined;
|
|
16
18
|
export declare function temporarilyShowShadowOnly(root: Object3D): () => void;
|
|
17
19
|
/**
|
|
18
20
|
* Lifts what the user's view holds back under `root` — solo's shadow-only
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-visibility.d.ts","sourceRoot":"","sources":["../../src/lib/scene-visibility.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAGrC;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,cAAc,GAAG,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"scene-visibility.d.ts","sourceRoot":"","sources":["../../src/lib/scene-visibility.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAGrC;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,cAAc,GAAG,cAAc,CAAA;AAoBnG,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CASvE;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAarE;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,GAAG,SAAS,CAEhF;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,IAAI,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,IAAI,CAEtE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,SAAS,QAAQ,EAAE,EAC7B,KAAK,EAAE,OAAO,GACb,MAAM,IAAI,CAYZ;AAED,wFAAwF;AACxF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,IAAI,CAczF"}
|
|
@@ -14,7 +14,11 @@ const HOLD = Symbol('pascal:scene-visibility:hold');
|
|
|
14
14
|
/** Holds `obj` off the scene layer for `reason`. Idempotent per reason. */
|
|
15
15
|
export function hideFromScene(obj, reason) {
|
|
16
16
|
const holder = obj;
|
|
17
|
-
|
|
17
|
+
// Solo re-hides whole levels every frame: when nothing rewrote the mask since, there is no work.
|
|
18
|
+
const held = holder[HOLD];
|
|
19
|
+
if (held?.reasons.has(reason) && held.applied === obj.layers.mask)
|
|
20
|
+
return;
|
|
21
|
+
const hold = held ?? { original: obj.layers.mask, reasons: new Set() };
|
|
18
22
|
holder[HOLD] = hold;
|
|
19
23
|
hold.reasons.add(reason);
|
|
20
24
|
applyHold(obj, hold);
|
|
@@ -33,6 +37,10 @@ export function showInScene(obj, reason) {
|
|
|
33
37
|
obj.layers.mask = hold.original;
|
|
34
38
|
delete holder[HOLD];
|
|
35
39
|
}
|
|
40
|
+
/** The reasons `obj` is held off the scene layer, if any. */
|
|
41
|
+
export function heldReasons(obj) {
|
|
42
|
+
return obj[HOLD]?.reasons;
|
|
43
|
+
}
|
|
36
44
|
export function temporarilyShowShadowOnly(root) {
|
|
37
45
|
return temporarilyShowHeld(root, ['shadow-only']);
|
|
38
46
|
}
|
|
@@ -114,8 +122,9 @@ function applyHold(obj, hold) {
|
|
|
114
122
|
obj.layers.disable(SHADOW_ONLY_LAYER);
|
|
115
123
|
if (hold.reasons.has('batched') || hold.reasons.has('wall-batched')) {
|
|
116
124
|
obj.layers.enable(BATCHED_LAYER);
|
|
117
|
-
return;
|
|
118
125
|
}
|
|
119
|
-
if (!hold.reasons.has('isolated') && hold.reasons.has('shadow-only'))
|
|
126
|
+
else if (!hold.reasons.has('isolated') && hold.reasons.has('shadow-only')) {
|
|
120
127
|
obj.layers.enable(SHADOW_ONLY_LAYER);
|
|
128
|
+
}
|
|
129
|
+
hold.applied = obj.layers.mask;
|
|
121
130
|
}
|
|
@@ -4,14 +4,9 @@ import type { Object3D } from 'three';
|
|
|
4
4
|
* drawn on the ground (property line, setbacks, contours) carry none.
|
|
5
5
|
*/
|
|
6
6
|
export declare const SITE_GROUND = "siteGround";
|
|
7
|
-
/**
|
|
8
|
-
* `userData` key marking the generic foundation under the buildings (footing and stem, drawn under
|
|
9
|
-
* the ground): a capture that sees through the veil leaves it out, as it left it out before it was drawn.
|
|
10
|
-
*/
|
|
11
|
-
export declare const SITE_FOUNDATION = "siteFoundation";
|
|
12
7
|
/**
|
|
13
8
|
* `solid`: the lot's fill, its sculpted terrain, the horizon disc. `veil`: what is drawn in their
|
|
14
|
-
* place over a level below grade
|
|
9
|
+
* place over a level below grade.
|
|
15
10
|
*/
|
|
16
11
|
export type SiteGroundRole = 'solid' | 'veil';
|
|
17
12
|
/**
|
|
@@ -19,8 +14,6 @@ export type SiteGroundRole = 'solid' | 'veil';
|
|
|
19
14
|
* its registered children (buildings, items), which are groups.
|
|
20
15
|
*/
|
|
21
16
|
export declare function siteSurfaces(): Object3D[];
|
|
22
|
-
/** The site's generic foundation meshes, shown or not. */
|
|
23
|
-
export declare function siteFoundation(): Object3D[];
|
|
24
17
|
/** The site's ground by role, shown or not: the veil is hidden until a level below grade is shown. */
|
|
25
18
|
export declare function siteGround(): Record<SiteGroundRole, Object3D[]>;
|
|
26
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"site-surfaces.d.ts","sourceRoot":"","sources":["../../src/lib/site-surfaces.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAGrC;;;GAGG;AACH,eAAO,MAAM,WAAW,eAAe,CAAA;AAEvC;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"site-surfaces.d.ts","sourceRoot":"","sources":["../../src/lib/site-surfaces.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAGrC;;;GAGG;AACH,eAAO,MAAM,WAAW,eAAe,CAAA;AAEvC;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,CAAA;AAE7C;;;GAGG;AACH,wBAAgB,YAAY,IAAI,QAAQ,EAAE,CAUzC;AAED,sGAAsG;AACtG,wBAAgB,UAAU,IAAI,MAAM,CAAC,cAAc,EAAE,QAAQ,EAAE,CAAC,CAS/D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,CASjE"}
|