@pascal-app/viewer 1.0.0 → 1.0.3
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 +12 -0
- package/dist/capture/capture-runtime.js +2 -32
- package/dist/capture/layers/device-motion-layer.d.ts.map +1 -1
- package/dist/capture/layers/device-motion-layer.js +5 -7
- package/dist/capture/stream-rendering.d.ts.map +1 -1
- package/dist/capture/stream-rendering.js +2 -1
- package/dist/capture/use-json-artifact.d.ts +2 -0
- package/dist/capture/use-json-artifact.d.ts.map +1 -0
- package/dist/capture/use-json-artifact.js +42 -0
- package/dist/components/viewer/glb-scene.d.ts.map +1 -1
- package/dist/components/viewer/glb-scene.js +3 -1
- package/dist/components/viewer/index.d.ts +12 -0
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +28 -7
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +6 -0
- package/dist/components/viewer/selection-manager.d.ts.map +1 -1
- package/dist/components/viewer/selection-manager.js +8 -16
- package/dist/components/viewer/viewer-camera.d.ts +15 -1
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
- package/dist/components/viewer/viewer-camera.js +43 -5
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/lib/csg-utils.d.ts +1 -1
- package/dist/lib/csg-utils.d.ts.map +1 -1
- package/dist/lib/csg-utils.js +1 -1
- package/dist/lib/isolation.d.ts +14 -30
- package/dist/lib/isolation.d.ts.map +1 -1
- package/dist/lib/isolation.js +62 -66
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +2 -1
- package/dist/lib/renderer-capability.d.ts +2 -1
- package/dist/lib/renderer-capability.d.ts.map +1 -1
- package/dist/lib/renderer-capability.js +2 -2
- package/dist/lib/scene-visibility.js +3 -1
- package/dist/lib/snapshot-pipeline.d.ts +3 -1
- package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
- package/dist/lib/snapshot-pipeline.js +32 -16
- package/dist/store/use-viewer.d.ts +3 -1
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +2 -0
- package/dist/systems/door/door-system.d.ts.map +1 -1
- package/dist/systems/door/door-system.js +18 -5
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts.map +1 -1
- package/dist/systems/floor-elevation/floor-elevation-system.js +122 -3
- package/dist/systems/geometry/geometry-system.d.ts.map +1 -1
- package/dist/systems/geometry/geometry-system.js +4 -0
- package/dist/systems/level/level-system.js +14 -14
- package/dist/systems/level/level-utils.d.ts +25 -1
- package/dist/systems/level/level-utils.d.ts.map +1 -1
- package/dist/systems/level/level-utils.js +25 -4
- package/dist/systems/wall/wall-cutout-cache.d.ts +4 -1
- package/dist/systems/wall/wall-cutout-cache.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout-cache.js +16 -7
- package/dist/systems/wall/wall-cutout.d.ts +3 -1
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout.js +5 -5
- package/dist/systems/wall/wall-materials.d.ts +11 -2
- package/dist/systems/wall/wall-materials.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.js +24 -18
- package/dist/systems/wall/wall-system.d.ts +15 -2
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +20 -21
- package/dist/systems/window/window-system.d.ts +1 -1
- package/dist/systems/window/window-system.d.ts.map +1 -1
- package/dist/systems/window/window-system.js +3 -2
- package/dist/systems/zone/zone-system.d.ts.map +1 -1
- package/dist/systems/zone/zone-system.js +28 -2
- package/dist/xr/presentation-context.d.ts +7 -0
- package/dist/xr/presentation-context.d.ts.map +1 -0
- package/dist/xr/presentation-context.js +10 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ 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
|
-
export { default as Viewer } from './components/viewer';
|
|
13
|
+
export { default as Viewer, } from './components/viewer';
|
|
14
14
|
export { default as BVHEcctrl, } from './components/viewer/bvh-ecctrl';
|
|
15
15
|
export { buildGlbInteractiveItems, GlbInteractive, } from './components/viewer/glb-interactive';
|
|
16
16
|
export { buildGlbReferenceNodes, buildGlbReplaceNodes, } from './components/viewer/glb-reference-nodes';
|
|
@@ -31,11 +31,11 @@ export { applyWorldScaleBoxUVs } from './lib/box-uv';
|
|
|
31
31
|
// CSG primitives — used by chimney's roof-trim and other kinds whose
|
|
32
32
|
// geometry subtracts pieces against their host. Lives in viewer
|
|
33
33
|
// because three-bvh-csg / three-mesh-bvh are viewer-only deps.
|
|
34
|
-
export { ADDITION, Brush, computeGeometryBoundsTree, csgEvaluator, csgGeometry, csgMaterials, INTERSECTION, prepareBrushForCSG, SUBTRACTION, } from './lib/csg-utils';
|
|
34
|
+
export { ADDITION, Brush, computeGeometryBoundsTree, csgEvaluator, csgGeometry, csgMaterials, Evaluator, ensureRenderableGeometryAttributes, INTERSECTION, prepareBrushForCSG, SUBTRACTION, } from './lib/csg-utils';
|
|
35
35
|
export { disposeObject3DResources } from './lib/dispose-object3d';
|
|
36
36
|
export { PERF_OVERLAY_ENABLED } from './lib/gpu-perf';
|
|
37
37
|
export { computeHeroFraming, DEFAULT_FRAMING_EXCLUDED_TYPES, heroCameraPose, temporarilyHideNodeTypes, unionRegisteredNodeBounds, } from './lib/hero-pose';
|
|
38
|
-
export { applyIsolation, clearIsolation, collectIsolationSubtree, isIsolationActive, } from './lib/isolation';
|
|
38
|
+
export { applyIsolation, clearIsolation, collectIsolationSubtree, isIsolationActive, refreshIsolation, } from './lib/isolation';
|
|
39
39
|
export { configureKtx2Support, ensureKtx2Support } from './lib/ktx2-loader';
|
|
40
40
|
export { LayerPassIndex } from './lib/layer-pass';
|
|
41
41
|
export { BATCHED_LAYER, GRID_LAYER, OVERLAY_LAYER, SCENE_LAYER, SHADOW_ONLY_LAYER, setSurfaceRaycastLayers, ZONE_LAYER, } from './lib/layers';
|
|
@@ -92,14 +92,16 @@ export { StairSystem } from './systems/stair/stair-system';
|
|
|
92
92
|
// Pure opening-cutout profile math shared by the wall CSG pipeline and
|
|
93
93
|
// roof-wall opening cuts in `@pascal-app/nodes` — keeps shaped holes
|
|
94
94
|
// (arch / rounded / frameless opening) identical across both hosts.
|
|
95
|
-
export { buildOpeningCutoutGeometry, getOpeningCutoutBottomPadding, hasFlatOpeningCutoutBottom, } from './systems/wall/opening-cutout-geometry';
|
|
95
|
+
export { buildOpeningCutoutGeometry, buildOpeningCutoutShape, getOpeningCutoutBottomPadding, hasFlatOpeningCutoutBottom, } from './systems/wall/opening-cutout-geometry';
|
|
96
96
|
export { getWallHideState, WallCutout } from './systems/wall/wall-cutout';
|
|
97
|
-
export {
|
|
97
|
+
export { WallCutoutCache, } from './systems/wall/wall-cutout-cache';
|
|
98
|
+
export { getMaterialsForWall, getVisibleWallMaterials, } from './systems/wall/wall-materials';
|
|
98
99
|
// Wall internals re-exported so `@pascal-app/nodes`' registry-driven wall
|
|
99
100
|
// definition can compose them into `def.system` without duplicating the
|
|
100
101
|
// 800+ lines of CSG / mitering logic during Phase 3. These exports are
|
|
101
102
|
// removed in Phase 6 when the legacy mount points are deleted.
|
|
102
|
-
export { drainRebuiltWalls, getPendingWallRebuildCount, isWallInitialBuildActive, WallSystem, } from './systems/wall/wall-system';
|
|
103
|
+
export { drainRebuiltWalls, generateExtrudedWall, getPendingWallRebuildCount, isWallInitialBuildActive, runWallBuildFrame, WallSystem, } from './systems/wall/wall-system';
|
|
103
104
|
export { poseWindowMovingParts, WindowAnimationSystem, } from './systems/window/window-animation-system';
|
|
104
105
|
export { buildWindowPreviewMesh, WindowSystem } from './systems/window/window-system';
|
|
105
106
|
export { ZoneSystem } from './systems/zone/zone-system';
|
|
107
|
+
export { useImmersiveXRPresentation } from './xr/presentation-context';
|
package/dist/lib/csg-utils.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export declare const csgEvaluator: Evaluator;
|
|
|
7
7
|
export declare function computeGeometryBoundsTree(geometry: THREE.BufferGeometry): void;
|
|
8
8
|
export declare function prepareBrushForCSG(brush: Brush): void;
|
|
9
9
|
export declare function subtractCsgBrush(left: Brush, right: Brush, evaluator: Evaluator): Brush;
|
|
10
|
-
export { ADDITION, Brush, INTERSECTION, SUBTRACTION } from 'three-bvh-csg';
|
|
10
|
+
export { ADDITION, Brush, Evaluator, INTERSECTION, SUBTRACTION } from 'three-bvh-csg';
|
|
11
11
|
//# sourceMappingURL=csg-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csg-utils.d.ts","sourceRoot":"","sources":["../../src/lib/csg-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,KAAK,KAAK,EAAE,SAAS,EAAe,MAAM,eAAe,CAAA;AA4ClE,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,KAAK,CAAC,cAAc,GAC7B,KAAK,CAAC,cAAc,CAoCtB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,cAAc,CAE9D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAG3D;AAED,eAAO,MAAM,YAAY,WAAkB,CAAA;AAK3C,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,QAMvE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,QAI9C;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,KAAK,CAIvF;AAID,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"csg-utils.d.ts","sourceRoot":"","sources":["../../src/lib/csg-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,KAAK,KAAK,EAAE,SAAS,EAAe,MAAM,eAAe,CAAA;AA4ClE,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,KAAK,CAAC,cAAc,GAC7B,KAAK,CAAC,cAAc,CAoCtB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,cAAc,CAE9D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAG3D;AAED,eAAO,MAAM,YAAY,WAAkB,CAAA;AAK3C,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,QAMvE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,QAI9C;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAG,KAAK,CAIvF;AAID,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/lib/csg-utils.js
CHANGED
|
@@ -95,4 +95,4 @@ export function subtractCsgBrush(left, right, evaluator) {
|
|
|
95
95
|
}
|
|
96
96
|
// Re-export Brush + SUBTRACTION + ADDITION + INTERSECTION so kinds don't need a
|
|
97
97
|
// direct `three-bvh-csg` dependency.
|
|
98
|
-
export { ADDITION, Brush, INTERSECTION, SUBTRACTION } from 'three-bvh-csg';
|
|
98
|
+
export { ADDITION, Brush, Evaluator, INTERSECTION, SUBTRACTION } from 'three-bvh-csg';
|
package/dist/lib/isolation.d.ts
CHANGED
|
@@ -1,39 +1,23 @@
|
|
|
1
1
|
import type { AnyNodeId } from '@pascal-app/core';
|
|
2
2
|
import type { Object3D } from 'three';
|
|
3
|
-
/** True while
|
|
3
|
+
/** True while a subtree is isolated, including before its lazy meshes mount. */
|
|
4
4
|
export declare function isIsolationActive(): boolean;
|
|
5
|
-
/**
|
|
6
|
-
* Compute the union of every isolated subtree's `Object3D` descendants.
|
|
7
|
-
*
|
|
8
|
-
* Pure traversal — exported so future "focus mode" / debug tooling can
|
|
9
|
-
* reuse the same definition of "what's in the isolated set". Each root
|
|
10
|
-
* is walked via `Object3D.traverse` (the live Three.js graph, not the
|
|
11
|
-
* data-model `children` array — those can disagree when systems mount
|
|
12
|
-
* synthesized sub-meshes that the data model doesn't track).
|
|
13
|
-
*/
|
|
5
|
+
/** Include synthesized meshes below a selected native root, including hosted openings. */
|
|
14
6
|
export declare function collectIsolationSubtree(ids: ReadonlyArray<string>): Set<Object3D>;
|
|
15
7
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* isolated subtree by taking it off the scene layer.
|
|
19
|
-
*
|
|
20
|
-
* Why layers instead of `obj.visible = false`? Three.js's visibility
|
|
21
|
-
* flag *cascades* — hiding a parent hides every descendant — so we
|
|
22
|
-
* can't hide a host wall while keeping a door rendered inside it.
|
|
23
|
-
* Layer masks are per-object and don't cascade: `WebGLRenderer
|
|
24
|
-
* .projectObject` skips objects whose layer mask doesn't intersect the
|
|
25
|
-
* camera's, but always recurses into their children. So we can hide
|
|
26
|
-
* the wall and the door (hosted under it in the scene graph) still
|
|
27
|
-
* renders, with its local position relative to the wall preserved
|
|
28
|
-
* automatically by the matrix walk.
|
|
29
|
-
*
|
|
30
|
-
* The mask itself belongs to `lib/scene-visibility.ts`, which reconciles
|
|
31
|
-
* isolation with solo's shadow-caster pass, so {@link clearIsolation}
|
|
32
|
-
* gives an object back only what isolation took.
|
|
33
|
-
*
|
|
34
|
-
* Pass `null` to clear isolation (equivalent to calling
|
|
35
|
-
* {@link clearIsolation}).
|
|
8
|
+
* Select native subtrees without mutating the saved scene or cascading visibility
|
|
9
|
+
* through their hosts. The next draw also filters unregistered presentation geometry.
|
|
36
10
|
*/
|
|
37
11
|
export declare function applyIsolation(ids: ReadonlyArray<AnyNodeId> | null): void;
|
|
12
|
+
/**
|
|
13
|
+
* Reconcile immediately before viewport or snapshot rendering. Environment, sky,
|
|
14
|
+
* ground and instance batches can live outside sceneRegistry or mount asynchronously.
|
|
15
|
+
* Lights/cameras remain usable; masks do not cascade, so an isolated door can still
|
|
16
|
+
* render under its hidden wall. Collective renderers fall back to native geometry.
|
|
17
|
+
* The returned cleanup restores fog after the synchronous draw, before atmosphere
|
|
18
|
+
* owners can change it again. Do not hold this cleanup across async GPU readback.
|
|
19
|
+
*/
|
|
20
|
+
export declare function refreshIsolation(scene?: Object3D): () => void;
|
|
21
|
+
/** Restore even detached/unregistered meshes, without undoing solo or batching holds. */
|
|
38
22
|
export declare function clearIsolation(): void;
|
|
39
23
|
//# sourceMappingURL=isolation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isolation.d.ts","sourceRoot":"","sources":["../../src/lib/isolation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD,OAAO,KAAK,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"isolation.d.ts","sourceRoot":"","sources":["../../src/lib/isolation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD,OAAO,KAAK,EAAE,QAAQ,EAAS,MAAM,OAAO,CAAA;AAQ5C,gFAAgF;AAChF,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,0FAA0F;AAC1F,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CASjF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,CAAC,SAAS,CAAC,GAAG,IAAI,GAAG,IAAI,CAOzE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,IAAI,CA6B7D;AAED,yFAAyF;AACzF,wBAAgB,cAAc,IAAI,IAAI,CAKrC"}
|
package/dist/lib/isolation.js
CHANGED
|
@@ -1,91 +1,87 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { sceneRegistry } from '@pascal-app/core';
|
|
3
3
|
import { hideFromScene, showInScene } from './scene-visibility';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** True while an isolation filter is applied (see {@link applyIsolation}). */
|
|
4
|
+
let isolatedIds = null;
|
|
5
|
+
let heldObjects = new Set();
|
|
6
|
+
let liveScene;
|
|
7
|
+
const noop = () => { };
|
|
8
|
+
/** True while a subtree is isolated, including before its lazy meshes mount. */
|
|
10
9
|
export function isIsolationActive() {
|
|
11
|
-
return
|
|
10
|
+
return isolatedIds !== null;
|
|
12
11
|
}
|
|
13
|
-
/**
|
|
14
|
-
* Compute the union of every isolated subtree's `Object3D` descendants.
|
|
15
|
-
*
|
|
16
|
-
* Pure traversal — exported so future "focus mode" / debug tooling can
|
|
17
|
-
* reuse the same definition of "what's in the isolated set". Each root
|
|
18
|
-
* is walked via `Object3D.traverse` (the live Three.js graph, not the
|
|
19
|
-
* data-model `children` array — those can disagree when systems mount
|
|
20
|
-
* synthesized sub-meshes that the data model doesn't track).
|
|
21
|
-
*/
|
|
12
|
+
/** Include synthesized meshes below a selected native root, including hosted openings. */
|
|
22
13
|
export function collectIsolationSubtree(ids) {
|
|
23
14
|
const keep = new Set();
|
|
24
15
|
for (const id of ids) {
|
|
25
16
|
const root = sceneRegistry.nodes.get(id);
|
|
26
|
-
|
|
27
|
-
continue;
|
|
28
|
-
root.traverse((child) => {
|
|
17
|
+
root?.traverse((child) => {
|
|
29
18
|
keep.add(child);
|
|
30
19
|
});
|
|
31
20
|
}
|
|
32
21
|
return keep;
|
|
33
22
|
}
|
|
34
23
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* isolated subtree by taking it off the scene layer.
|
|
38
|
-
*
|
|
39
|
-
* Why layers instead of `obj.visible = false`? Three.js's visibility
|
|
40
|
-
* flag *cascades* — hiding a parent hides every descendant — so we
|
|
41
|
-
* can't hide a host wall while keeping a door rendered inside it.
|
|
42
|
-
* Layer masks are per-object and don't cascade: `WebGLRenderer
|
|
43
|
-
* .projectObject` skips objects whose layer mask doesn't intersect the
|
|
44
|
-
* camera's, but always recurses into their children. So we can hide
|
|
45
|
-
* the wall and the door (hosted under it in the scene graph) still
|
|
46
|
-
* renders, with its local position relative to the wall preserved
|
|
47
|
-
* automatically by the matrix walk.
|
|
48
|
-
*
|
|
49
|
-
* The mask itself belongs to `lib/scene-visibility.ts`, which reconciles
|
|
50
|
-
* isolation with solo's shadow-caster pass, so {@link clearIsolation}
|
|
51
|
-
* gives an object back only what isolation took.
|
|
52
|
-
*
|
|
53
|
-
* Pass `null` to clear isolation (equivalent to calling
|
|
54
|
-
* {@link clearIsolation}).
|
|
24
|
+
* Select native subtrees without mutating the saved scene or cascading visibility
|
|
25
|
+
* through their hosts. The next draw also filters unregistered presentation geometry.
|
|
55
26
|
*/
|
|
56
27
|
export function applyIsolation(ids) {
|
|
57
28
|
if (ids == null || ids.length === 0) {
|
|
58
29
|
clearIsolation();
|
|
59
30
|
return;
|
|
60
31
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// hide it and every descendant — *except* descendants that are
|
|
64
|
-
// themselves in `keep` (a kept node nested under a non-kept host:
|
|
65
|
-
// the isolated door under the hidden wall).
|
|
66
|
-
for (const [, obj] of sceneRegistry.nodes) {
|
|
67
|
-
if (keep.has(obj))
|
|
68
|
-
continue;
|
|
69
|
-
hideRecursive(obj, keep);
|
|
70
|
-
}
|
|
71
|
-
isolationActive = true;
|
|
32
|
+
isolatedIds = [...ids];
|
|
33
|
+
refreshIsolation();
|
|
72
34
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Reconcile immediately before viewport or snapshot rendering. Environment, sky,
|
|
37
|
+
* ground and instance batches can live outside sceneRegistry or mount asynchronously.
|
|
38
|
+
* Lights/cameras remain usable; masks do not cascade, so an isolated door can still
|
|
39
|
+
* render under its hidden wall. Collective renderers fall back to native geometry.
|
|
40
|
+
* The returned cleanup restores fog after the synchronous draw, before atmosphere
|
|
41
|
+
* owners can change it again. Do not hold this cleanup across async GPU readback.
|
|
42
|
+
*/
|
|
43
|
+
export function refreshIsolation(scene) {
|
|
44
|
+
if (!isolatedIds)
|
|
45
|
+
return noop;
|
|
46
|
+
if (scene)
|
|
47
|
+
liveScene = scene;
|
|
48
|
+
const keep = collectIsolationSubtree(isolatedIds);
|
|
49
|
+
const visited = new Set();
|
|
50
|
+
const hidden = new Set();
|
|
51
|
+
const visit = (object) => {
|
|
52
|
+
if (visited.has(object))
|
|
53
|
+
return;
|
|
54
|
+
visited.add(object);
|
|
55
|
+
const flags = object;
|
|
56
|
+
if (keep.has(object) || flags.isLight || flags.isCamera)
|
|
57
|
+
return;
|
|
58
|
+
hideFromScene(object, 'isolated');
|
|
59
|
+
hidden.add(object);
|
|
60
|
+
};
|
|
61
|
+
liveScene?.traverse(visit);
|
|
62
|
+
// Also covers not-yet-attached registered roots and imperative callers without a scene.
|
|
63
|
+
for (const object of sceneRegistry.nodes.values())
|
|
64
|
+
object.traverse(visit);
|
|
65
|
+
for (const object of heldObjects)
|
|
66
|
+
if (!hidden.has(object))
|
|
67
|
+
showInScene(object, 'isolated');
|
|
68
|
+
heldObjects = hidden;
|
|
69
|
+
const atmosphere = scene;
|
|
70
|
+
if (!atmosphere?.isScene)
|
|
71
|
+
return noop;
|
|
72
|
+
const { fog, fogNode } = atmosphere;
|
|
73
|
+
atmosphere.fog = null;
|
|
74
|
+
atmosphere.fogNode = null;
|
|
75
|
+
return () => {
|
|
76
|
+
atmosphere.fog = fog;
|
|
77
|
+
atmosphere.fogNode = fogNode;
|
|
78
|
+
};
|
|
80
79
|
}
|
|
80
|
+
/** Restore even detached/unregistered meshes, without undoing solo or batching holds. */
|
|
81
81
|
export function clearIsolation() {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
showInScene(child, 'isolated');
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
isolationActive = false;
|
|
82
|
+
for (const object of heldObjects)
|
|
83
|
+
showInScene(object, 'isolated');
|
|
84
|
+
heldObjects.clear();
|
|
85
|
+
isolatedIds = null;
|
|
86
|
+
liveScene = undefined;
|
|
91
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/lib/materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EAGnB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,uBAAuB,EAA4B,MAAM,cAAc,CAAA;AAOhF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,CAAA;AAChD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAA;AAEjE,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAQpD,CAAA;AAID,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAQrD,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAQpD,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAQzD,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAK5E,CAAA;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,WAAW,EACnB,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAKR;AAOD,eAAO,MAAM,aAAa,yBAKxB,CAAA;AAsBF,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AA2ED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAWtF;AAED,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM,CAK/D;AA6SD,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,EAChD,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,QAcjD;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,GAAE,aAA0B,GAClC,KAAK,CAAC,QAAQ,CAchB;AAED,wBAAgB,2BAA2B,CACzC,cAAc,CAAC,EAAE,MAAM,EACvB,OAAO,GAAE,aAA0B,GAClC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAIvB;AAED,wBAAgB,cAAc,CAC5B,QAAQ,CAAC,EAAE,cAAc,EACzB,OAAO,GAAE,aAA0B,GAClC,KAAK,CAAC,QAAQ,CAqChB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,cAAc,EAAE,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,GAAG,SAAS,EAClE,OAAO,GAAE,aAA0B,GAClC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAOvB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,aAA0B,EACnC,SAAS,SAAM,GACd,KAAK,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/lib/materials.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/materials.js
CHANGED
|
@@ -475,7 +475,8 @@ export function resolveSlotDefaultMaterial(slotDefault, shading = 'rendered', ro
|
|
|
475
475
|
return (createMaterialFromPresetRef(slotDefault, shading) ??
|
|
476
476
|
cachedDefaultMaterial(`slot-#ffffff-${roughness}`, '#ffffff', roughness, shading));
|
|
477
477
|
}
|
|
478
|
-
|
|
478
|
+
const color = slotDefault.startsWith('#') ? slotDefault.toLowerCase() : slotDefault;
|
|
479
|
+
return cachedDefaultMaterial(`slot-${color}-${roughness}`, color, roughness, shading);
|
|
479
480
|
}
|
|
480
481
|
export function createDefaultMaterial(color = '#ffffff', roughness = 0.9, shading = 'rendered', side = THREE.FrontSide) {
|
|
481
482
|
const resolvedSide = resolveNodeMaterialSide(side);
|
|
@@ -45,8 +45,9 @@ export declare function detectRendererCapability({ canvas, gpu, powerPreference,
|
|
|
45
45
|
powerPreference?: RendererPowerPreference;
|
|
46
46
|
webgpuTimeoutMs?: number;
|
|
47
47
|
}): Promise<RendererCapability>;
|
|
48
|
-
export declare function initializeGpuRenderer<Renderer extends InitializableRenderer>({ createRenderer, gpu, powerPreference, probeCanvas, webgpuTimeoutMs, }: {
|
|
48
|
+
export declare function initializeGpuRenderer<Renderer extends InitializableRenderer>({ createRenderer, forceWebGL, gpu, powerPreference, probeCanvas, webgpuTimeoutMs, }: {
|
|
49
49
|
createRenderer: (parameters: RendererBackendParameters) => Renderer;
|
|
50
|
+
forceWebGL?: boolean;
|
|
50
51
|
gpu?: RendererGpu | null;
|
|
51
52
|
powerPreference?: RendererPowerPreference;
|
|
52
53
|
probeCanvas?: RendererCapabilityCanvas | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer-capability.d.ts","sourceRoot":"","sources":["../../src/lib/renderer-capability.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,CAAC,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAA;CACzC,CAAA;AAED,oGAAoG;AACpG,MAAM,MAAM,uBAAuB,GAAG,kBAAkB,GAAG,WAAW,CAAA;AAEtE,KAAK,kBAAkB,GAAG;IACxB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC3B,aAAa,CAAC,UAAU,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC9E,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAA;CACtF,CAAA;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,OAAO,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAC3D;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACzC;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAA;AAE9C,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,4BAA4B,CAAC,QAAQ,IAC7C;IAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACpE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAA;AAiD9C,wBAAsB,wBAAwB,CAAC,EAC7C,MAAwB,EACxB,GAAkB,EAClB,eAAe,EACf,eAAkD,GACnD,GAAE;IACD,MAAM,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAA;IACxC,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,uBAAuB,CAAA;IACzC,eAAe,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2BnC;AAED,wBAAsB,qBAAqB,CAAC,QAAQ,SAAS,qBAAqB,EAAE,EAClF,cAAc,EACd,GAAG,EACH,eAAe,EACf,WAA6B,EAC7B,eAAkD,GACnD,EAAE;IACD,cAAc,EAAE,CAAC,UAAU,EAAE,yBAAyB,KAAK,QAAQ,CAAA;IACnE,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,uBAAuB,CAAA;IACzC,WAAW,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAA;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,GAAG,OAAO,CAAC,4BAA4B,CAAC,QAAQ,CAAC,CAAC,CAyClD"}
|
|
1
|
+
{"version":3,"file":"renderer-capability.d.ts","sourceRoot":"","sources":["../../src/lib/renderer-capability.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,CAAC,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAA;CACzC,CAAA;AAED,oGAAoG;AACpG,MAAM,MAAM,uBAAuB,GAAG,kBAAkB,GAAG,WAAW,CAAA;AAEtE,KAAK,kBAAkB,GAAG;IACxB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC3B,aAAa,CAAC,UAAU,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC9E,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAA;CACtF,CAAA;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,OAAO,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAC3D;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACzC;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAA;AAE9C,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,4BAA4B,CAAC,QAAQ,IAC7C;IAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACpE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAA;AAiD9C,wBAAsB,wBAAwB,CAAC,EAC7C,MAAwB,EACxB,GAAkB,EAClB,eAAe,EACf,eAAkD,GACnD,GAAE;IACD,MAAM,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAA;IACxC,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,uBAAuB,CAAA;IACzC,eAAe,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2BnC;AAED,wBAAsB,qBAAqB,CAAC,QAAQ,SAAS,qBAAqB,EAAE,EAClF,cAAc,EACd,UAAkB,EAClB,GAAG,EACH,eAAe,EACf,WAA6B,EAC7B,eAAkD,GACnD,EAAE;IACD,cAAc,EAAE,CAAC,UAAU,EAAE,yBAAyB,KAAK,QAAQ,CAAA;IACnE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,uBAAuB,CAAA;IACzC,WAAW,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAA;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,GAAG,OAAO,CAAC,4BAA4B,CAAC,QAAQ,CAAC,CAAC,CAyClD"}
|
|
@@ -71,10 +71,10 @@ export async function detectRendererCapability({ canvas = browserCanvas(), gpu =
|
|
|
71
71
|
}
|
|
72
72
|
return { error: capabilityError, status: 'unsupported' };
|
|
73
73
|
}
|
|
74
|
-
export async function initializeGpuRenderer({ createRenderer, gpu, powerPreference, probeCanvas = browserCanvas(), webgpuTimeoutMs = WEBGPU_INITIALIZATION_TIMEOUT_MS, }) {
|
|
74
|
+
export async function initializeGpuRenderer({ createRenderer, forceWebGL = false, gpu, powerPreference, probeCanvas = browserCanvas(), webgpuTimeoutMs = WEBGPU_INITIALIZATION_TIMEOUT_MS, }) {
|
|
75
75
|
const capability = await detectRendererCapability({
|
|
76
76
|
canvas: probeCanvas,
|
|
77
|
-
gpu,
|
|
77
|
+
gpu: forceWebGL ? null : gpu,
|
|
78
78
|
powerPreference,
|
|
79
79
|
webgpuTimeoutMs,
|
|
80
80
|
});
|
|
@@ -60,10 +60,12 @@ function applyHold(obj, hold) {
|
|
|
60
60
|
// A batched wall is both drawn and shadowed by the merged mesh, so it stays
|
|
61
61
|
// out of the shadow pass too — enabling the shadow-only bit would submit its
|
|
62
62
|
// triangles a second time, on top of the copy the batch already casts.
|
|
63
|
+
if (hold.reasons.has('isolated'))
|
|
64
|
+
obj.layers.disable(SHADOW_ONLY_LAYER);
|
|
63
65
|
if (hold.reasons.has('batched') || hold.reasons.has('wall-batched')) {
|
|
64
66
|
obj.layers.enable(BATCHED_LAYER);
|
|
65
67
|
return;
|
|
66
68
|
}
|
|
67
|
-
if (hold.reasons.has('shadow-only'))
|
|
69
|
+
if (!hold.reasons.has('isolated') && hold.reasons.has('shadow-only'))
|
|
68
70
|
obj.layers.enable(SHADOW_ONLY_LAYER);
|
|
69
71
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Camera, type Scene } from 'three';
|
|
2
2
|
import { type WebGPURenderer } from 'three/webgpu';
|
|
3
|
+
import type { SceneAtmosphereSource } from '../components/viewer/scene-atmosphere';
|
|
3
4
|
import { type EdgeMode } from './edge-style';
|
|
4
5
|
export declare const THUMBNAIL_WIDTH = 1920;
|
|
5
6
|
export declare const THUMBNAIL_HEIGHT = 1080;
|
|
@@ -43,9 +44,10 @@ export type SnapshotPipeline = {
|
|
|
43
44
|
}) => Promise<SnapshotCaptureResult>;
|
|
44
45
|
dispose: () => void;
|
|
45
46
|
};
|
|
46
|
-
export declare function createSnapshotPipeline({ renderer, scene, camera, }: {
|
|
47
|
+
export declare function createSnapshotPipeline({ renderer, scene, camera, atmosphere, }: {
|
|
47
48
|
renderer: WebGPURenderer;
|
|
48
49
|
scene: Scene;
|
|
49
50
|
camera: Camera;
|
|
51
|
+
atmosphere?: SceneAtmosphereSource | null;
|
|
50
52
|
}): Promise<SnapshotPipeline | null>;
|
|
51
53
|
//# sourceMappingURL=snapshot-pipeline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-pipeline.d.ts","sourceRoot":"","sources":["../../src/lib/snapshot-pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAkB,KAAK,KAAK,EAAoB,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"snapshot-pipeline.d.ts","sourceRoot":"","sources":["../../src/lib/snapshot-pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAkB,KAAK,KAAK,EAAoB,MAAM,OAAO,CAAA;AAoBjF,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAA;AAElF,OAAO,EAAE,KAAK,QAAQ,EAAqC,MAAM,cAAc,CAAA;AAK/E,eAAO,MAAM,eAAe,OAAO,CAAA;AACnC,eAAO,MAAM,gBAAgB,OAAO,CAAA;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,aAAa,eAAe,CAAA;AACzC,eAAO,MAAM,gBAAgB,MAAM,CAAA;AAEnC,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAUrC,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAElE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gBAAgB,EAAE,CAAC,EACjB,KAAK,EACL,WAAW,EACX,KAAK,EACL,KAAK,EACL,MAAM,GACP,EAAE;QACD,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,OAAO,CAAA;QACpB,KAAK,EAAE,OAAO,CAAA;QACd,KAAK,EAAE,QAAQ,CAAA;QACf,MAAM,EAAE,MAAM,CAAA;KACf,KAAK,IAAI,CAAA;IACV,OAAO,EAAE,CAAC,EACR,WAAW,EACX,UAAU,EACV,YAAY,GACb,EAAE;QACD,WAAW,CAAC,EAAE,mBAAmB,CAAA;QACjC,UAAU,CAAC,EAAE,kBAAkB,CAAA;QAC/B,YAAY,CAAC,EAAE,YAAY,CAAA;KAC5B,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;IACpC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAA;AAgBD,wBAAsB,sBAAsB,CAAC,EAC3C,QAAQ,EACR,KAAK,EACL,MAAM,EACN,UAAiB,GAClB,EAAE;IACD,QAAQ,EAAE,cAAc,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAA;CAC1C,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA0SnC"}
|
|
@@ -2,8 +2,8 @@ import { Color, Matrix4, UnsignedByteType } from 'three';
|
|
|
2
2
|
import { ssgi } from 'three/addons/tsl/display/SSGINode.js';
|
|
3
3
|
import { denoise } from 'three/examples/jsm/tsl/display/DenoiseNode.js';
|
|
4
4
|
import { fxaa } from 'three/examples/jsm/tsl/display/FXAANode.js';
|
|
5
|
-
import { convertToTexture, diffuseColor, float, mix, mrt, normalView, output,
|
|
6
|
-
import { RenderPipeline, RenderTarget } from 'three/webgpu';
|
|
5
|
+
import { convertToTexture, diffuseColor, float, mix, mrt, normalView, output, sample, saturation, screenUV, smoothstep, uniform, vec3, vec4, } from 'three/tsl';
|
|
6
|
+
import { PassNode, RenderPipeline, RenderTarget, } from 'three/webgpu';
|
|
7
7
|
import { GRADE_PARAMS, SSGI_PARAMS } from '../components/viewer/post-processing';
|
|
8
8
|
import { backdropGradient, deepSkyColor, horizonHazeColor } from './backdrop';
|
|
9
9
|
import { edgeColorFor, edgeOpacityScaleFor } from './edge-style';
|
|
@@ -29,7 +29,22 @@ function clampSnapshotSize(width, height) {
|
|
|
29
29
|
const scale = SNAPSHOT_MAX_EDGE / maxEdge;
|
|
30
30
|
return { w: Math.round(width * scale), h: Math.round(height * scale) };
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
class SnapshotScenePass extends PassNode {
|
|
33
|
+
updateBefore(frame) {
|
|
34
|
+
const renderer = frame.renderer;
|
|
35
|
+
const clearAlpha = renderer.getClearAlpha();
|
|
36
|
+
// RTTNode resets clear alpha in r186. The geometry mask must be cleared
|
|
37
|
+
// inside this pass, not inherited from the outer snapshot render.
|
|
38
|
+
renderer.setClearAlpha(0);
|
|
39
|
+
try {
|
|
40
|
+
return super.updateBefore(frame);
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
renderer.setClearAlpha(clearAlpha);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export async function createSnapshotPipeline({ renderer, scene, camera, atmosphere = null, }) {
|
|
33
48
|
try {
|
|
34
49
|
if (renderer.init)
|
|
35
50
|
await renderer.init();
|
|
@@ -49,10 +64,9 @@ export async function createSnapshotPipeline({ renderer, scene, camera, }) {
|
|
|
49
64
|
const inkColorUniform = uniform(new Color('#1a1d24'));
|
|
50
65
|
const inkOpacityUniform = uniform(0.5);
|
|
51
66
|
const inkOpacityScaleUniform = uniform(1);
|
|
52
|
-
// pass
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
const scenePass = pass(scene, camera);
|
|
67
|
+
// The scene pass owns MRT and its transparent clear, including when nested
|
|
68
|
+
// inside FXAA's intermediate render target.
|
|
69
|
+
const scenePass = new SnapshotScenePass('color', scene, camera);
|
|
56
70
|
scenePass.setMRT(mrt({
|
|
57
71
|
output,
|
|
58
72
|
diffuseColor,
|
|
@@ -111,13 +125,15 @@ export async function createSnapshotPipeline({ renderer, scene, camera, }) {
|
|
|
111
125
|
const ndc = vec4(screenUV.x.mul(2).sub(1), float(1).sub(screenUV.y).mul(2).sub(1), 1, 1);
|
|
112
126
|
const viewRay = bgProjInvUniform.mul(ndc);
|
|
113
127
|
const worldDir = bgCamWorldUniform.mul(vec4(viewRay.xyz, 0)).xyz.normalize();
|
|
114
|
-
const ungradedBgGradient =
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
const ungradedBgGradient = atmosphere
|
|
129
|
+
? atmosphere.skyRadiance(worldDir)
|
|
130
|
+
: backdropGradient({
|
|
131
|
+
dirY: worldDir.y,
|
|
132
|
+
background: bgColorUniform,
|
|
133
|
+
haze: bgHazeUniform,
|
|
134
|
+
sky: bgSkyUniform,
|
|
135
|
+
skyDeep: bgSkyDeepUniform,
|
|
136
|
+
});
|
|
121
137
|
const bgGradient = mix(ungradedBgGradient, gradeRgb(ungradedBgGradient), gradeMixUniform);
|
|
122
138
|
const alpha = scenePassColor.a;
|
|
123
139
|
const finalOutput = vec4(mix(sceneRgb, mix(bgGradient, sceneRgb, alpha), bgMixUniform), mix(alpha, float(1), bgMixUniform));
|
|
@@ -159,8 +175,6 @@ export async function createSnapshotPipeline({ renderer, scene, camera, }) {
|
|
|
159
175
|
renderTarget.setSize(captureWidth, captureHeight);
|
|
160
176
|
}
|
|
161
177
|
try {
|
|
162
|
-
;
|
|
163
|
-
renderer.setClearAlpha(0);
|
|
164
178
|
renderer.setRenderTarget(renderTarget);
|
|
165
179
|
pipeline.render();
|
|
166
180
|
}
|
|
@@ -268,6 +282,8 @@ export async function createSnapshotPipeline({ renderer, scene, camera, }) {
|
|
|
268
282
|
dispose: () => {
|
|
269
283
|
pipeline.dispose();
|
|
270
284
|
renderTarget.dispose();
|
|
285
|
+
scenePass.dispose();
|
|
286
|
+
giPass.dispose();
|
|
271
287
|
},
|
|
272
288
|
};
|
|
273
289
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyNode, BaseNode, BuildingNode, LevelNode, ZoneNode } from '@pascal-app/core';
|
|
1
|
+
import type { AnyNode, BaseNode, BuildingNode, LevelNode, UnitNode, ZoneNode } from '@pascal-app/core';
|
|
2
2
|
import type { Object3D } from 'three';
|
|
3
3
|
import type { EdgeMode } from '../lib/edge-style';
|
|
4
4
|
import type { ColorPreset, RenderShading } from '../lib/materials';
|
|
@@ -17,6 +17,8 @@ type Outliner = {
|
|
|
17
17
|
};
|
|
18
18
|
type ViewerState = {
|
|
19
19
|
selection: SelectionPath;
|
|
20
|
+
focusedUnitId: UnitNode['id'] | null;
|
|
21
|
+
setFocusedUnit: (id: UnitNode['id'] | null) => void;
|
|
20
22
|
previewSelectedIds: BaseNode['id'][];
|
|
21
23
|
setPreviewSelectedIds: (ids: BaseNode['id'][]) => void;
|
|
22
24
|
/** Host-owned selection highlights rendered through the viewer's native
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"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"}
|
package/dist/store/use-viewer.js
CHANGED
|
@@ -122,6 +122,8 @@ function normalizePersistedViewerState(value) {
|
|
|
122
122
|
}
|
|
123
123
|
const useViewer = create()(persist((set) => ({
|
|
124
124
|
selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [] },
|
|
125
|
+
focusedUnitId: null,
|
|
126
|
+
setFocusedUnit: (focusedUnitId) => set({ focusedUnitId }),
|
|
125
127
|
previewSelectedIds: [],
|
|
126
128
|
setPreviewSelectedIds: (ids) => set({ previewSelectedIds: ids }),
|
|
127
129
|
externalSelectedIds: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"door-system.d.ts","sourceRoot":"","sources":["../../../src/systems/door/door-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAYd,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA2D9B,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"door-system.d.ts","sourceRoot":"","sources":["../../../src/systems/door/door-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAYd,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA2D9B,eAAO,MAAM,UAAU,YAuHtB,CAAA;AA0pCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,KAAK,CAAC,QAAQ,GAAG,SAAS,EAChC,KAAK,EAAE,MAAM,GACZ,OAAO,CA6GT;AAyuCD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC,IAAI,CAI/D"}
|
|
@@ -154,8 +154,9 @@ export const DoorSystem = () => {
|
|
|
154
154
|
// Rebuild the parent wall so its cutout reflects the updated door geometry
|
|
155
155
|
// Avoid triggering expensive wall CSG rebuilds while the door is being interactively moved/duplicated.
|
|
156
156
|
// The editor tools will request a final wall rebuild on commit.
|
|
157
|
-
const
|
|
158
|
-
|
|
157
|
+
const metadata = effectiveNode.metadata;
|
|
158
|
+
const deferParentRebuild = !!metadata?.isTransient || !!metadata?.deferParentRebuild;
|
|
159
|
+
if (!deferParentRebuild && effectiveNode.parentId) {
|
|
159
160
|
useScene.getState().dirtyNodes.add(effectiveNode.parentId);
|
|
160
161
|
}
|
|
161
162
|
}
|
|
@@ -777,9 +778,21 @@ function addDoorLeaf(mesh, { leafWidth, leafHeight, leafCenterX, leafCenterY, le
|
|
|
777
778
|
const hingeH = 0.1;
|
|
778
779
|
const hingeW = 0.024;
|
|
779
780
|
const hingeD = leafDepth + 0.016;
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
781
|
+
const hingeRadii = roundedBoundary?.radii ?? openingTopRadii;
|
|
782
|
+
const cornerDrop = openingShape === 'rounded'
|
|
783
|
+
? hingeSide === 'left'
|
|
784
|
+
? hingeRadii.topLeft
|
|
785
|
+
: hingeRadii.topRight
|
|
786
|
+
: openingShape === 'arch'
|
|
787
|
+
? getClampedArchHeight(leafWidth, leafHeight, archHeight)
|
|
788
|
+
: 0;
|
|
789
|
+
// Hinges need their full height supported by the straight jamb below the curve.
|
|
790
|
+
const straightEdgeTop = leafTop - cornerDrop;
|
|
791
|
+
for (const hingeY of [leafBottom + 0.25, (leafBottom + leafTop) / 2, leafTop - 0.25]) {
|
|
792
|
+
if (hingeY + hingeH / 2 > straightEdgeTop + 1e-6)
|
|
793
|
+
continue;
|
|
794
|
+
addBox(mesh, hardwareMaterial, hingeW, hingeH, hingeD, hingeMarkerX, hingeY, 0);
|
|
795
|
+
}
|
|
783
796
|
}
|
|
784
797
|
// When the leaf is swung open it projects into the room and would otherwise
|
|
785
798
|
// win a top-down selection click over the floor beneath it. Drop only the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floor-elevation-system.d.ts","sourceRoot":"","sources":["../../../src/systems/floor-elevation/floor-elevation-system.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"floor-elevation-system.d.ts","sourceRoot":"","sources":["../../../src/systems/floor-elevation/floor-elevation-system.tsx"],"names":[],"mappings":"AA8DA;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,oBAAoB,YA2LhC,CAAA"}
|