@pascal-app/viewer 0.7.0 → 0.8.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/dist/components/renderers/column/column-renderer.d.ts.map +1 -1
- package/dist/components/renderers/column/column-renderer.js +5 -2
- package/dist/components/renderers/fence/fence-renderer.d.ts.map +1 -1
- package/dist/components/renderers/fence/fence-renderer.js +2 -16
- package/dist/components/renderers/slab/slab-renderer.js +1 -1
- package/dist/components/renderers/stair/stair-renderer.js +3 -3
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +1 -1
- package/dist/components/renderers/stair-segment/stair-segment-renderer.js +20 -1
- package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
- package/dist/components/viewer/frame-limiter.js +5 -1
- package/dist/components/viewer/index.d.ts +1 -0
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +7 -7
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +0 -21
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +2 -3
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +4 -11
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +1 -1
- package/dist/systems/fence/fence-system.d.ts.map +1 -1
- package/dist/systems/fence/fence-system.js +1 -1
- package/dist/systems/guide/guide-system.d.ts.map +1 -1
- package/dist/systems/guide/guide-system.js +1 -26
- package/dist/systems/item/item-system.js +1 -1
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +16 -13
- package/dist/systems/scan/scan-system.d.ts.map +1 -1
- package/dist/systems/scan/scan-system.js +1 -26
- package/dist/systems/slab/slab-system.d.ts.map +1 -1
- package/dist/systems/slab/slab-system.js +1 -1
- package/dist/systems/stair/stair-system.js +9 -11
- package/dist/systems/wall/wall-system.d.ts +1 -1
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +8 -5
- package/package.json +3 -3
- package/dist/lib/suppress-three-clock-warning.d.ts +0 -25
- package/dist/lib/suppress-three-clock-warning.d.ts.map +0 -1
- package/dist/lib/suppress-three-clock-warning.js +0 -51
- package/dist/systems/export/export-system.d.ts +0 -2
- package/dist/systems/export/export-system.d.ts.map +0 -1
- package/dist/systems/export/export-system.js +0 -60
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts +0 -14
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts.map +0 -1
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.js +0 -155
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts +0 -6
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts.map +0 -1
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.js +0 -75
- package/dist/systems/item-mesh-metadata/sync-request.d.ts +0 -7
- package/dist/systems/item-mesh-metadata/sync-request.d.ts.map +0 -1
- package/dist/systems/item-mesh-metadata/sync-request.js +0 -25
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/column/column-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAkC,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"column-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/column/column-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAkC,MAAM,kBAAkB,CAAA;AAs6ClF,eAAO,MAAM,cAAc,GAAI,UAAU;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,4CA0E5D,CAAA"}
|
|
@@ -348,6 +348,9 @@ function Flutes({ node, shaftY, shaftHeight, }) {
|
|
|
348
348
|
return (_jsx(MappedCylinder, { height: shaftHeight * 0.92, position: [x, shaftY + shaftHeight / 2, z], radius: fluteRadius, segments: 8 }, index));
|
|
349
349
|
}) }));
|
|
350
350
|
}
|
|
351
|
+
function DravidianPanelFace({ position, rotation = 0, panelHeight, panelWidth, rail, reliefDepth, panelShape, }) {
|
|
352
|
+
return (_jsxs("group", { position: position, rotation: [0, rotation, 0], children: [_jsx(MappedBox, { depth: reliefDepth, height: rail, position: [0, panelHeight / 2, 0], softenEdges: false, width: panelWidth }), _jsx(MappedBox, { depth: reliefDepth, height: rail, position: [0, -panelHeight / 2, 0], softenEdges: false, width: panelWidth }), _jsx(MappedBox, { depth: reliefDepth, height: panelHeight, position: [panelWidth / 2, 0, 0], softenEdges: false, width: rail }), _jsx(MappedBox, { depth: reliefDepth, height: panelHeight, position: [-panelWidth / 2, 0, 0], softenEdges: false, width: rail }), panelShape === 'diamond' && (_jsx(MappedBox, { depth: reliefDepth, height: panelHeight * 0.42, position: [0, 0, 0], rotation: [0, 0, Math.PI / 4], softenEdges: false, width: rail * 1.2 })), panelShape === 'arched' && (_jsx(MappedTorus, { arc: Math.PI, position: [0, panelHeight * 0.28, 0], ringRadius: panelWidth * 0.42, scaleX: panelWidth * 0.42, scaleY: rail, scaleZ: reliefDepth, tubeRadius: Math.max(rail, reliefDepth) * 0.18 }))] }));
|
|
353
|
+
}
|
|
351
354
|
function DravidianShaftPanels({ node, shaftY, shaftHeight, }) {
|
|
352
355
|
const panelCount = Math.max(node.panelCount ?? 0, node.style === 'dravidian-carved' || node.shaftDetail === 'panelled' ? 3 : 0);
|
|
353
356
|
if (panelCount <= 0 || shaftHeight <= 0)
|
|
@@ -360,10 +363,10 @@ function DravidianShaftPanels({ node, shaftY, shaftHeight, }) {
|
|
|
360
363
|
const reliefDepth = Math.max(0.012, node.panelInsetDepth ?? node.width * 0.025);
|
|
361
364
|
const rows = Array.from({ length: panelCount }, (_, index) => (index + 1) / (panelCount + 1));
|
|
362
365
|
const panelShape = node.panelShape ?? 'rectangle';
|
|
363
|
-
const
|
|
366
|
+
const faceProps = { panelHeight, panelWidth, rail, reliefDepth, panelShape };
|
|
364
367
|
return (_jsx("group", { children: rows.map((t, rowIndex) => {
|
|
365
368
|
const y = shaftY + shaftHeight * t;
|
|
366
|
-
return (_jsxs("group", { children: [_jsx(
|
|
369
|
+
return (_jsxs("group", { children: [_jsx(DravidianPanelFace, { position: [0, y, shaftDepth / 2 + reliefDepth / 2], ...faceProps }), _jsx(DravidianPanelFace, { position: [0, y, -shaftDepth / 2 - reliefDepth / 2], ...faceProps }), _jsx(DravidianPanelFace, { position: [shaftWidth / 2 + reliefDepth / 2, y, 0], rotation: Math.PI / 2, ...faceProps }), _jsx(DravidianPanelFace, { position: [-shaftWidth / 2 - reliefDepth / 2, y, 0], rotation: Math.PI / 2, ...faceProps })] }, rowIndex));
|
|
367
370
|
}) }));
|
|
368
371
|
}
|
|
369
372
|
function SpiralRibs({ node, shaftY, shaftHeight, }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fence-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/fence/fence-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"fence-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/fence/fence-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,kBAAkB,CAAA;AAMxE,eAAO,MAAM,aAAa,GAAI,UAAU;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,4CAsB1D,CAAA"}
|
|
@@ -2,25 +2,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useRegistry, useScene } from '@pascal-app/core';
|
|
3
3
|
import { useLayoutEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { useNodeEvents } from '../../../hooks/use-node-events';
|
|
5
|
-
import {
|
|
5
|
+
import { DEFAULT_STAIR_MATERIAL } from '../../../lib/materials';
|
|
6
6
|
export const FenceRenderer = ({ node }) => {
|
|
7
7
|
const ref = useRef(null);
|
|
8
8
|
const handlers = useNodeEvents(node, 'fence');
|
|
9
|
-
const material = useMemo(() =>
|
|
10
|
-
const presetMaterial = createMaterialFromPresetRef(node.materialPreset);
|
|
11
|
-
if (presetMaterial)
|
|
12
|
-
return presetMaterial;
|
|
13
|
-
const mat = node.material;
|
|
14
|
-
if (!mat)
|
|
15
|
-
return DEFAULT_STAIR_MATERIAL;
|
|
16
|
-
return createMaterial(mat);
|
|
17
|
-
}, [
|
|
18
|
-
node.materialPreset,
|
|
19
|
-
node.material,
|
|
20
|
-
node.material?.preset,
|
|
21
|
-
node.material?.properties,
|
|
22
|
-
node.material?.texture,
|
|
23
|
-
]);
|
|
9
|
+
const material = useMemo(() => DEFAULT_STAIR_MATERIAL, []);
|
|
24
10
|
useRegistry(node.id, 'fence', ref);
|
|
25
11
|
useLayoutEffect(() => {
|
|
26
12
|
useScene.getState().markDirty(node.id);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { getMaterialPresetByRef, useRegistry } from '@pascal-app/core';
|
|
3
|
-
import { useMemo, useRef } from 'react';
|
|
3
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import * as THREE from 'three';
|
|
5
5
|
import { useNodeEvents } from '../../../hooks/use-node-events';
|
|
6
6
|
import { applyMaterialPresetToMaterials, createMaterial, DEFAULT_SLAB_MATERIAL, } from '../../../lib/materials';
|
|
@@ -43,7 +43,7 @@ export const StairRenderer = ({ node }) => {
|
|
|
43
43
|
straightPlaceholderGeometry.dispose();
|
|
44
44
|
};
|
|
45
45
|
}, [straightPlaceholderGeometry]);
|
|
46
|
-
return (_jsxs("group", { "position-x": node.position[0], "position-z": node.position[2], ref: ref, "rotation-y": node.rotation, visible: node.visible, ...handlers, children: [isSegmentBasedStair ? (_jsx("mesh", { castShadow: true, geometry: straightPlaceholderGeometry, material: straightBodyMaterials, name: "merged-stair", receiveShadow: true })) : null,
|
|
46
|
+
return (_jsxs("group", { "position-x": node.position[0], "position-z": node.position[2], ref: ref, "rotation-y": node.rotation, visible: node.visible, ...handlers, children: [isSegmentBasedStair ? (_jsx("mesh", { castShadow: true, geometry: straightPlaceholderGeometry, material: straightBodyMaterials, name: "merged-stair", receiveShadow: true })) : null, isSegmentBasedStair ? null : (_jsx(CurvedStairBody, { bodyMaterials: straightBodyMaterials, stair: node })), _jsx(StairRailings, { material: railingMaterial, stair: node }), isSegmentBasedStair ? (_jsx("group", { name: "segments-wrapper", visible: false, children: (node.children ?? []).map((childId) => (_jsx(NodeRenderer, { nodeId: childId }, childId))) })) : null] }));
|
|
47
47
|
};
|
|
48
48
|
function StairRailings({ stair, material }) {
|
|
49
49
|
const nodes = useScene((state) => state.nodes);
|
|
@@ -107,7 +107,7 @@ function StairRailings({ stair, material }) {
|
|
|
107
107
|
return (_jsxs("group", { children: [_jsx(RailSegment, { end: [nextPoint[2], nextPoint[1] + railHeight, nextPoint[0]], material: material, radius: railRadius, start: [point[2], point[1] + railHeight, point[0]] }), _jsx(RailSegment, { end: [nextPoint[2], nextPoint[1] + midRailHeight, nextPoint[0]], material: material, radius: railRadius * 0.8, start: [point[2], point[1] + midRailHeight, point[0]] })] }, `${segmentPath.layout.segment.id}-${sidePath.side}-rail-${pointIndex}`));
|
|
108
108
|
})] }, `${segmentPath.layout.segment.id}-${sidePath.side}-${sideIndex}`))) }, `${segmentPath.layout.segment.id}-railing`))), railPaths.slice(1).map((segmentPath, index) => {
|
|
109
109
|
const previousPath = railPaths[index];
|
|
110
|
-
if (!previousPath
|
|
110
|
+
if (!(previousPath && segmentPath.connectFromPrevious))
|
|
111
111
|
return null;
|
|
112
112
|
if (previousPath.layout.segment.segmentType === 'landing')
|
|
113
113
|
return null;
|
|
@@ -191,7 +191,7 @@ function CurvedStairBody({ stair, bodyMaterials, }) {
|
|
|
191
191
|
const spiralLandingThickness = isSpiral && (stair.topLandingMode ?? 'none') === 'integrated'
|
|
192
192
|
? Math.max(0.02, totalRise - spiralLastStepTop)
|
|
193
193
|
: 0;
|
|
194
|
-
return (_jsxs("group", { name: isSpiral ? 'spiral-stair' : 'curved-stair', children: [isSpiral && (stair.showCenterColumn ?? true) ? (_jsx("mesh", { castShadow: true,
|
|
194
|
+
return (_jsxs("group", { name: isSpiral ? 'spiral-stair' : 'curved-stair', children: [isSpiral && (stair.showCenterColumn ?? true) ? (_jsx("mesh", { castShadow: true, material: sideMaterial, name: "stair-side", position: [0, spiralColumnHeight / 2, 0], receiveShadow: true, children: _jsx("cylinderGeometry", { args: [spiralColumnRadius, spiralColumnRadius, spiralColumnHeight, 10] }) })) : null, Array.from({ length: stepCount }).map((_, index) => {
|
|
195
195
|
const currentHeight = stepHeight * (index + 1);
|
|
196
196
|
const actualStepHeight = isSpiral
|
|
197
197
|
? thickness
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stair-segment-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/stair-segment/stair-segment-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EAGtB,MAAM,kBAAkB,CAAA;AAMzB,eAAO,MAAM,oBAAoB,GAAI,UAAU;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"stair-segment-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/stair-segment/stair-segment-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EAGtB,MAAM,kBAAkB,CAAA;AAMzB,eAAO,MAAM,oBAAoB,GAAI,UAAU;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,4CA6DxE,CAAA"}
|
|
@@ -15,7 +15,26 @@ export const StairSegmentRenderer = ({ node }) => {
|
|
|
15
15
|
const parentNode = node.parentId
|
|
16
16
|
? nodes[node.parentId]
|
|
17
17
|
: undefined;
|
|
18
|
-
const material = useMemo(() =>
|
|
18
|
+
const material = useMemo(() => {
|
|
19
|
+
return getStraightStairSegmentBodyMaterials(node, parentNode);
|
|
20
|
+
}, [
|
|
21
|
+
node.materialPreset,
|
|
22
|
+
node.material,
|
|
23
|
+
node.material?.preset,
|
|
24
|
+
node.material?.properties,
|
|
25
|
+
node.material?.texture,
|
|
26
|
+
parentNode?.materialPreset,
|
|
27
|
+
parentNode?.material,
|
|
28
|
+
parentNode?.material?.preset,
|
|
29
|
+
parentNode?.material?.properties,
|
|
30
|
+
parentNode?.material?.texture,
|
|
31
|
+
parentNode?.railingMaterialPreset,
|
|
32
|
+
parentNode?.railingMaterial,
|
|
33
|
+
parentNode?.sideMaterialPreset,
|
|
34
|
+
parentNode?.sideMaterial,
|
|
35
|
+
parentNode?.treadMaterialPreset,
|
|
36
|
+
parentNode?.treadMaterial,
|
|
37
|
+
]);
|
|
19
38
|
const placeholderGeometry = useMemo(() => {
|
|
20
39
|
const geometry = new THREE.BufferGeometry();
|
|
21
40
|
geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-limiter.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/frame-limiter.tsx"],"names":[],"mappings":"AAGA,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"frame-limiter.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/frame-limiter.tsx"],"names":[],"mappings":"AAGA,KAAK,iBAAiB,GAAG;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAiC7C,CAAA;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { useThree } from '@react-three/fiber';
|
|
2
2
|
import { useLayoutEffect } from 'react';
|
|
3
3
|
const FrameLimiter = ({ fps = 50 }) => {
|
|
4
|
-
const { advance, set, frameloop: initFrameloop } = useThree();
|
|
4
|
+
const { advance, set, frameloop: initFrameloop, scene, clock } = useThree();
|
|
5
|
+
const renderer = useThree((state) => state.gl);
|
|
5
6
|
useLayoutEffect(() => {
|
|
6
7
|
let elapsed = 0;
|
|
7
8
|
let then = 0;
|
|
@@ -17,8 +18,11 @@ const FrameLimiter = ({ fps = 50 }) => {
|
|
|
17
18
|
then = t - (elapsed % interval);
|
|
18
19
|
}
|
|
19
20
|
}
|
|
21
|
+
// Set frameloop to never, it will shut down the default render loop
|
|
20
22
|
set({ frameloop: 'never' });
|
|
23
|
+
// Kick off custom render loop
|
|
21
24
|
raf = requestAnimationFrame(tick);
|
|
25
|
+
// Restore initial setting
|
|
22
26
|
return () => {
|
|
23
27
|
if (raf) {
|
|
24
28
|
cancelAnimationFrame(raf);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,kBAAkB,EAAsB,MAAM,oBAAoB,CAAA;AAEhG,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAwBrC,OAAuB,EAAwB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA+B1F,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAc,SAAQ,kBAAkB,CAAC,OAAO,KAAK,CAAC;KAAG;CACpE;AAkFD,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,gBAAgB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACvC,IAAI,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,kBAAkB,EAAsB,MAAM,oBAAoB,CAAA;AAEhG,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAwBrC,OAAuB,EAAwB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA+B1F,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAc,SAAQ,kBAAkB,CAAC,OAAO,KAAK,CAAC;KAAG;CACpE;AAkFD,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,gBAAgB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACvC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAwGjC,CAAA;AASD,eAAe,MAAM,CAAA"}
|
|
@@ -81,25 +81,25 @@ function GPUDeviceWatcher() {
|
|
|
81
81
|
}
|
|
82
82
|
console.log('[viewer] WebGPU device ready', {
|
|
83
83
|
label: device.label,
|
|
84
|
-
features:
|
|
84
|
+
features: Array.from(device.features ?? []),
|
|
85
85
|
});
|
|
86
86
|
device.lost.then((info) => {
|
|
87
|
-
console.error(`[viewer] WebGPU device lost: reason="${info.reason
|
|
87
|
+
console.error(`[viewer] WebGPU device lost: reason="${info.reason}", message="${info.message}". ` +
|
|
88
88
|
'The page must be reloaded to recover the GPU context.');
|
|
89
89
|
});
|
|
90
90
|
// Uncaptured errors are normally silent (only console-warned by Chrome at
|
|
91
91
|
// best). Pipe them to console.error so silent mobile crashes show up.
|
|
92
92
|
const onUncapturedError = (event) => {
|
|
93
|
-
console.error('[viewer] WebGPU uncaptured error:', event
|
|
93
|
+
console.error('[viewer] WebGPU uncaptured error:', event.error.message, event.error);
|
|
94
94
|
};
|
|
95
|
-
device.addEventListener
|
|
95
|
+
device.addEventListener('uncapturederror', onUncapturedError);
|
|
96
96
|
return () => {
|
|
97
|
-
device.removeEventListener
|
|
97
|
+
device.removeEventListener('uncapturederror', onUncapturedError);
|
|
98
98
|
};
|
|
99
99
|
}, [gl]);
|
|
100
100
|
return null;
|
|
101
101
|
}
|
|
102
|
-
const Viewer = ({ children, hoverStyles = DEFAULT_HOVER_STYLES, selectionManager = 'default', perf = false, }) => {
|
|
102
|
+
const Viewer = ({ children, hoverStyles = DEFAULT_HOVER_STYLES, selectionManager = 'default', perf = false, useBvh = true, }) => {
|
|
103
103
|
const theme = useViewer((state) => state.theme);
|
|
104
104
|
return (_jsxs(Canvas, { camera: { position: [50, 50, 50], fov: 50 }, className: `transition-colors duration-700 ${theme === 'dark' ? 'bg-[#1f2433]' : 'bg-[#fafafa]'}`, dpr: [1, 1.5], frameloop: "never", gl: ((props) => {
|
|
105
105
|
const canvas = props.canvas;
|
|
@@ -144,7 +144,7 @@ const Viewer = ({ children, hoverStyles = DEFAULT_HOVER_STYLES, selectionManager
|
|
|
144
144
|
}, shadows: {
|
|
145
145
|
type: THREE.PCFShadowMap,
|
|
146
146
|
enabled: true,
|
|
147
|
-
}, children: [_jsx(FrameLimiter, { fps: 50 }), _jsx(ViewerCamera, {}), _jsx(GPUDeviceWatcher, {}), _jsxs(ErrorBoundary, { fallback: null, scope: "viewer-scene", children: [_jsx(Lights, {}), _jsx(Bvh, { children: _jsx(SceneRenderer, {}) }), _jsx(LevelSystem, {}), _jsx(GuideSystem, {}), _jsx(ScanSystem, {}), _jsx(WallCutout, {}), _jsx(CeilingSystem, {}), _jsx(DoorAnimationSystem, {}), _jsx(WindowAnimationSystem, {}), _jsx(DoorSystem, {}), _jsx(FenceSystem, {}), _jsx(ItemSystem, {}), _jsx(RoofSystem, {}), _jsx(SlabSystem, {}), _jsx(StairSystem, {}), _jsx(WallSystem, {}), _jsx(WindowSystem, {}), _jsx(ZoneSystem, {}), _jsx(PostProcessing, { hoverStyles: hoverStyles }), _jsx(ItemLightSystem, {}), selectionManager === 'default' && _jsx(SelectionManager, {}), perf && _jsx(PerfMonitor, {}), children] })] }));
|
|
147
|
+
}, children: [_jsx(FrameLimiter, { fps: 50 }), _jsx(ViewerCamera, {}), _jsx(GPUDeviceWatcher, {}), _jsxs(ErrorBoundary, { fallback: null, scope: "viewer-scene", children: [_jsx(Lights, {}), useBvh ? (_jsx(Bvh, { children: _jsx(SceneRenderer, {}) })) : (_jsx(SceneRenderer, {})), _jsx(LevelSystem, {}), _jsx(GuideSystem, {}), _jsx(ScanSystem, {}), _jsx(WallCutout, {}), _jsx(CeilingSystem, {}), _jsx(DoorAnimationSystem, {}), _jsx(WindowAnimationSystem, {}), _jsx(DoorSystem, {}), _jsx(FenceSystem, {}), _jsx(ItemSystem, {}), _jsx(RoofSystem, {}), _jsx(SlabSystem, {}), _jsx(StairSystem, {}), _jsx(WallSystem, {}), _jsx(WindowSystem, {}), _jsx(ZoneSystem, {}), _jsx(PostProcessing, { hoverStyles: hoverStyles }), _jsx(ItemLightSystem, {}), selectionManager === 'default' && _jsx(SelectionManager, {}), perf && _jsx(PerfMonitor, {}), children] })] }));
|
|
148
148
|
};
|
|
149
149
|
const DebugRenderer = () => {
|
|
150
150
|
useFrame(({ gl, scene, camera }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-processing.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/post-processing.tsx"],"names":[],"mappings":"AA4BA,eAAO,MAAM,WAAW;;;;;;;;;;;;;CAavB,CAAA;AAQD,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,UAAU,CAAA;CACpB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAS9B,eAAO,MAAM,oBAAoB,EAAE,WAElC,CAAA;AAiBD,QAAA,MAAM,oBAAoB,GAAI,kBAE3B;IACD,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,
|
|
1
|
+
{"version":3,"file":"post-processing.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/post-processing.tsx"],"names":[],"mappings":"AA4BA,eAAO,MAAM,WAAW;;;;;;;;;;;;;CAavB,CAAA;AAQD,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,UAAU,CAAA;CACpB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAS9B,eAAO,MAAM,oBAAoB,EAAE,WAElC,CAAA;AAiBD,QAAA,MAAM,oBAAoB,GAAI,kBAE3B;IACD,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,SAyTA,CAAA;AAED,eAAe,oBAAoB,CAAA"}
|
|
@@ -83,8 +83,6 @@ const PostProcessingPasses = ({ hoverStyles = DEFAULT_HOVER_STYLES, }) => {
|
|
|
83
83
|
}, []);
|
|
84
84
|
// Reset retry state when project changes
|
|
85
85
|
useEffect(() => {
|
|
86
|
-
// Intentionally touch projectId so the effect reruns on project switches.
|
|
87
|
-
void projectId;
|
|
88
86
|
retryCountRef.current = 0;
|
|
89
87
|
if (rebuildTimeoutRef.current !== null) {
|
|
90
88
|
clearTimeout(rebuildTimeoutRef.current);
|
|
@@ -117,10 +115,6 @@ const PostProcessingPasses = ({ hoverStyles = DEFAULT_HOVER_STYLES, }) => {
|
|
|
117
115
|
]);
|
|
118
116
|
// Build / rebuild the post-processing pipeline
|
|
119
117
|
useEffect(() => {
|
|
120
|
-
// Intentionally touch these so React/biome treat project switches and retry bumps
|
|
121
|
-
// as explicit rebuild triggers instead of accidental extra dependencies.
|
|
122
|
-
void projectId;
|
|
123
|
-
void pipelineVersion;
|
|
124
118
|
if (!(renderer && scene && camera)) {
|
|
125
119
|
console.warn('[viewer/post-processing] Skipping pipeline build — missing dependency.', {
|
|
126
120
|
hasRenderer: !!renderer,
|
|
@@ -137,21 +131,6 @@ const PostProcessingPasses = ({ hoverStyles = DEFAULT_HOVER_STYLES, }) => {
|
|
|
137
131
|
rendererCtor: renderer.constructor?.name,
|
|
138
132
|
});
|
|
139
133
|
hasPipelineErrorRef.current = false;
|
|
140
|
-
// WebGPU availability check: SSGI, denoise, and RenderPipeline are all
|
|
141
|
-
// WebGPU-only APIs. When the browser falls back to WebGL2 (no
|
|
142
|
-
// `navigator.gpu`, or the device couldn't be created), building the
|
|
143
|
-
// pipeline either throws silently or produces a broken output where
|
|
144
|
-
// the scene renders for a few frames and then goes black as the retry
|
|
145
|
-
// loop fights the direct-render fallback path. Short-circuit here so
|
|
146
|
-
// `useFrame` uses the direct `renderer.render(scene, camera)` path
|
|
147
|
-
// exclusively and never attempts the TSL pipeline.
|
|
148
|
-
const hasWebGPU = typeof navigator !== 'undefined' && 'gpu' in navigator;
|
|
149
|
-
if (!hasWebGPU) {
|
|
150
|
-
console.warn('[viewer] WebGPU unavailable — rendering without post-processing (SSGI, outlines, denoise).');
|
|
151
|
-
hasPipelineErrorRef.current = true;
|
|
152
|
-
renderPipelineRef.current = null;
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
134
|
// Clear outliner arrays synchronously to prevent stale Object3D refs
|
|
156
135
|
// from the previous project leaking into the new pipeline's outline passes.
|
|
157
136
|
const outliner = useViewer.getState().outliner;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { DEFAULT_HOVER_STYLES, SSGI_PARAMS, } from './components/viewer/post-pro
|
|
|
4
4
|
export { WalkthroughControls } from './components/viewer/walkthrough-controls';
|
|
5
5
|
export { ASSETS_CDN_URL, resolveAssetUrl, resolveCdnUrl } from './lib/asset-url';
|
|
6
6
|
export { SCENE_LAYER, ZONE_LAYER } from './lib/layers';
|
|
7
|
-
export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, } from './lib/materials';
|
|
7
|
+
export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, glassMaterial, } from './lib/materials';
|
|
8
8
|
export { mergedOutline } from './lib/merged-outline-node';
|
|
9
9
|
export { default as useViewer } from './store/use-viewer';
|
|
10
10
|
export { InteractiveSystem } from './systems/interactive/interactive-system';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAA;AAClF,OAAO,EACL,oBAAoB,EACpB,WAAW,GACZ,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAA;AAClF,OAAO,EACL,oBAAoB,EACpB,WAAW,GACZ,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,aAAa,GACd,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAC5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export { DEFAULT_HOVER_STYLES, SSGI_PARAMS, } from './components/viewer/post-pro
|
|
|
3
3
|
export { WalkthroughControls } from './components/viewer/walkthrough-controls';
|
|
4
4
|
export { ASSETS_CDN_URL, resolveAssetUrl, resolveCdnUrl } from './lib/asset-url';
|
|
5
5
|
export { SCENE_LAYER, ZONE_LAYER } from './lib/layers';
|
|
6
|
-
export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, } from './lib/materials';
|
|
6
|
+
export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, glassMaterial, } from './lib/materials';
|
|
7
7
|
export { mergedOutline } from './lib/merged-outline-node';
|
|
8
8
|
export { default as useViewer } from './store/use-viewer';
|
|
9
9
|
export { InteractiveSystem } from './systems/interactive/interactive-system';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/lib/materials.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/lib/materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EAEpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAEvD,eAAO,MAAM,YAAY,0BAIvB,CAAA;AAEF,eAAO,MAAM,aAAa,0BAOxB,CAAA;AAkNF,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,GAC5B,KAAK,CAAC,oBAAoB,CAW5B;AAED,wBAAgB,2BAA2B,CACzC,cAAc,CAAC,EAAE,MAAM,GACtB,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAInC;AAED,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC,oBAAoB,CAsBpF;AAED,wBAAgB,qBAAqB,CACnC,KAAK,SAAY,EACjB,SAAS,SAAM,GACd,KAAK,CAAC,oBAAoB,CAO5B;AAED,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,uBAAuB,4BAOlC,CAAA;AACF,eAAO,MAAM,wBAAwB,4BAAyC,CAAA;AAC9E,eAAO,MAAM,qBAAqB,4BAAyC,CAAA;AAC3E,eAAO,MAAM,sBAAsB,4BAAwC,CAAA;AAE3E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAE9D;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAWzC"}
|
package/dist/lib/materials.js
CHANGED
|
@@ -59,8 +59,7 @@ function getTexture(material) {
|
|
|
59
59
|
return texture;
|
|
60
60
|
}
|
|
61
61
|
function isStandardMaterial(material) {
|
|
62
|
-
return (material instanceof THREE.MeshStandardMaterial ||
|
|
63
|
-
material instanceof THREE.MeshPhysicalMaterial);
|
|
62
|
+
return (material instanceof THREE.MeshStandardMaterial || material instanceof THREE.MeshPhysicalMaterial);
|
|
64
63
|
}
|
|
65
64
|
function applyTextureProperties(texture, props, slot) {
|
|
66
65
|
texture.wrapS = wrapMap[props.wrapS];
|
|
@@ -123,7 +122,7 @@ function queueTextureAssignment(material, slot, path, props) {
|
|
|
123
122
|
return;
|
|
124
123
|
}
|
|
125
124
|
material[slot] = null;
|
|
126
|
-
|
|
125
|
+
loadPresetTexture(path, props, slot).then((texture) => {
|
|
127
126
|
if (!texture)
|
|
128
127
|
return;
|
|
129
128
|
material[slot] = texture;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merged-outline-node.d.ts","sourceRoot":"","sources":["../../src/lib/merged-outline-node.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"merged-outline-node.d.ts","sourceRoot":"","sources":["../../src/lib/merged-outline-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -460,17 +460,10 @@ export class MergedOutlineNode extends TempNode {
|
|
|
460
460
|
}
|
|
461
461
|
_buildCache(objects, cache) {
|
|
462
462
|
for (const obj of objects) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (child.isMesh || child.isSprite)
|
|
468
|
-
cache.add(child);
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
catch {
|
|
472
|
-
// Skip objects that were disposed or removed from the scene graph
|
|
473
|
-
}
|
|
463
|
+
obj.traverse((child) => {
|
|
464
|
+
if (child.isMesh || child.isSprite)
|
|
465
|
+
cache.add(child);
|
|
466
|
+
});
|
|
474
467
|
}
|
|
475
468
|
}
|
|
476
469
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAA2B,MAAM,kBAAkB,CAAA;AAE5F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,eAAO,MAAM,aAAa,YAuBzB,CAAA;AAqBD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,KAAK,CAAC,cAAc,CAgDtF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useFrame } from '@react-three/fiber';
|
|
2
1
|
import { sceneRegistry, useScene } from '@pascal-app/core';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
4
|
function ensureUv2Attribute(geometry) {
|
|
5
5
|
const uv = geometry.getAttribute('uv');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fence-system.d.ts","sourceRoot":"","sources":["../../../src/systems/fence/fence-system.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fence-system.d.ts","sourceRoot":"","sources":["../../../src/systems/fence/fence-system.tsx"],"names":[],"mappings":"AA+QA,eAAO,MAAM,WAAW,YAiBvB,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useFrame } from '@react-three/fiber';
|
|
2
1
|
import { getWallCurveFrameAt, getWallCurveLength, sceneRegistry, useScene, } from '@pascal-app/core';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
4
|
import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
|
|
5
5
|
const MIN_CURVE_SEGMENT_LENGTH = 0.18;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guide-system.d.ts","sourceRoot":"","sources":["../../../src/systems/guide/guide-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"guide-system.d.ts","sourceRoot":"","sources":["../../../src/systems/guide/guide-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,YAcvB,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sceneRegistry } from '@pascal-app/core';
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import useViewer from '../../store/use-viewer';
|
|
4
4
|
export const GuideSystem = () => {
|
|
@@ -12,30 +12,5 @@ export const GuideSystem = () => {
|
|
|
12
12
|
}
|
|
13
13
|
});
|
|
14
14
|
}, [showGuides]);
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
const hideForCapture = () => {
|
|
17
|
-
const guides = sceneRegistry.byType.guide || new Set();
|
|
18
|
-
guides.forEach((guideId) => {
|
|
19
|
-
const node = sceneRegistry.nodes.get(guideId);
|
|
20
|
-
if (node)
|
|
21
|
-
node.visible = false;
|
|
22
|
-
});
|
|
23
|
-
};
|
|
24
|
-
const restoreAfterCapture = () => {
|
|
25
|
-
const showGuidesNow = useViewer.getState().showGuides;
|
|
26
|
-
const guides = sceneRegistry.byType.guide || new Set();
|
|
27
|
-
guides.forEach((guideId) => {
|
|
28
|
-
const node = sceneRegistry.nodes.get(guideId);
|
|
29
|
-
if (node)
|
|
30
|
-
node.visible = showGuidesNow;
|
|
31
|
-
});
|
|
32
|
-
};
|
|
33
|
-
emitter.on('thumbnail:before-capture', hideForCapture);
|
|
34
|
-
emitter.on('thumbnail:after-capture', restoreAfterCapture);
|
|
35
|
-
return () => {
|
|
36
|
-
emitter.off('thumbnail:before-capture', hideForCapture);
|
|
37
|
-
emitter.off('thumbnail:after-capture', restoreAfterCapture);
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
15
|
return null;
|
|
41
16
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useFrame } from '@react-three/fiber';
|
|
2
1
|
import { getScaledDimensions, resolveLevelId, sceneRegistry, spatialGridManager, useScene, } from '@pascal-app/core';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
3
|
// ============================================================================
|
|
4
4
|
// ITEM SYSTEM
|
|
5
5
|
// ============================================================================
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EAIrB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,KAAK,EAA0B,MAAM,eAAe,CAAA;AA4CvE,eAAO,MAAM,UAAU,YAsFtB,CAAA;AAqLD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,GACpB;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,KAAK,CAAA;CAAE,GAAG,IAAI,CAqRlF;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,eAAe,GAAG,KAAK,CAAC,cAAc,CAmDvF"}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import { useFrame } from '@react-three/fiber';
|
|
2
1
|
import { sceneRegistry, useScene, } from '@pascal-app/core';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
4
|
import { mergeVertices } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
|
|
5
5
|
import { ADDITION, Brush, Evaluator, SUBTRACTION } from 'three-bvh-csg';
|
|
6
6
|
import { computeBoundsTree } from 'three-mesh-bvh';
|
|
7
|
+
function csgGeometry(brush) {
|
|
8
|
+
return brush.geometry;
|
|
9
|
+
}
|
|
10
|
+
function csgMaterials(brush) {
|
|
11
|
+
const mat = brush.material;
|
|
12
|
+
return Array.isArray(mat) ? mat : [mat];
|
|
13
|
+
}
|
|
7
14
|
const csgEvaluator = new Evaluator();
|
|
8
15
|
csgEvaluator.useGroups = true;
|
|
9
16
|
csgEvaluator.consolidateGroups = false; // shared dummyMats across brushes causes consolidation to misalign groupIndices vs groupOrder indices → crash
|
|
@@ -151,7 +158,7 @@ function updateMergedRoofGeometry(roofNode, group, nodes) {
|
|
|
151
158
|
continue;
|
|
152
159
|
_matrix.compose(_position.set(child.position[0], child.position[1], child.position[2]), _quaternion.setFromAxisAngle(_yAxis, child.rotation), _scale);
|
|
153
160
|
const applyTransform = (brush) => {
|
|
154
|
-
brush.
|
|
161
|
+
csgGeometry(brush).applyMatrix4(_matrix);
|
|
155
162
|
brush.updateMatrixWorld();
|
|
156
163
|
};
|
|
157
164
|
applyTransform(brushes.shinSlab);
|
|
@@ -206,10 +213,8 @@ function updateMergedRoofGeometry(roofNode, group, nodes) {
|
|
|
206
213
|
const finalWallTrimmed = csgEvaluator.evaluate(totalWall, totalInner, SUBTRACTION);
|
|
207
214
|
const shinDeck = csgEvaluator.evaluate(finalShinTrimmed, finalDeckTrimmed, ADDITION);
|
|
208
215
|
const combined = csgEvaluator.evaluate(shinDeck, finalWallTrimmed, ADDITION);
|
|
209
|
-
const resultGeo = combined
|
|
210
|
-
const resultMaterials =
|
|
211
|
-
? combined.material
|
|
212
|
-
: [combined.material];
|
|
216
|
+
const resultGeo = csgGeometry(combined);
|
|
217
|
+
const resultMaterials = csgMaterials(combined);
|
|
213
218
|
const matToIndex = new Map([
|
|
214
219
|
[dummyMats[0], 0],
|
|
215
220
|
[dummyMats[1], 1],
|
|
@@ -219,8 +224,8 @@ function updateMergedRoofGeometry(roofNode, group, nodes) {
|
|
|
219
224
|
for (const g of resultGeo.groups) {
|
|
220
225
|
g.materialIndex = mapRoofGroupMaterialIndex(g.materialIndex, resultMaterials, matToIndex);
|
|
221
226
|
}
|
|
222
|
-
ensureUv2Attribute(resultGeo);
|
|
223
227
|
resultGeo.computeVertexNormals();
|
|
228
|
+
ensureUv2Attribute(resultGeo);
|
|
224
229
|
mergedMesh.geometry.dispose();
|
|
225
230
|
mergedMesh.geometry = resultGeo;
|
|
226
231
|
finalShinTrimmed.geometry.dispose();
|
|
@@ -477,10 +482,8 @@ export function generateRoofSegmentGeometry(node) {
|
|
|
477
482
|
const hollowWall = csgEvaluator.evaluate(wallBrush, innerBrush, SUBTRACTION);
|
|
478
483
|
const shinDeck = csgEvaluator.evaluate(shinSlab, deckSlab, ADDITION);
|
|
479
484
|
const combined = csgEvaluator.evaluate(shinDeck, hollowWall, ADDITION);
|
|
480
|
-
resultGeo = combined
|
|
481
|
-
const resultMaterials =
|
|
482
|
-
? combined.material
|
|
483
|
-
: [combined.material];
|
|
485
|
+
resultGeo = csgGeometry(combined);
|
|
486
|
+
const resultMaterials = csgMaterials(combined);
|
|
484
487
|
const matToIndex = new Map([
|
|
485
488
|
[dummyMats[0], 0],
|
|
486
489
|
[dummyMats[1], 1],
|
|
@@ -496,14 +499,14 @@ export function generateRoofSegmentGeometry(node) {
|
|
|
496
499
|
}
|
|
497
500
|
catch (e) {
|
|
498
501
|
console.error('Roof CSG failed:', e);
|
|
499
|
-
resultGeo = wallBrush.
|
|
502
|
+
resultGeo = csgGeometry(wallBrush).clone();
|
|
500
503
|
}
|
|
501
504
|
deckSlab.geometry.dispose();
|
|
502
505
|
shinSlab.geometry.dispose();
|
|
503
506
|
wallBrush.geometry.dispose();
|
|
504
507
|
innerBrush.geometry.dispose();
|
|
505
|
-
ensureUv2Attribute(resultGeo);
|
|
506
508
|
resultGeo.computeVertexNormals();
|
|
509
|
+
ensureUv2Attribute(resultGeo);
|
|
507
510
|
return resultGeo;
|
|
508
511
|
}
|
|
509
512
|
function remapRoofShellFaces(geometry, node) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan-system.d.ts","sourceRoot":"","sources":["../../../src/systems/scan/scan-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"scan-system.d.ts","sourceRoot":"","sources":["../../../src/systems/scan/scan-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,YActB,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sceneRegistry } from '@pascal-app/core';
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import useViewer from '../../store/use-viewer';
|
|
4
4
|
export const ScanSystem = () => {
|
|
@@ -12,30 +12,5 @@ export const ScanSystem = () => {
|
|
|
12
12
|
}
|
|
13
13
|
});
|
|
14
14
|
}, [showScans]);
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
const hideForCapture = () => {
|
|
17
|
-
const scans = sceneRegistry.byType.scan || new Set();
|
|
18
|
-
scans.forEach((scanId) => {
|
|
19
|
-
const node = sceneRegistry.nodes.get(scanId);
|
|
20
|
-
if (node)
|
|
21
|
-
node.visible = false;
|
|
22
|
-
});
|
|
23
|
-
};
|
|
24
|
-
const restoreAfterCapture = () => {
|
|
25
|
-
const showScansNow = useViewer.getState().showScans;
|
|
26
|
-
const scans = sceneRegistry.byType.scan || new Set();
|
|
27
|
-
scans.forEach((scanId) => {
|
|
28
|
-
const node = sceneRegistry.nodes.get(scanId);
|
|
29
|
-
if (node)
|
|
30
|
-
node.visible = showScansNow;
|
|
31
|
-
});
|
|
32
|
-
};
|
|
33
|
-
emitter.on('thumbnail:before-capture', hideForCapture);
|
|
34
|
-
emitter.on('thumbnail:after-capture', restoreAfterCapture);
|
|
35
|
-
return () => {
|
|
36
|
-
emitter.off('thumbnail:before-capture', hideForCapture);
|
|
37
|
-
emitter.off('thumbnail:after-capture', restoreAfterCapture);
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
15
|
return null;
|
|
41
16
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slab-system.d.ts","sourceRoot":"","sources":["../../../src/systems/slab/slab-system.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"slab-system.d.ts","sourceRoot":"","sources":["../../../src/systems/slab/slab-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EAGd,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,eAAO,MAAM,UAAU,YAwBtB,CAAA;AAkBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,cAAc,CAG7E"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useFrame } from '@react-three/fiber';
|
|
2
1
|
import { getRenderableSlabPolygon, sceneRegistry, useScene, } from '@pascal-app/core';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
4
|
function ensureUv2Attribute(geometry) {
|
|
5
5
|
const uv = geometry.getAttribute('uv');
|