@pascal-app/viewer 0.5.1 → 0.7.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/error-boundary.d.ts +7 -3
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/error-boundary.js +3 -1
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +1 -1
- package/dist/components/renderers/ceiling/ceiling-renderer.js +21 -4
- package/dist/components/renderers/column/column-renderer.d.ts +5 -0
- package/dist/components/renderers/column/column-renderer.d.ts.map +1 -0
- package/dist/components/renderers/column/column-renderer.js +594 -0
- package/dist/components/renderers/door/door-renderer.d.ts.map +1 -1
- package/dist/components/renderers/door/door-renderer.js +8 -10
- package/dist/components/renderers/fence/fence-renderer.d.ts.map +1 -1
- package/dist/components/renderers/fence/fence-renderer.js +16 -2
- package/dist/components/renderers/guide/guide-renderer.js +1 -1
- package/dist/components/renderers/item/item-renderer.d.ts.map +1 -1
- package/dist/components/renderers/item/item-renderer.js +2 -1
- package/dist/components/renderers/node-renderer.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.js +3 -1
- package/dist/components/renderers/roof/roof-renderer.d.ts.map +1 -1
- package/dist/components/renderers/roof/roof-renderer.js +19 -9
- package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts.map +1 -1
- package/dist/components/renderers/roof-segment/roof-segment-renderer.js +27 -8
- package/dist/components/renderers/site/site-renderer.d.ts.map +1 -1
- package/dist/components/renderers/site/site-renderer.js +7 -1
- package/dist/components/renderers/slab/slab-renderer.d.ts.map +1 -1
- package/dist/components/renderers/slab/slab-renderer.js +48 -7
- package/dist/components/renderers/spawn/spawn-renderer.d.ts +5 -0
- package/dist/components/renderers/spawn/spawn-renderer.d.ts.map +1 -0
- package/dist/components/renderers/spawn/spawn-renderer.js +32 -0
- package/dist/components/renderers/stair/stair-renderer.d.ts.map +1 -1
- package/dist/components/renderers/stair/stair-renderer.js +154 -39
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +1 -1
- package/dist/components/renderers/stair-segment/stair-segment-renderer.js +22 -10
- package/dist/components/renderers/wall/wall-renderer.d.ts.map +1 -1
- package/dist/components/renderers/wall/wall-renderer.js +4 -9
- package/dist/components/renderers/window/window-renderer.d.ts.map +1 -1
- package/dist/components/renderers/window/window-renderer.js +5 -2
- package/dist/components/viewer/frame-limiter.d.ts +6 -0
- package/dist/components/viewer/frame-limiter.d.ts.map +1 -0
- package/dist/components/viewer/frame-limiter.js +31 -0
- package/dist/components/viewer/ground-occluder.d.ts.map +1 -1
- package/dist/components/viewer/ground-occluder.js +5 -1
- package/dist/components/viewer/index.d.ts +2 -0
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +90 -20
- package/dist/components/viewer/post-processing.d.ts +13 -1
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +98 -44
- package/dist/components/viewer/selection-manager.d.ts.map +1 -1
- package/dist/components/viewer/selection-manager.js +31 -3
- package/dist/hooks/use-node-events.d.ts +9 -1
- package/dist/hooks/use-node-events.d.ts.map +1 -1
- package/dist/hooks/use-node-events.js +2 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/lib/materials.d.ts +7 -1
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +192 -2
- package/dist/lib/merged-outline-node.d.ts +2 -0
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +36 -9
- package/dist/store/use-viewer.d.ts +6 -6
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +2 -2
- package/dist/systems/ceiling/ceiling-system.d.ts +8 -0
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -0
- package/dist/systems/ceiling/ceiling-system.js +91 -0
- package/dist/systems/column/column-geometry.d.ts +22 -0
- package/dist/systems/column/column-geometry.d.ts.map +1 -0
- package/dist/systems/column/column-geometry.js +108 -0
- package/dist/systems/door/door-animation-system.d.ts +2 -0
- package/dist/systems/door/door-animation-system.d.ts.map +1 -0
- package/dist/systems/door/door-animation-system.js +53 -0
- package/dist/systems/door/door-system.d.ts +2 -0
- package/dist/systems/door/door-system.d.ts.map +1 -0
- package/dist/systems/door/door-system.js +867 -0
- package/dist/systems/fence/fence-system.d.ts +2 -0
- package/dist/systems/fence/fence-system.d.ts.map +1 -0
- package/dist/systems/fence/fence-system.js +185 -0
- package/dist/systems/item/item-system.d.ts +2 -0
- package/dist/systems/item/item-system.d.ts.map +1 -0
- package/dist/systems/item/item-system.js +44 -0
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts +14 -0
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts.map +1 -0
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.js +155 -0
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts +6 -0
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts.map +1 -0
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.js +75 -0
- package/dist/systems/item-mesh-metadata/sync-request.d.ts +7 -0
- package/dist/systems/item-mesh-metadata/sync-request.d.ts.map +1 -0
- package/dist/systems/item-mesh-metadata/sync-request.js +25 -0
- package/dist/systems/roof/roof-materials.d.ts +5 -0
- package/dist/systems/roof/roof-materials.d.ts.map +1 -0
- package/dist/systems/roof/roof-materials.js +46 -0
- package/dist/systems/roof/roof-system.d.ts +16 -0
- package/dist/systems/roof/roof-system.d.ts.map +1 -0
- package/dist/systems/roof/roof-system.js +797 -0
- package/dist/systems/slab/slab-system.d.ts +8 -0
- package/dist/systems/slab/slab-system.d.ts.map +1 -0
- package/dist/systems/slab/slab-system.js +155 -0
- package/dist/systems/stair/stair-materials.d.ts +7 -0
- package/dist/systems/stair/stair-materials.d.ts.map +1 -0
- package/dist/systems/stair/stair-materials.js +56 -0
- package/dist/systems/stair/stair-system.d.ts +2 -0
- package/dist/systems/stair/stair-system.d.ts.map +1 -0
- package/dist/systems/stair/stair-system.js +772 -0
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout.js +4 -123
- package/dist/systems/wall/wall-materials.d.ts +16 -0
- package/dist/systems/wall/wall-materials.d.ts.map +1 -0
- package/dist/systems/wall/wall-materials.js +148 -0
- package/dist/systems/wall/wall-system.d.ts +11 -0
- package/dist/systems/wall/wall-system.d.ts.map +1 -0
- package/dist/systems/wall/wall-system.js +592 -0
- package/dist/systems/window/window-animation-system.d.ts +2 -0
- package/dist/systems/window/window-animation-system.d.ts.map +1 -0
- package/dist/systems/window/window-animation-system.js +135 -0
- package/dist/systems/window/window-system.d.ts +12 -0
- package/dist/systems/window/window-system.d.ts.map +1 -0
- package/dist/systems/window/window-system.js +1430 -0
- package/package.json +6 -4
|
@@ -1,24 +1,49 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useRegistry, useScene } from '@pascal-app/core';
|
|
3
|
-
import { useLayoutEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { useRegistry, useScene, } from '@pascal-app/core';
|
|
3
|
+
import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import * as THREE from 'three';
|
|
5
5
|
import { useNodeEvents } from '../../../hooks/use-node-events';
|
|
6
|
-
import { createMaterial, DEFAULT_STAIR_MATERIAL } from '../../../lib/materials';
|
|
6
|
+
import { createMaterial, createMaterialFromPresetRef, DEFAULT_STAIR_MATERIAL, } from '../../../lib/materials';
|
|
7
|
+
import { getStairBodyMaterials, getStairRailingMaterial, } from '../../../systems/stair/stair-materials';
|
|
7
8
|
import { NodeRenderer } from '../node-renderer';
|
|
8
9
|
export const StairRenderer = ({ node }) => {
|
|
9
10
|
const ref = useRef(null);
|
|
11
|
+
const isSegmentBasedStair = node.stairType === 'straight';
|
|
10
12
|
useRegistry(node.id, 'stair', ref);
|
|
11
13
|
useLayoutEffect(() => {
|
|
12
14
|
useScene.getState().markDirty(node.id);
|
|
13
15
|
}, [node.id]);
|
|
14
16
|
const handlers = useNodeEvents(node, 'stair');
|
|
15
17
|
const material = useMemo(() => {
|
|
18
|
+
const presetMaterial = createMaterialFromPresetRef(node.materialPreset);
|
|
19
|
+
if (presetMaterial)
|
|
20
|
+
return presetMaterial;
|
|
16
21
|
const mat = node.material;
|
|
17
22
|
if (!mat)
|
|
18
23
|
return DEFAULT_STAIR_MATERIAL;
|
|
19
24
|
return createMaterial(mat);
|
|
20
|
-
}, [
|
|
21
|
-
|
|
25
|
+
}, [
|
|
26
|
+
node.materialPreset,
|
|
27
|
+
node.material,
|
|
28
|
+
node.material?.preset,
|
|
29
|
+
node.material?.properties,
|
|
30
|
+
node.material?.texture,
|
|
31
|
+
]);
|
|
32
|
+
const straightBodyMaterials = useMemo(() => getStairBodyMaterials(node), [node]);
|
|
33
|
+
const railingMaterial = useMemo(() => getStairRailingMaterial(node), [node]);
|
|
34
|
+
const straightPlaceholderGeometry = useMemo(() => {
|
|
35
|
+
const geometry = new THREE.BufferGeometry();
|
|
36
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3));
|
|
37
|
+
geometry.addGroup(0, 0, 0);
|
|
38
|
+
geometry.addGroup(0, 0, 1);
|
|
39
|
+
return geometry;
|
|
40
|
+
}, []);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
return () => {
|
|
43
|
+
straightPlaceholderGeometry.dispose();
|
|
44
|
+
};
|
|
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, !isSegmentBasedStair ? (_jsx(CurvedStairBody, { bodyMaterials: straightBodyMaterials, stair: node })) : null, _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] }));
|
|
22
47
|
};
|
|
23
48
|
function StairRailings({ stair, material }) {
|
|
24
49
|
const nodes = useScene((state) => state.nodes);
|
|
@@ -60,7 +85,7 @@ function StairRailings({ stair, material }) {
|
|
|
60
85
|
Math.sin(angle) * radius,
|
|
61
86
|
];
|
|
62
87
|
});
|
|
63
|
-
return (_jsxs("group", { children: [sidePoints.map((point, pointIndex) => (_jsx("mesh", { castShadow: true, geometry: BALUSTER_GEOMETRY, material: material, position: [point[0], point[1] + railHeight / 2, point[2]], receiveShadow: true, scale: [balusterRadius, railHeight, balusterRadius] }, `${stair.id}-curved-baluster-${sideIndex}-${pointIndex}`))), sidePoints.slice(0, -1).map((point, pointIndex) => {
|
|
88
|
+
return (_jsxs("group", { children: [sidePoints.map((point, pointIndex) => (_jsx("mesh", { castShadow: true, geometry: BALUSTER_GEOMETRY, material: material, name: "stair-railing-baluster", position: [point[0], point[1] + railHeight / 2, point[2]], receiveShadow: true, scale: [balusterRadius, railHeight, balusterRadius] }, `${stair.id}-curved-baluster-${sideIndex}-${pointIndex}`))), sidePoints.slice(0, -1).map((point, pointIndex) => {
|
|
64
89
|
const nextPoint = sidePoints[pointIndex + 1];
|
|
65
90
|
if (!nextPoint)
|
|
66
91
|
return null;
|
|
@@ -71,7 +96,11 @@ function StairRailings({ stair, material }) {
|
|
|
71
96
|
if (railPaths.length === 0) {
|
|
72
97
|
return null;
|
|
73
98
|
}
|
|
74
|
-
return (_jsxs("group", { name: "stair-railing", children: [railPaths.map((segmentPath, index) => (_jsx("group", { position: [
|
|
99
|
+
return (_jsxs("group", { name: "stair-railing", children: [railPaths.map((segmentPath, index) => (_jsx("group", { position: [
|
|
100
|
+
segmentPath.layout.center[0],
|
|
101
|
+
segmentPath.layout.elevation,
|
|
102
|
+
segmentPath.layout.center[1],
|
|
103
|
+
], "rotation-y": segmentPath.layout.rotation, children: segmentPath.sidePaths.map((sidePath, sideIndex) => (_jsxs("group", { children: [sidePath.points.map((point, pointIndex) => (_jsx("mesh", { castShadow: true, geometry: BALUSTER_GEOMETRY, material: material, name: "stair-railing-baluster", position: [point[2], point[1] + railHeight / 2, point[0]], receiveShadow: true, scale: [balusterRadius, railHeight, balusterRadius] }, `${segmentPath.layout.segment.id}-${sidePath.side}-baluster-${pointIndex}`))), sidePath.points.slice(0, -1).map((point, pointIndex) => {
|
|
75
104
|
const nextPoint = sidePath.points[pointIndex + 1];
|
|
76
105
|
if (!nextPoint)
|
|
77
106
|
return null;
|
|
@@ -94,23 +123,43 @@ function StairRailings({ stair, material }) {
|
|
|
94
123
|
const lastPoint = entry.points[entry.points.length - 1];
|
|
95
124
|
return {
|
|
96
125
|
entry,
|
|
97
|
-
distance: lastPoint
|
|
126
|
+
distance: lastPoint
|
|
127
|
+
? distance3(toWorldRailPoint(previousPath.layout, lastPoint), currentWorldPoint)
|
|
128
|
+
: Number.POSITIVE_INFINITY,
|
|
98
129
|
};
|
|
99
130
|
})
|
|
100
131
|
.sort((left, right) => left.distance - right.distance)[0]?.entry;
|
|
101
|
-
const previousPoint = previousSidePath
|
|
132
|
+
const previousPoint = previousSidePath?.points.length
|
|
102
133
|
? previousSidePath.points[previousSidePath.points.length - 1]
|
|
103
134
|
: null;
|
|
104
135
|
if (!(previousPoint && currentPoint)) {
|
|
105
136
|
return null;
|
|
106
137
|
}
|
|
107
138
|
const previousWorldPoint = toWorldRailPoint(previousPath.layout, previousPoint);
|
|
108
|
-
return (_jsxs("group", { children: [_jsx(RailSegment, { end: [
|
|
139
|
+
return (_jsxs("group", { children: [_jsx(RailSegment, { end: [
|
|
140
|
+
currentWorldPoint[0],
|
|
141
|
+
currentWorldPoint[1] + railHeight,
|
|
142
|
+
currentWorldPoint[2],
|
|
143
|
+
], material: material, radius: railRadius, start: [
|
|
144
|
+
previousWorldPoint[0],
|
|
145
|
+
previousWorldPoint[1] + railHeight,
|
|
146
|
+
previousWorldPoint[2],
|
|
147
|
+
] }), _jsx(RailSegment, { end: [
|
|
148
|
+
currentWorldPoint[0],
|
|
149
|
+
currentWorldPoint[1] + midRailHeight,
|
|
150
|
+
currentWorldPoint[2],
|
|
151
|
+
], material: material, radius: railRadius * 0.8, start: [
|
|
152
|
+
previousWorldPoint[0],
|
|
153
|
+
previousWorldPoint[1] + midRailHeight,
|
|
154
|
+
previousWorldPoint[2],
|
|
155
|
+
] })] }, `${previousPath.layout.segment.id}-${segmentPath.layout.segment.id}-${sideIndex}`));
|
|
109
156
|
});
|
|
110
157
|
})] }));
|
|
111
158
|
}
|
|
112
159
|
const BALUSTER_GEOMETRY = new THREE.CylinderGeometry(1, 1, 1, 8);
|
|
113
160
|
const RAIL_GEOMETRY = new THREE.CylinderGeometry(1, 1, 1, 8);
|
|
161
|
+
const STAIR_TREAD_MATERIAL_INDEX = 0;
|
|
162
|
+
const STAIR_SIDE_MATERIAL_INDEX = 1;
|
|
114
163
|
function RailSegment({ start, end, radius, material, }) {
|
|
115
164
|
const startVector = useMemo(() => new THREE.Vector3(...start), [start]);
|
|
116
165
|
const endVector = useMemo(() => new THREE.Vector3(...end), [end]);
|
|
@@ -118,9 +167,10 @@ function RailSegment({ start, end, radius, material, }) {
|
|
|
118
167
|
const length = Math.max(direction.length(), 0.01);
|
|
119
168
|
const quaternion = useMemo(() => new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), direction.clone().normalize()), [direction]);
|
|
120
169
|
const midpoint = useMemo(() => startVector.clone().add(endVector).multiplyScalar(0.5), [endVector, startVector]);
|
|
121
|
-
return (_jsx("mesh", { castShadow: true, geometry: RAIL_GEOMETRY, material: material, position: [midpoint.x, midpoint.y, midpoint.z], quaternion: quaternion, receiveShadow: true, scale: [Math.max(radius, 0.01), length, Math.max(radius, 0.01)] }));
|
|
170
|
+
return (_jsx("mesh", { castShadow: true, geometry: RAIL_GEOMETRY, material: material, name: "stair-railing-rail", position: [midpoint.x, midpoint.y, midpoint.z], quaternion: quaternion, receiveShadow: true, scale: [Math.max(radius, 0.01), length, Math.max(radius, 0.01)] }));
|
|
122
171
|
}
|
|
123
|
-
function CurvedStairBody({ stair,
|
|
172
|
+
function CurvedStairBody({ stair, bodyMaterials, }) {
|
|
173
|
+
const sideMaterial = bodyMaterials[1];
|
|
124
174
|
const stepCount = Math.max(2, Math.round(stair.stepCount ?? 10));
|
|
125
175
|
const totalRise = Math.max(stair.totalRise ?? 2.5, 0.1);
|
|
126
176
|
const stepHeight = totalRise / stepCount;
|
|
@@ -135,34 +185,47 @@ function CurvedStairBody({ stair, material }) {
|
|
|
135
185
|
const spiralColumnHeight = totalRise + thickness;
|
|
136
186
|
const spiralLandingDepth = Math.max(0.3, stair.topLandingDepth ?? Math.max((stair.width ?? 1) * 0.9, 0.8));
|
|
137
187
|
const spiralLandingSweep = isSpiral && (stair.topLandingMode ?? 'none') === 'integrated'
|
|
138
|
-
? Math.min(Math.PI * 0.75, spiralLandingDepth / Math.max(innerRadius + (stair.width ?? 1) / 2, 0.1)) *
|
|
139
|
-
Math.sign(sweepAngle || 1)
|
|
188
|
+
? Math.min(Math.PI * 0.75, spiralLandingDepth / Math.max(innerRadius + (stair.width ?? 1) / 2, 0.1)) * Math.sign(sweepAngle || 1)
|
|
140
189
|
: 0;
|
|
141
190
|
const spiralLastStepTop = stepHeight * Math.max(stepCount - 1, 0) + thickness;
|
|
142
191
|
const spiralLandingThickness = isSpiral && (stair.topLandingMode ?? 'none') === 'integrated'
|
|
143
192
|
? Math.max(0.02, totalRise - spiralLastStepTop)
|
|
144
193
|
: 0;
|
|
145
|
-
return (_jsxs("group", { name: isSpiral ? 'spiral-stair' : 'curved-stair', children: [isSpiral && (stair.showCenterColumn ?? true) ? (_jsx("mesh", { castShadow: true, receiveShadow: true, material:
|
|
194
|
+
return (_jsxs("group", { name: isSpiral ? 'spiral-stair' : 'curved-stair', children: [isSpiral && (stair.showCenterColumn ?? true) ? (_jsx("mesh", { castShadow: true, receiveShadow: true, material: sideMaterial, name: "stair-side", position: [0, spiralColumnHeight / 2, 0], children: _jsx("cylinderGeometry", { args: [spiralColumnRadius, spiralColumnRadius, spiralColumnHeight, 10] }) })) : null, Array.from({ length: stepCount }).map((_, index) => {
|
|
146
195
|
const currentHeight = stepHeight * (index + 1);
|
|
147
|
-
const actualStepHeight = isSpiral
|
|
196
|
+
const actualStepHeight = isSpiral
|
|
197
|
+
? thickness
|
|
198
|
+
: fillToFloor
|
|
199
|
+
? Math.max(currentHeight, thickness)
|
|
200
|
+
: thickness;
|
|
148
201
|
const startAngle = -sweepAngle / 2 + stepSweep * index;
|
|
149
202
|
const endAngle = startAngle + stepSweep;
|
|
150
|
-
const stepY = isSpiral
|
|
203
|
+
const stepY = isSpiral
|
|
204
|
+
? stepHeight * index
|
|
205
|
+
: fillToFloor
|
|
206
|
+
? 0
|
|
207
|
+
: Math.max(currentHeight - thickness, 0);
|
|
151
208
|
const midAngle = startAngle + stepSweep / 2;
|
|
152
|
-
return (_jsxs("group", { "position-y": stepY, children: [isSpiral && (stair.showStepSupports ?? true) ? (_jsx("mesh", { castShadow: true, material:
|
|
153
|
-
Math.cos(midAngle) *
|
|
209
|
+
return (_jsxs("group", { "position-y": stepY, children: [isSpiral && (stair.showStepSupports ?? true) ? (_jsx("mesh", { castShadow: true, material: sideMaterial, name: "stair-side", position: [
|
|
210
|
+
Math.cos(midAngle) *
|
|
211
|
+
(spiralColumnRadius +
|
|
212
|
+
Math.max(0.04, innerRadius - spiralColumnRadius + 0.04) / 2 -
|
|
213
|
+
0.02),
|
|
154
214
|
Math.max(thickness * 0.55, 0.025) / 2,
|
|
155
|
-
Math.sin(midAngle) *
|
|
215
|
+
Math.sin(midAngle) *
|
|
216
|
+
(spiralColumnRadius +
|
|
217
|
+
Math.max(0.04, innerRadius - spiralColumnRadius + 0.04) / 2 -
|
|
218
|
+
0.02),
|
|
156
219
|
], receiveShadow: true, "rotation-y": -midAngle, children: _jsx("boxGeometry", { args: [
|
|
157
220
|
Math.max(0.04, innerRadius - spiralColumnRadius + 0.04),
|
|
158
221
|
Math.max(thickness * 0.55, 0.025),
|
|
159
222
|
Math.max(0.04, Math.min(0.12, Math.max(thickness * 0.55, 0.025) * 1.5)),
|
|
160
|
-
] }) })) : null, _jsx(CurvedStepMesh, { endAngle: endAngle, innerRadius: innerRadius, material:
|
|
161
|
-
}), isSpiral && (stair.topLandingMode ?? 'none') === 'integrated' ? (_jsx(CurvedStepMesh, { endAngle: sweepAngle / 2 + spiralLandingSweep, innerRadius: innerRadius, material:
|
|
223
|
+
] }) })) : null, _jsx(CurvedStepMesh, { endAngle: endAngle, innerRadius: innerRadius, material: bodyMaterials, outerRadius: outerRadius, positionY: 0, startAngle: startAngle, stepHeight: actualStepHeight, thickness: thickness })] }, `${stair.id}-${isSpiral ? 'spiral' : 'curved'}-step-${index}`));
|
|
224
|
+
}), isSpiral && (stair.topLandingMode ?? 'none') === 'integrated' ? (_jsx(CurvedStepMesh, { endAngle: sweepAngle / 2 + spiralLandingSweep, innerRadius: innerRadius, material: bodyMaterials, outerRadius: outerRadius, positionY: spiralLastStepTop, startAngle: sweepAngle / 2, stepHeight: spiralLandingThickness, thickness: spiralLandingThickness })) : null] }));
|
|
162
225
|
}
|
|
163
226
|
function CurvedStepMesh({ innerRadius, outerRadius, startAngle, endAngle, stepHeight, thickness, positionY, material, }) {
|
|
164
227
|
const geometry = useMemo(() => buildCurvedStepGeometry(innerRadius, outerRadius, startAngle, endAngle, Math.max(stepHeight, thickness)), [endAngle, innerRadius, outerRadius, startAngle, stepHeight, thickness]);
|
|
165
|
-
return _jsx("mesh", { castShadow: true, geometry: geometry, material: material, "position-y": positionY, receiveShadow: true });
|
|
228
|
+
return (_jsx("mesh", { castShadow: true, geometry: geometry, material: material, "position-y": positionY, receiveShadow: true }));
|
|
166
229
|
}
|
|
167
230
|
function buildCurvedStepGeometry(innerRadius, outerRadius, startAngle, endAngle, height) {
|
|
168
231
|
const clampedHeight = Math.max(height, 0.02);
|
|
@@ -173,8 +236,30 @@ function buildCurvedStepGeometry(innerRadius, outerRadius, startAngle, endAngle,
|
|
|
173
236
|
const segmentCount = Math.max(4, Math.min(24, Math.ceil(Math.abs(sweepAngle) / (Math.PI / 18) + Math.max(0, (outerRadius - innerRadius) * 3))));
|
|
174
237
|
const positions = [];
|
|
175
238
|
const normals = [];
|
|
239
|
+
const uvs = [];
|
|
240
|
+
const triangleMaterialIndices = [];
|
|
176
241
|
const pointOnArc = (radius, angle, y) => new THREE.Vector3(Math.cos(angle) * radius, y, Math.sin(angle) * radius);
|
|
177
|
-
const
|
|
242
|
+
const pushUv = (point, normal, materialIndex) => {
|
|
243
|
+
if (materialIndex === STAIR_TREAD_MATERIAL_INDEX) {
|
|
244
|
+
const angle = Math.atan2(point.z, point.x);
|
|
245
|
+
const arcOffset = (angle - startAngle) * Math.max((innerRadius + outerRadius) * 0.5, 0.01);
|
|
246
|
+
uvs.push(arcOffset, Math.sqrt(point.x * point.x + point.z * point.z) - innerRadius);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const absX = Math.abs(normal.x);
|
|
250
|
+
const absY = Math.abs(normal.y);
|
|
251
|
+
const absZ = Math.abs(normal.z);
|
|
252
|
+
if (absY >= absX && absY >= absZ) {
|
|
253
|
+
uvs.push(point.x, point.z);
|
|
254
|
+
}
|
|
255
|
+
else if (absX >= absZ) {
|
|
256
|
+
uvs.push(point.z, point.y);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
uvs.push(point.x, point.y);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
const pushTriangle = (a, b, c, normal, materialIndex) => {
|
|
178
263
|
const edgeAB = b.clone().sub(a);
|
|
179
264
|
const edgeAC = c.clone().sub(a);
|
|
180
265
|
const faceNormal = edgeAB.cross(edgeAC);
|
|
@@ -182,11 +267,13 @@ function buildCurvedStepGeometry(innerRadius, outerRadius, startAngle, endAngle,
|
|
|
182
267
|
for (const point of ordered) {
|
|
183
268
|
positions.push(point.x, point.y, point.z);
|
|
184
269
|
normals.push(normal.x, normal.y, normal.z);
|
|
270
|
+
pushUv(point, normal, materialIndex);
|
|
185
271
|
}
|
|
272
|
+
triangleMaterialIndices.push(materialIndex);
|
|
186
273
|
};
|
|
187
|
-
const pushQuad = (a, b, c, d, normal) => {
|
|
188
|
-
pushTriangle(a, b, c, normal);
|
|
189
|
-
pushTriangle(a, c, d, normal);
|
|
274
|
+
const pushQuad = (a, b, c, d, normal, materialIndex) => {
|
|
275
|
+
pushTriangle(a, b, c, normal, materialIndex);
|
|
276
|
+
pushTriangle(a, c, d, normal, materialIndex);
|
|
190
277
|
};
|
|
191
278
|
const upNormal = new THREE.Vector3(0, 1, 0);
|
|
192
279
|
const downNormal = new THREE.Vector3(0, -1, 0);
|
|
@@ -206,10 +293,10 @@ function buildCurvedStepGeometry(innerRadius, outerRadius, startAngle, endAngle,
|
|
|
206
293
|
const outerEndTop = pointOnArc(outerRadius, segEnd, y1);
|
|
207
294
|
const outerNormal = new THREE.Vector3(Math.cos(midAngle), 0, Math.sin(midAngle)).normalize();
|
|
208
295
|
const innerNormal = new THREE.Vector3(-Math.cos(midAngle), 0, -Math.sin(midAngle)).normalize();
|
|
209
|
-
pushQuad(innerStartTop, outerStartTop, outerEndTop, innerEndTop, upNormal);
|
|
210
|
-
pushQuad(innerStartBottom, innerEndBottom, outerEndBottom, outerStartBottom, downNormal);
|
|
211
|
-
pushQuad(innerStartBottom, innerStartTop, innerEndTop, innerEndBottom, innerNormal);
|
|
212
|
-
pushQuad(outerStartBottom, outerEndBottom, outerEndTop, outerStartTop, outerNormal);
|
|
296
|
+
pushQuad(innerStartTop, outerStartTop, outerEndTop, innerEndTop, upNormal, STAIR_TREAD_MATERIAL_INDEX);
|
|
297
|
+
pushQuad(innerStartBottom, innerEndBottom, outerEndBottom, outerStartBottom, downNormal, STAIR_SIDE_MATERIAL_INDEX);
|
|
298
|
+
pushQuad(innerStartBottom, innerStartTop, innerEndTop, innerEndBottom, innerNormal, STAIR_SIDE_MATERIAL_INDEX);
|
|
299
|
+
pushQuad(outerStartBottom, outerEndBottom, outerEndTop, outerStartTop, outerNormal, STAIR_SIDE_MATERIAL_INDEX);
|
|
213
300
|
}
|
|
214
301
|
const startInnerBottom = pointOnArc(innerRadius, startAngle, y0);
|
|
215
302
|
const startOuterBottom = pointOnArc(outerRadius, startAngle, y0);
|
|
@@ -221,11 +308,27 @@ function buildCurvedStepGeometry(innerRadius, outerRadius, startAngle, endAngle,
|
|
|
221
308
|
const endOuterTop = pointOnArc(outerRadius, endAngle, y1);
|
|
222
309
|
const startNormal = new THREE.Vector3(sweepDirection * Math.sin(startAngle), 0, -sweepDirection * Math.cos(startAngle)).normalize();
|
|
223
310
|
const endNormal = new THREE.Vector3(-sweepDirection * Math.sin(endAngle), 0, sweepDirection * Math.cos(endAngle)).normalize();
|
|
224
|
-
pushQuad(startInnerBottom, startOuterBottom, startOuterTop, startInnerTop, startNormal);
|
|
225
|
-
pushQuad(endInnerBottom, endInnerTop, endOuterTop, endOuterBottom, endNormal);
|
|
311
|
+
pushQuad(startInnerBottom, startOuterBottom, startOuterTop, startInnerTop, startNormal, STAIR_SIDE_MATERIAL_INDEX);
|
|
312
|
+
pushQuad(endInnerBottom, endInnerTop, endOuterTop, endOuterBottom, endNormal, STAIR_SIDE_MATERIAL_INDEX);
|
|
226
313
|
const geometry = new THREE.BufferGeometry();
|
|
227
314
|
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
|
228
315
|
geometry.setAttribute('normal', new THREE.Float32BufferAttribute(normals, 3));
|
|
316
|
+
geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));
|
|
317
|
+
geometry.clearGroups();
|
|
318
|
+
let currentMaterial = triangleMaterialIndices[0];
|
|
319
|
+
let groupStart = 0;
|
|
320
|
+
for (let triangleIndex = 1; triangleIndex < triangleMaterialIndices.length; triangleIndex++) {
|
|
321
|
+
const materialIndex = triangleMaterialIndices[triangleIndex];
|
|
322
|
+
if (materialIndex === currentMaterial)
|
|
323
|
+
continue;
|
|
324
|
+
geometry.addGroup(groupStart * 3, (triangleIndex - groupStart) * 3, currentMaterial);
|
|
325
|
+
groupStart = triangleIndex;
|
|
326
|
+
currentMaterial = materialIndex;
|
|
327
|
+
}
|
|
328
|
+
if (triangleMaterialIndices.length > 0) {
|
|
329
|
+
geometry.addGroup(groupStart * 3, (triangleMaterialIndices.length - groupStart) * 3, currentMaterial ?? STAIR_SIDE_MATERIAL_INDEX);
|
|
330
|
+
}
|
|
331
|
+
geometry.setAttribute('uv2', new THREE.Float32BufferAttribute(uvs.slice(), 2));
|
|
229
332
|
geometry.computeVertexNormals();
|
|
230
333
|
return geometry;
|
|
231
334
|
}
|
|
@@ -281,7 +384,8 @@ function buildStairRailPaths(segments, railingMode) {
|
|
|
281
384
|
? ['left', 'right'].map((side) => buildSegmentRailPath(layouts, index, side, landingInset))
|
|
282
385
|
: sideCandidates.map((side) => buildSegmentRailPath(layouts, index, side, landingInset)),
|
|
283
386
|
connectFromPrevious: index > 0 &&
|
|
284
|
-
!(previousLayout?.segment.segmentType === 'landing' &&
|
|
387
|
+
!(previousLayout?.segment.segmentType === 'landing' &&
|
|
388
|
+
layout.segment.segmentType === 'landing'),
|
|
285
389
|
};
|
|
286
390
|
});
|
|
287
391
|
}
|
|
@@ -310,7 +414,9 @@ function buildStairRailPaths(segments, railingMode) {
|
|
|
310
414
|
nextAttachmentSide === railingMode) ||
|
|
311
415
|
suppressMiddleLandingOnPreferredTurnSide;
|
|
312
416
|
const landingContinuesOnPreferredSide = layout.segment.segmentType === 'landing'
|
|
313
|
-
? nextAttachmentSide == null ||
|
|
417
|
+
? nextAttachmentSide == null ||
|
|
418
|
+
nextAttachmentSide === 'front' ||
|
|
419
|
+
nextAttachmentSide === railingMode
|
|
314
420
|
: true;
|
|
315
421
|
const sideCandidates = suppressLandingRailing
|
|
316
422
|
? []
|
|
@@ -395,8 +501,12 @@ function buildSegmentRailPath(layouts, layoutIndex, side, landingInset) {
|
|
|
395
501
|
const stepDepth = segment.length / steps;
|
|
396
502
|
const stepHeight = segment.segmentType === 'landing' ? 0 : segment.height / steps;
|
|
397
503
|
const flightSideOffset = side === 'left' ? segment.width / 2 - 0.045 : -segment.width / 2 + 0.045;
|
|
398
|
-
const flightStartX = previousLayout?.segment.segmentType === 'landing'
|
|
399
|
-
|
|
504
|
+
const flightStartX = previousLayout?.segment.segmentType === 'landing'
|
|
505
|
+
? -segment.length / 2 + landingInset
|
|
506
|
+
: -segment.length / 2;
|
|
507
|
+
const flightEndX = nextLayout?.segment.segmentType === 'landing'
|
|
508
|
+
? segment.length / 2 - landingInset
|
|
509
|
+
: segment.length / 2;
|
|
400
510
|
const landingFrontX = previousLayout?.segment.segmentType === 'stair' &&
|
|
401
511
|
segment.attachmentSide &&
|
|
402
512
|
segment.attachmentSide !== 'front'
|
|
@@ -428,7 +538,9 @@ function buildSegmentRailPath(layouts, layoutIndex, side, landingInset) {
|
|
|
428
538
|
return {
|
|
429
539
|
side,
|
|
430
540
|
points: [
|
|
431
|
-
...(previousLayout?.segment.segmentType === 'landing'
|
|
541
|
+
...(previousLayout?.segment.segmentType === 'landing'
|
|
542
|
+
? []
|
|
543
|
+
: [[flightStartX, stepHeight > 0 ? stepHeight : 0, flightSideOffset]]),
|
|
432
544
|
...Array.from({ length: steps }).map((_, index) => [
|
|
433
545
|
-segment.length / 2 + stepDepth * index + stepDepth / 2,
|
|
434
546
|
stepHeight * (index + 1),
|
|
@@ -452,7 +564,10 @@ function computeSegmentTransforms(segments) {
|
|
|
452
564
|
for (let i = 0; i < segments.length; i++) {
|
|
453
565
|
const segment = segments[i];
|
|
454
566
|
if (i === 0) {
|
|
455
|
-
transforms.push({
|
|
567
|
+
transforms.push({
|
|
568
|
+
position: [currentPos.x, currentPos.y, currentPos.z],
|
|
569
|
+
rotation: currentRot,
|
|
570
|
+
});
|
|
456
571
|
continue;
|
|
457
572
|
}
|
|
458
573
|
const prev = segments[i - 1];
|
|
@@ -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,
|
|
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,4CA4CxE,CAAA"}
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useRegistry, useScene } from '@pascal-app/core';
|
|
3
|
-
import { useLayoutEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { useRegistry, useScene, } from '@pascal-app/core';
|
|
3
|
+
import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
|
|
4
|
+
import * as THREE from 'three';
|
|
4
5
|
import { useNodeEvents } from '../../../hooks/use-node-events';
|
|
5
|
-
import {
|
|
6
|
+
import { getStraightStairSegmentBodyMaterials } from '../../../systems/stair/stair-materials';
|
|
6
7
|
export const StairSegmentRenderer = ({ node }) => {
|
|
7
8
|
const ref = useRef(null);
|
|
9
|
+
const nodes = useScene((state) => state.nodes);
|
|
8
10
|
useRegistry(node.id, 'stair-segment', ref);
|
|
9
11
|
useLayoutEffect(() => {
|
|
10
12
|
useScene.getState().markDirty(node.id);
|
|
11
13
|
}, [node.id]);
|
|
12
14
|
const handlers = useNodeEvents(node, 'stair-segment');
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const parentNode = node.parentId
|
|
16
|
+
? nodes[node.parentId]
|
|
17
|
+
: undefined;
|
|
18
|
+
const material = useMemo(() => getStraightStairSegmentBodyMaterials(node, parentNode), [node, parentNode]);
|
|
19
|
+
const placeholderGeometry = useMemo(() => {
|
|
20
|
+
const geometry = new THREE.BufferGeometry();
|
|
21
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3));
|
|
22
|
+
geometry.addGroup(0, 0, 0);
|
|
23
|
+
geometry.addGroup(0, 0, 1);
|
|
24
|
+
return geometry;
|
|
25
|
+
}, []);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
return () => {
|
|
28
|
+
placeholderGeometry.dispose();
|
|
29
|
+
};
|
|
30
|
+
}, [placeholderGeometry]);
|
|
31
|
+
return (_jsx("mesh", { geometry: placeholderGeometry, material: material, position: node.position, ref: ref, "rotation-y": node.rotation, visible: node.visible, ...handlers }));
|
|
20
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wall-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/wall/wall-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAOvE,eAAO,MAAM,YAAY,GAAI,UAAU;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"wall-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/wall/wall-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAOvE,eAAO,MAAM,YAAY,GAAI,UAAU;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,4CAwBxD,CAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useRegistry, useScene } from '@pascal-app/core';
|
|
3
|
-
import { useLayoutEffect,
|
|
3
|
+
import { useLayoutEffect, useRef } from 'react';
|
|
4
4
|
import { useNodeEvents } from '../../../hooks/use-node-events';
|
|
5
|
-
import {
|
|
5
|
+
import { getVisibleWallMaterials } from '../../../systems/wall/wall-materials';
|
|
6
6
|
import { NodeRenderer } from '../node-renderer';
|
|
7
7
|
export const WallRenderer = ({ node }) => {
|
|
8
8
|
const ref = useRef(null);
|
|
@@ -11,11 +11,6 @@ export const WallRenderer = ({ node }) => {
|
|
|
11
11
|
useScene.getState().markDirty(node.id);
|
|
12
12
|
}, [node.id]);
|
|
13
13
|
const handlers = useNodeEvents(node, 'wall');
|
|
14
|
-
const material =
|
|
15
|
-
|
|
16
|
-
if (!mat)
|
|
17
|
-
return DEFAULT_WALL_MATERIAL;
|
|
18
|
-
return createMaterial(mat);
|
|
19
|
-
}, [node.material, node.material?.preset, node.material?.properties, node.material?.texture]);
|
|
20
|
-
return (_jsxs("mesh", { castShadow: true, material: material, receiveShadow: true, ref: ref, visible: node.visible, children: [_jsx("boxGeometry", { args: [0, 0, 0] }), _jsx("mesh", { name: "collision-mesh", visible: false, ...handlers, children: _jsx("boxGeometry", { args: [0, 0, 0] }) }), node.children.map((childId) => (_jsx(NodeRenderer, { nodeId: childId }, childId)))] }));
|
|
14
|
+
const material = getVisibleWallMaterials(node);
|
|
15
|
+
return (_jsxs("mesh", { castShadow: true, material: material, receiveShadow: true, ref: ref, visible: node.visible, children: [_jsx("boxGeometry", { args: [0, 0, 0] }), _jsx("mesh", { name: "collision-mesh", visible: false, ...handlers, children: _jsx("boxGeometry", { args: [0, 0, 0] }) }), node.children.map((childId) => (_jsx(NodeRenderer, { nodeId: childId }, `${node.id}:${childId}`)))] }));
|
|
21
16
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"window-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/window/window-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"window-renderer.d.ts","sourceRoot":"","sources":["../../../../src/components/renderers/window/window-renderer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAMzE,eAAO,MAAM,cAAc,GAAI,UAAU;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,4CA8B5D,CAAA"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useRegistry } from '@pascal-app/core';
|
|
3
|
-
import { useMemo, useRef } from 'react';
|
|
2
|
+
import { useRegistry, useScene } from '@pascal-app/core';
|
|
3
|
+
import { useLayoutEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { useNodeEvents } from '../../../hooks/use-node-events';
|
|
5
5
|
import { createMaterial, DEFAULT_WINDOW_MATERIAL } from '../../../lib/materials';
|
|
6
6
|
export const WindowRenderer = ({ node }) => {
|
|
7
7
|
const ref = useRef(null);
|
|
8
8
|
useRegistry(node.id, 'window', ref);
|
|
9
|
+
useLayoutEffect(() => {
|
|
10
|
+
useScene.getState().markDirty(node.id);
|
|
11
|
+
}, [node.id]);
|
|
9
12
|
const handlers = useNodeEvents(node, 'window');
|
|
10
13
|
const isTransient = !!node.metadata?.isTransient;
|
|
11
14
|
const material = useMemo(() => {
|
|
@@ -0,0 +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,CAgC7C,CAAA;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useThree } from '@react-three/fiber';
|
|
2
|
+
import { useLayoutEffect } from 'react';
|
|
3
|
+
const FrameLimiter = ({ fps = 50 }) => {
|
|
4
|
+
const { advance, set, frameloop: initFrameloop } = useThree();
|
|
5
|
+
useLayoutEffect(() => {
|
|
6
|
+
let elapsed = 0;
|
|
7
|
+
let then = 0;
|
|
8
|
+
let i = 0;
|
|
9
|
+
let raf = null;
|
|
10
|
+
const interval = 1000 / fps;
|
|
11
|
+
function tick(t) {
|
|
12
|
+
raf = requestAnimationFrame(tick);
|
|
13
|
+
elapsed = t - then;
|
|
14
|
+
if (elapsed > interval) {
|
|
15
|
+
advance(i);
|
|
16
|
+
i += elapsed / 1000 - (elapsed % interval) / 1000;
|
|
17
|
+
then = t - (elapsed % interval);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
set({ frameloop: 'never' });
|
|
21
|
+
raf = requestAnimationFrame(tick);
|
|
22
|
+
return () => {
|
|
23
|
+
if (raf) {
|
|
24
|
+
cancelAnimationFrame(raf);
|
|
25
|
+
}
|
|
26
|
+
set({ frameloop: initFrameloop });
|
|
27
|
+
};
|
|
28
|
+
}, [fps, advance, set, initFrameloop]);
|
|
29
|
+
return null;
|
|
30
|
+
};
|
|
31
|
+
export default FrameLimiter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ground-occluder.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/ground-occluder.tsx"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,+
|
|
1
|
+
{"version":3,"file":"ground-occluder.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/ground-occluder.tsx"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,+CAuG1B,CAAA"}
|
|
@@ -31,7 +31,11 @@ export const GroundOccluder = () => {
|
|
|
31
31
|
// reveal their footprint on the level-zero ground material.
|
|
32
32
|
const polygons = [];
|
|
33
33
|
Object.values(nodes).forEach((node) => {
|
|
34
|
-
if (!(node.type === 'slab' &&
|
|
34
|
+
if (!(node.type === 'slab' &&
|
|
35
|
+
node.visible &&
|
|
36
|
+
node.polygon.length >= 3 &&
|
|
37
|
+
// Only recessed slabs should punch through the ground plane.
|
|
38
|
+
(node.elevation ?? 0.05) < 0)) {
|
|
35
39
|
return;
|
|
36
40
|
}
|
|
37
41
|
if (Number.isFinite(lowestLevelIndex)) {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { type ThreeToJSXElements } from '@react-three/fiber';
|
|
2
2
|
import * as THREE from 'three/webgpu';
|
|
3
|
+
import { type HoverStyles } from './post-processing';
|
|
3
4
|
declare module '@react-three/fiber' {
|
|
4
5
|
interface ThreeElements extends ThreeToJSXElements<typeof THREE> {
|
|
5
6
|
}
|
|
6
7
|
}
|
|
7
8
|
interface ViewerProps {
|
|
8
9
|
children?: React.ReactNode;
|
|
10
|
+
hoverStyles?: HoverStyles;
|
|
9
11
|
selectionManager?: 'default' | 'custom';
|
|
10
12
|
perf?: boolean;
|
|
11
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/index.tsx"],"names":[],"mappings":"
|
|
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;CACf;AAED,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAmGjC,CAAA;AASD,eAAe,MAAM,CAAA"}
|