@pascal-app/viewer 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -21
- package/dist/components/viewer/daylight-atmosphere.d.ts +9 -0
- package/dist/components/viewer/daylight-atmosphere.d.ts.map +1 -0
- package/dist/components/viewer/daylight-atmosphere.js +315 -0
- package/dist/components/viewer/drone-controller.d.ts +15 -0
- package/dist/components/viewer/drone-controller.d.ts.map +1 -0
- package/dist/components/viewer/drone-controller.js +194 -0
- package/dist/components/viewer/glb-interactive.d.ts +4 -18
- package/dist/components/viewer/glb-interactive.d.ts.map +1 -1
- package/dist/components/viewer/glb-interactive.js +32 -268
- package/dist/components/viewer/glb-replace-instances.d.ts +6 -3
- package/dist/components/viewer/glb-replace-instances.d.ts.map +1 -1
- package/dist/components/viewer/glb-replace-instances.js +5 -4
- package/dist/components/viewer/glb-scene-motion.d.ts +8 -0
- package/dist/components/viewer/glb-scene-motion.d.ts.map +1 -0
- package/dist/components/viewer/glb-scene-motion.js +57 -0
- package/dist/components/viewer/glb-scene.d.ts +5 -1
- package/dist/components/viewer/glb-scene.d.ts.map +1 -1
- package/dist/components/viewer/glb-scene.js +290 -49
- package/dist/components/viewer/glb-selection-callout.d.ts +17 -0
- package/dist/components/viewer/glb-selection-callout.d.ts.map +1 -0
- package/dist/components/viewer/glb-selection-callout.js +54 -0
- package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -1
- package/dist/components/viewer/glb-walkthrough-controller.js +6 -3
- package/dist/components/viewer/index.d.ts +5 -0
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +38 -10
- package/dist/components/viewer/lights.d.ts.map +1 -1
- package/dist/components/viewer/lights.js +192 -5
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +150 -94
- package/dist/components/viewer/registered-systems.d.ts.map +1 -1
- package/dist/components/viewer/registered-systems.js +2 -2
- package/dist/components/viewer/scene-environment.js +4 -5
- package/dist/components/viewer/selection-callout.d.ts +51 -0
- package/dist/components/viewer/selection-callout.d.ts.map +1 -0
- package/dist/components/viewer/selection-callout.js +197 -0
- package/dist/components/viewer/unsupported-gpu-fallback.d.ts.map +1 -1
- package/dist/components/viewer/unsupported-gpu-fallback.js +21 -1
- package/dist/components/viewer/use-daylight-rooms.d.ts +13 -0
- package/dist/components/viewer/use-daylight-rooms.d.ts.map +1 -0
- package/dist/components/viewer/use-daylight-rooms.js +278 -0
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
- package/dist/components/viewer/viewer-camera.js +12 -1
- package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
- package/dist/hooks/use-gltf-ktx2.js +2 -1
- package/dist/index.d.ts +26 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -8
- package/dist/lib/asset-url.d.ts +0 -1
- package/dist/lib/asset-url.d.ts.map +1 -1
- package/dist/lib/asset-url.js +3 -3
- package/dist/lib/daylight/ground.d.ts +21 -0
- package/dist/lib/daylight/ground.d.ts.map +1 -0
- package/dist/lib/daylight/ground.js +53 -0
- package/dist/lib/daylight/location.d.ts +32 -0
- package/dist/lib/daylight/location.d.ts.map +1 -0
- package/dist/lib/daylight/location.js +74 -0
- package/dist/lib/daylight/look.d.ts +33 -0
- package/dist/lib/daylight/look.d.ts.map +1 -0
- package/dist/lib/daylight/look.js +13 -0
- package/dist/lib/daylight/material-hooks.d.ts +2 -0
- package/dist/lib/daylight/material-hooks.d.ts.map +1 -0
- package/dist/lib/daylight/material-hooks.js +150 -0
- package/dist/lib/daylight/room-context.d.ts +12 -0
- package/dist/lib/daylight/room-context.d.ts.map +1 -0
- package/dist/lib/daylight/room-context.js +54 -0
- package/dist/lib/daylight/room-map.d.ts +124 -0
- package/dist/lib/daylight/room-map.d.ts.map +1 -0
- package/dist/lib/daylight/room-map.js +630 -0
- package/dist/lib/daylight/room-scene.d.ts +56 -0
- package/dist/lib/daylight/room-scene.d.ts.map +1 -0
- package/dist/lib/daylight/room-scene.js +391 -0
- package/dist/lib/daylight/rooms.d.ts +292 -0
- package/dist/lib/daylight/rooms.d.ts.map +1 -0
- package/dist/lib/daylight/rooms.js +1268 -0
- package/dist/lib/daylight/runtime.d.ts +33 -0
- package/dist/lib/daylight/runtime.d.ts.map +1 -0
- package/dist/lib/daylight/runtime.js +42 -0
- package/dist/lib/daylight/sky.d.ts +26 -0
- package/dist/lib/daylight/sky.d.ts.map +1 -0
- package/dist/lib/daylight/sky.js +217 -0
- package/dist/lib/daylight/solar.d.ts +46 -0
- package/dist/lib/daylight/solar.d.ts.map +1 -0
- package/dist/lib/daylight/solar.js +156 -0
- package/dist/lib/device-tier.d.ts +29 -0
- package/dist/lib/device-tier.d.ts.map +1 -0
- package/dist/lib/device-tier.js +71 -0
- package/dist/lib/dispose-object3d.d.ts.map +1 -1
- package/dist/lib/dispose-object3d.js +4 -2
- package/dist/lib/drone-flight.d.ts +44 -0
- package/dist/lib/drone-flight.d.ts.map +1 -0
- package/dist/lib/drone-flight.js +121 -0
- package/dist/lib/editor-highlight.d.ts +16 -0
- package/dist/lib/editor-highlight.d.ts.map +1 -0
- package/dist/lib/editor-highlight.js +33 -0
- package/dist/lib/foundation-materials.d.ts.map +1 -1
- package/dist/lib/foundation-materials.js +2 -4
- package/dist/lib/glb-merge.d.ts +23 -0
- package/dist/lib/glb-merge.d.ts.map +1 -0
- package/dist/lib/glb-merge.js +184 -0
- package/dist/lib/hardware-geometry.d.ts +21 -0
- package/dist/lib/hardware-geometry.d.ts.map +1 -0
- package/dist/lib/hardware-geometry.js +283 -0
- package/dist/lib/ktx2-loader.d.ts.map +1 -1
- package/dist/lib/ktx2-loader.js +2 -1
- package/dist/lib/layer-pass.d.ts +2 -0
- package/dist/lib/layer-pass.d.ts.map +1 -1
- package/dist/lib/layer-pass.js +20 -0
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +50 -23
- package/dist/lib/measurement-label.d.ts +4 -0
- package/dist/lib/measurement-label.d.ts.map +1 -0
- package/dist/lib/measurement-label.js +54 -0
- package/dist/lib/measurement-presentation.d.ts +5 -0
- package/dist/lib/measurement-presentation.d.ts.map +1 -0
- package/dist/lib/measurement-presentation.js +8 -0
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +7 -1
- package/dist/lib/occlusion-culler.d.ts +34 -0
- package/dist/lib/occlusion-culler.d.ts.map +1 -0
- package/dist/lib/occlusion-culler.js +698 -0
- package/dist/lib/pointer-events.d.ts.map +1 -1
- package/dist/lib/pointer-events.js +3 -3
- package/dist/lib/post-processing-resources.d.ts +4 -0
- package/dist/lib/post-processing-resources.d.ts.map +1 -1
- package/dist/lib/post-processing-resources.js +5 -0
- package/dist/lib/readback-rows.d.ts +14 -0
- package/dist/lib/readback-rows.d.ts.map +1 -0
- package/dist/lib/readback-rows.js +31 -0
- package/dist/lib/reveal-pose.d.ts.map +1 -1
- package/dist/lib/reveal-pose.js +3 -0
- package/dist/lib/scene-matrices.d.ts +12 -0
- package/dist/lib/scene-matrices.d.ts.map +1 -0
- package/dist/lib/scene-matrices.js +287 -0
- package/dist/lib/scene-pass-mrt.d.ts +5 -2
- package/dist/lib/scene-pass-mrt.d.ts.map +1 -1
- package/dist/lib/scene-pass-mrt.js +7 -2
- package/dist/lib/scene-themes.d.ts +0 -2
- package/dist/lib/scene-themes.d.ts.map +1 -1
- package/dist/lib/scene-themes.js +0 -2
- package/dist/lib/scene-visibility.d.ts +2 -0
- package/dist/lib/scene-visibility.d.ts.map +1 -1
- package/dist/lib/scene-visibility.js +12 -3
- package/dist/lib/site-surfaces.d.ts +1 -8
- package/dist/lib/site-surfaces.d.ts.map +1 -1
- package/dist/lib/site-surfaces.js +0 -19
- package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
- package/dist/lib/snapshot-pipeline.js +24 -40
- package/dist/lib/texture-reference.d.ts.map +1 -1
- package/dist/lib/texture-reference.js +13 -10
- package/dist/lib/underground-ambiance.d.ts +0 -2
- package/dist/lib/underground-ambiance.d.ts.map +1 -1
- package/dist/lib/underground-ambiance.js +0 -2
- package/dist/lib/viewer-config.d.ts +21 -0
- package/dist/lib/viewer-config.d.ts.map +1 -0
- package/dist/lib/viewer-config.js +21 -0
- package/dist/lib/viewer-preference-storage.d.ts +7 -0
- package/dist/lib/viewer-preference-storage.d.ts.map +1 -0
- package/dist/lib/viewer-preference-storage.js +23 -0
- package/dist/store/use-item-light-pool.d.ts +3 -6
- package/dist/store/use-item-light-pool.d.ts.map +1 -1
- package/dist/store/use-item-light-pool.js +12 -0
- package/dist/store/use-viewer.d.ts +62 -59
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +106 -19
- package/dist/systems/ceiling/ceiling-system.d.ts +5 -0
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +11 -1
- package/dist/systems/door/door-system.d.ts.map +1 -1
- package/dist/systems/door/door-system.js +501 -145
- package/dist/systems/door/leaf-profile.d.ts +11 -0
- package/dist/systems/door/leaf-profile.d.ts.map +1 -0
- package/dist/systems/door/leaf-profile.js +140 -0
- package/dist/systems/elevator/elevator-interaction-system.d.ts +16 -2
- package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -1
- package/dist/systems/elevator/elevator-interaction-system.js +41 -8
- package/dist/systems/geometry/geometry-status.d.ts +8 -0
- package/dist/systems/geometry/geometry-status.d.ts.map +1 -0
- package/dist/systems/geometry/geometry-status.js +24 -0
- package/dist/systems/interactive/callout-actions.d.ts +72 -0
- package/dist/systems/interactive/callout-actions.d.ts.map +1 -0
- package/dist/systems/interactive/callout-actions.js +212 -0
- package/dist/systems/interactive/interactive-system.d.ts +5 -1
- package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
- package/dist/systems/interactive/interactive-system.js +44 -121
- package/dist/systems/interactive/opening-settled.d.ts +16 -0
- package/dist/systems/interactive/opening-settled.d.ts.map +1 -0
- package/dist/systems/interactive/opening-settled.js +53 -0
- package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
- package/dist/systems/item-light/item-light-system.js +22 -214
- package/dist/systems/item-light/pooled-lights.d.ts +70 -0
- package/dist/systems/item-light/pooled-lights.d.ts.map +1 -0
- package/dist/systems/item-light/pooled-lights.js +449 -0
- package/dist/systems/level/level-system.d.ts.map +1 -1
- package/dist/systems/level/level-system.js +19 -1
- package/dist/systems/roof/roof-material-slots.d.ts +14 -0
- package/dist/systems/roof/roof-material-slots.d.ts.map +1 -0
- package/dist/systems/roof/roof-material-slots.js +13 -0
- package/dist/systems/roof/roof-materials.d.ts +25 -2
- package/dist/systems/roof/roof-materials.d.ts.map +1 -1
- package/dist/systems/roof/roof-materials.js +85 -26
- package/dist/systems/roof/roof-system.d.ts +34 -1
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +582 -168
- package/dist/systems/wall/opening-casing-geometry.d.ts +14 -0
- package/dist/systems/wall/opening-casing-geometry.d.ts.map +1 -0
- package/dist/systems/wall/opening-casing-geometry.js +102 -0
- package/dist/systems/wall/opening-cutout-geometry.d.ts +9 -0
- package/dist/systems/wall/opening-cutout-geometry.d.ts.map +1 -1
- package/dist/systems/wall/opening-cutout-geometry.js +7 -3
- package/dist/systems/wall/wall-materials.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.js +28 -35
- package/dist/systems/wall/wall-system.d.ts +11 -0
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +86 -25
- package/dist/systems/wall/wall-t-junctions.d.ts +15 -0
- package/dist/systems/wall/wall-t-junctions.d.ts.map +1 -0
- package/dist/systems/wall/wall-t-junctions.js +149 -0
- package/dist/systems/window/window-animation-system.d.ts +3 -12
- package/dist/systems/window/window-animation-system.d.ts.map +1 -1
- package/dist/systems/window/window-animation-system.js +37 -122
- package/dist/systems/window/window-pose.d.ts +31 -0
- package/dist/systems/window/window-pose.d.ts.map +1 -0
- package/dist/systems/window/window-pose.js +152 -0
- package/dist/systems/window/window-roller-shutter.d.ts +8 -0
- package/dist/systems/window/window-roller-shutter.d.ts.map +1 -0
- package/dist/systems/window/window-roller-shutter.js +64 -0
- package/dist/systems/window/window-system.d.ts +2 -11
- package/dist/systems/window/window-system.d.ts.map +1 -1
- package/dist/systems/window/window-system.js +470 -303
- package/package.json +6 -6
- package/dist/systems/interactive/control-widget.d.ts +0 -10
- package/dist/systems/interactive/control-widget.d.ts.map +0 -1
- package/dist/systems/interactive/control-widget.js +0 -35
- package/dist/systems/interactive/procedural-controls.d.ts +0 -13
- package/dist/systems/interactive/procedural-controls.d.ts.map +0 -1
- package/dist/systems/interactive/procedural-controls.js +0 -17
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { BoxGeometry, CapsuleGeometry, CatmullRomCurve3, CylinderGeometry, LatheGeometry, SphereGeometry, TubeGeometry, Vector2, Vector3, } from 'three';
|
|
2
|
+
import { RoundedBoxGeometry } from 'three/addons/geometries/RoundedBoxGeometry.js';
|
|
3
|
+
import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js';
|
|
4
|
+
const cache = new Map();
|
|
5
|
+
const mm = (value) => Math.round(value * 1000);
|
|
6
|
+
function cached(name, dimensions, build) {
|
|
7
|
+
const sizes = dimensions.map(mm);
|
|
8
|
+
const key = `${name}:${sizes.join(':')}`;
|
|
9
|
+
let geometry = cache.get(key);
|
|
10
|
+
if (!geometry) {
|
|
11
|
+
geometry = build(...sizes.map((size) => size / 1000));
|
|
12
|
+
geometry.userData.shared = true;
|
|
13
|
+
cache.set(key, geometry);
|
|
14
|
+
}
|
|
15
|
+
return geometry;
|
|
16
|
+
}
|
|
17
|
+
function scaleUVs(geometry, u, v) {
|
|
18
|
+
const uv = geometry.getAttribute('uv');
|
|
19
|
+
for (let i = 0; i < uv.count; i++)
|
|
20
|
+
uv.setXY(i, uv.getX(i) * u, uv.getY(i) * v);
|
|
21
|
+
}
|
|
22
|
+
function lathe(profile, segments) {
|
|
23
|
+
const geometry = new LatheGeometry(profile.map(([r, y]) => new Vector2(r, y)), segments);
|
|
24
|
+
geometry.normalizeNormals();
|
|
25
|
+
const uv = geometry.getAttribute('uv');
|
|
26
|
+
let distance = 0;
|
|
27
|
+
for (let j = 0; j < profile.length; j++) {
|
|
28
|
+
const [r, y] = profile[j];
|
|
29
|
+
if (j > 0) {
|
|
30
|
+
const [previousR, previousY] = profile[j - 1];
|
|
31
|
+
distance += Math.hypot(r - previousR, y - previousY);
|
|
32
|
+
}
|
|
33
|
+
for (let i = 0; i <= segments; i++) {
|
|
34
|
+
uv.setXY(i * profile.length + j, (i / segments) * 2 * Math.PI * r, distance);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return geometry;
|
|
38
|
+
}
|
|
39
|
+
function cylinder(radius, length, segments) {
|
|
40
|
+
const geometry = new CylinderGeometry(radius, radius, length, segments);
|
|
41
|
+
const uv = geometry.getAttribute('uv');
|
|
42
|
+
const position = geometry.getAttribute('position');
|
|
43
|
+
const sideVertices = (segments + 1) * 2;
|
|
44
|
+
for (let i = 0; i < uv.count; i++) {
|
|
45
|
+
if (i < sideVertices) {
|
|
46
|
+
uv.setXY(i, uv.getX(i) * 2 * Math.PI * radius, uv.getY(i) * length);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
uv.setXY(i, position.getX(i), position.getZ(i));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return geometry;
|
|
53
|
+
}
|
|
54
|
+
function merge(parts) {
|
|
55
|
+
const indexed = parts.every((part) => part.index !== null);
|
|
56
|
+
const normalized = parts.map((part) => (!indexed && part.index ? part.toNonIndexed() : part));
|
|
57
|
+
const geometry = mergeGeometries(normalized);
|
|
58
|
+
for (const part of normalized)
|
|
59
|
+
if (!parts.includes(part))
|
|
60
|
+
part.dispose();
|
|
61
|
+
for (const part of parts)
|
|
62
|
+
part.dispose();
|
|
63
|
+
return geometry;
|
|
64
|
+
}
|
|
65
|
+
function hemisphere(radius, radialSegments, heightSegments) {
|
|
66
|
+
const geometry = new SphereGeometry(radius, radialSegments, heightSegments, 0, 2 * Math.PI, 0, Math.PI / 2);
|
|
67
|
+
scaleUVs(geometry, 2 * Math.PI * radius, (Math.PI * radius) / 2);
|
|
68
|
+
return geometry;
|
|
69
|
+
}
|
|
70
|
+
/** Origin is the spindle on the mounting face; the grip points along +X, out along +Z. */
|
|
71
|
+
function buildLever(curved, plate = false) {
|
|
72
|
+
return cached(plate ? 'lever-plate' : curved ? 'lever-curved' : 'lever-straight', [], () => {
|
|
73
|
+
const faceFillet = 0.0005;
|
|
74
|
+
const faceRadius = 0.0245 - faceFillet * (Math.SQRT2 - 1);
|
|
75
|
+
const profile = [
|
|
76
|
+
[0, 0],
|
|
77
|
+
[0.026, 0],
|
|
78
|
+
[0.026, 0.0075],
|
|
79
|
+
];
|
|
80
|
+
for (const angle of [Math.PI / 4, Math.PI / 2]) {
|
|
81
|
+
profile.push([
|
|
82
|
+
faceRadius + faceFillet * Math.cos(angle),
|
|
83
|
+
0.0085 + faceFillet * Math.sin(angle),
|
|
84
|
+
]);
|
|
85
|
+
}
|
|
86
|
+
profile.push([0, 0.009]);
|
|
87
|
+
const rose = plate
|
|
88
|
+
? roundedBox(0.04, 0.22, 0.006, 0.003).clone().translate(0, 0, 0.003)
|
|
89
|
+
: lathe(profile, 32).rotateX(Math.PI / 2);
|
|
90
|
+
const neck = cylinder(0.01, 0.037, 16)
|
|
91
|
+
.rotateX(Math.PI / 2)
|
|
92
|
+
.translate(0, 0, 0.009 + 0.037 / 2);
|
|
93
|
+
const neckProfile = [];
|
|
94
|
+
for (let i = 0; i <= 4; i++) {
|
|
95
|
+
const angle = (i * Math.PI) / 8;
|
|
96
|
+
neckProfile.push([0.009 + 0.001 * Math.cos(angle), 0.046 + 0.001 * Math.sin(angle)]);
|
|
97
|
+
}
|
|
98
|
+
neckProfile.push([0, 0.047]);
|
|
99
|
+
const fillet = lathe(neckProfile, 16);
|
|
100
|
+
const filletNormals = fillet.getAttribute('normal');
|
|
101
|
+
// Match the cylinder tangent exactly rather than averaging the first fillet chord.
|
|
102
|
+
for (let i = 0; i <= 16; i++) {
|
|
103
|
+
const phi = (i * 2 * Math.PI) / 16;
|
|
104
|
+
for (let j = 0; j < neckProfile.length; j++) {
|
|
105
|
+
const angle = (Math.min(j, 4) * Math.PI) / 8;
|
|
106
|
+
filletNormals.setXYZ(i * neckProfile.length + j, Math.cos(angle) * Math.sin(phi), Math.sin(angle), Math.cos(angle) * Math.cos(phi));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
fillet.rotateX(Math.PI / 2);
|
|
110
|
+
const curve = new CatmullRomCurve3((curved
|
|
111
|
+
? [
|
|
112
|
+
[0, 0],
|
|
113
|
+
[0.01, 0],
|
|
114
|
+
[0.02, 0],
|
|
115
|
+
[0.035, 0],
|
|
116
|
+
[0.065, -0.004],
|
|
117
|
+
[0.095, -0.011],
|
|
118
|
+
[0.105, -0.012],
|
|
119
|
+
[0.1155, -0.012],
|
|
120
|
+
]
|
|
121
|
+
: [
|
|
122
|
+
[0, 0],
|
|
123
|
+
[0.1155, 0],
|
|
124
|
+
]).map(([x, y]) => new Vector3(x, y, 0.047)));
|
|
125
|
+
const grip = new TubeGeometry(curve, curved ? 24 : 2, 0.0095, 16, false);
|
|
126
|
+
scaleUVs(grip, curve.getLength(), 2 * Math.PI * 0.0095);
|
|
127
|
+
const cap = hemisphere(0.0095, 12, 6)
|
|
128
|
+
.rotateZ(-Math.PI / 2)
|
|
129
|
+
.translate(0.1155, curved ? -0.012 : 0, 0.047);
|
|
130
|
+
// Close the heel where the horizontal grip meets the vertical neck.
|
|
131
|
+
const heel = hemisphere(0.0095, 12, 6)
|
|
132
|
+
.rotateZ(Math.PI / 2)
|
|
133
|
+
.translate(0, 0, 0.047);
|
|
134
|
+
if (plate)
|
|
135
|
+
for (const part of [neck, fillet, grip, cap, heel])
|
|
136
|
+
part.translate(0, 0, -0.003);
|
|
137
|
+
return merge([rose, neck, fillet, grip, cap, heel]);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
export function leverOnRose() {
|
|
141
|
+
return buildLever(false);
|
|
142
|
+
}
|
|
143
|
+
export function leverOnRoseCurved() {
|
|
144
|
+
return buildLever(true);
|
|
145
|
+
}
|
|
146
|
+
export function leverOnPlate() {
|
|
147
|
+
return buildLever(false, true);
|
|
148
|
+
}
|
|
149
|
+
/** Origin at the mounting face; a 56 mm ball on a 20 mm neck and 56 mm rose. */
|
|
150
|
+
export function knobOnRose() {
|
|
151
|
+
return cached('knob', [], () => {
|
|
152
|
+
const rose = cylinder(0.028, 0.006, 32)
|
|
153
|
+
.rotateX(Math.PI / 2)
|
|
154
|
+
.translate(0, 0, 0.003);
|
|
155
|
+
const neck = cylinder(0.01, 0.025, 16)
|
|
156
|
+
.rotateX(Math.PI / 2)
|
|
157
|
+
.translate(0, 0, 0.0185);
|
|
158
|
+
const ball = new SphereGeometry(0.028, 32, 16);
|
|
159
|
+
scaleUVs(ball, 2 * Math.PI * 0.028, Math.PI * 0.028);
|
|
160
|
+
ball.translate(0, 0, 0.052);
|
|
161
|
+
return merge([rose, neck, ball]);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/** Origin at the face; a 40 × 120 mm open cup with a 3 mm rim, recessed 12 mm. */
|
|
165
|
+
export function flushPull() {
|
|
166
|
+
return cached('flush-pull', [], () => {
|
|
167
|
+
const parts = [];
|
|
168
|
+
const box = (w, h, d, x, y, z) => {
|
|
169
|
+
const geometry = new BoxGeometry(w, h, d);
|
|
170
|
+
boxUVs(geometry, w, h, d);
|
|
171
|
+
parts.push(geometry.translate(x, y, z));
|
|
172
|
+
};
|
|
173
|
+
box(0.04, 0.12, 0.002, 0, 0, -0.011);
|
|
174
|
+
for (const side of [-1, 1]) {
|
|
175
|
+
box(0.002, 0.12, 0.01, side * 0.019, 0, -0.005);
|
|
176
|
+
box(0.036, 0.002, 0.01, 0, side * 0.059, -0.005);
|
|
177
|
+
box(0.003, 0.126, 0.001, side * 0.0215, 0, 0.0005);
|
|
178
|
+
box(0.04, 0.003, 0.001, 0, side * 0.0615, 0.0005);
|
|
179
|
+
}
|
|
180
|
+
return merge(parts);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function hingePart(leaf, diameter, height) {
|
|
184
|
+
return cached(leaf ? 'hinge-leaf' : 'hinge-jamb', [diameter, height], (d, h) => {
|
|
185
|
+
const radialScale = d / 0.014;
|
|
186
|
+
const heightScale = h / 0.103;
|
|
187
|
+
const radius = d / 2;
|
|
188
|
+
const plateW = 0.0025 * radialScale;
|
|
189
|
+
const plateH = 0.089 * heightScale;
|
|
190
|
+
const plateD = 0.028 * radialScale;
|
|
191
|
+
const plate = new BoxGeometry(plateW, plateH, plateD);
|
|
192
|
+
boxUVs(plate, plateW, plateH, plateD);
|
|
193
|
+
plate.translate(leaf ? plateW / 2 : -plateW / 2, 0, -plateD / 2);
|
|
194
|
+
const parts = [plate];
|
|
195
|
+
for (let i = leaf ? 0 : 1; i < 5; i += 2) {
|
|
196
|
+
parts.push(cylinder(radius, 0.017 * heightScale, 16).translate(0, (-0.036 + i * 0.018) * heightScale, 0));
|
|
197
|
+
}
|
|
198
|
+
if (leaf) {
|
|
199
|
+
for (const side of [-1, 1]) {
|
|
200
|
+
const cap = hemisphere(radius, 12, d <= 0.01 ? 2 : 3);
|
|
201
|
+
const capScale = heightScale / radialScale;
|
|
202
|
+
cap.scale(1, capScale, 1);
|
|
203
|
+
const uv = cap.getAttribute('uv');
|
|
204
|
+
for (let i = 0; i < uv.count; i++)
|
|
205
|
+
uv.setY(i, uv.getY(i) * capScale);
|
|
206
|
+
if (side < 0)
|
|
207
|
+
cap.rotateX(Math.PI);
|
|
208
|
+
parts.push(cap.translate(0, side * 0.0445 * heightScale, 0));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return merge(parts);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/** Odd knuckles and plate on the leaf edge (+X), extending into the rebate (-Z). */
|
|
215
|
+
export function hingeLeafPart(diameter = 0.014, height = 0.103) {
|
|
216
|
+
return hingePart(true, diameter, height);
|
|
217
|
+
}
|
|
218
|
+
/** Even knuckles and plate on the jamb face (-X), extending into the rebate (-Z). */
|
|
219
|
+
export function hingeJambPart(diameter = 0.014, height = 0.103) {
|
|
220
|
+
return hingePart(false, diameter, height);
|
|
221
|
+
}
|
|
222
|
+
/** Origin on the mounting face; bar along Y, projecting along +Z. */
|
|
223
|
+
export function pullBar(doorScale = false) {
|
|
224
|
+
return cached(doorScale ? 'door-pull' : 'pull', [], () => {
|
|
225
|
+
if (doorScale) {
|
|
226
|
+
const bar = cylinder(0.0125, 0.4, 32).translate(0, 0, 0.05);
|
|
227
|
+
return merge([
|
|
228
|
+
bar,
|
|
229
|
+
...[-0.15, 0.15].map((y) => cylinder(0.008, 0.05, 16)
|
|
230
|
+
.rotateX(Math.PI / 2)
|
|
231
|
+
.translate(0, y, 0.025)),
|
|
232
|
+
]);
|
|
233
|
+
}
|
|
234
|
+
const bar = new CapsuleGeometry(0.009, 0.102, 6, 12);
|
|
235
|
+
scaleUVs(bar, 2 * Math.PI * 0.009, 0.102 + Math.PI * 0.009);
|
|
236
|
+
bar.translate(0, 0, 0.022);
|
|
237
|
+
const parts = [bar];
|
|
238
|
+
for (const y of [-0.02, 0.02]) {
|
|
239
|
+
parts.push(cylinder(0.005, 0.02, 16)
|
|
240
|
+
.rotateX(Math.PI / 2)
|
|
241
|
+
.translate(0, y, 0.01));
|
|
242
|
+
}
|
|
243
|
+
return merge(parts);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function boxUVs(geometry, width, height, depth) {
|
|
247
|
+
const uv = geometry.getAttribute('uv');
|
|
248
|
+
const faceSizes = [
|
|
249
|
+
[depth, height],
|
|
250
|
+
[depth, height],
|
|
251
|
+
[width, depth],
|
|
252
|
+
[width, depth],
|
|
253
|
+
[width, height],
|
|
254
|
+
[width, height],
|
|
255
|
+
];
|
|
256
|
+
const verticesPerFace = uv.count / 6;
|
|
257
|
+
for (let i = 0; i < uv.count; i++) {
|
|
258
|
+
const [u, v] = faceSizes[Math.floor(i / verticesPerFace)];
|
|
259
|
+
uv.setXY(i, uv.getX(i) * u, uv.getY(i) * v);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
export function roundedBox(w, h, d, r = Math.min(0.004, w / 4, h / 4, d / 4)) {
|
|
263
|
+
return cached('box', [w, h, d, r], (width, height, depth, radius) => {
|
|
264
|
+
const geometry = new RoundedBoxGeometry(width, height, depth, 1, radius);
|
|
265
|
+
boxUVs(geometry, width, height, depth);
|
|
266
|
+
return geometry;
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
/** A capped round bar along Y. */
|
|
270
|
+
export function tube(radius, length) {
|
|
271
|
+
return cached('tube', [2 * radius, length], (diameter, l) => cylinder(diameter / 2, l, 12));
|
|
272
|
+
}
|
|
273
|
+
export function sphere(radius) {
|
|
274
|
+
return cached('sphere', [2 * radius], (diameter) => {
|
|
275
|
+
const geometry = new SphereGeometry(diameter / 2, 12, 8);
|
|
276
|
+
scaleUVs(geometry, Math.PI * diameter, (Math.PI * diameter) / 2);
|
|
277
|
+
return geometry;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/** A wheel with its axle along Z. */
|
|
281
|
+
export function roller(radius, width) {
|
|
282
|
+
return cached('roller', [2 * radius, width], (diameter, w) => cylinder(diameter / 2, w, 20).rotateX(Math.PI / 2));
|
|
283
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ktx2-loader.d.ts","sourceRoot":"","sources":["../../src/lib/ktx2-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAMvB,MAAM,OAAO,CAAA;AAId,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAA;
|
|
1
|
+
{"version":3,"file":"ktx2-loader.d.ts","sourceRoot":"","sources":["../../src/lib/ktx2-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAMvB,MAAM,OAAO,CAAA;AAId,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAA;AA4BrE,oFAAoF;AACpF,wBAAgB,oBAAoB,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAE1E;AAED;;;;;;;;;;GAUG;AACH,cAAM,uBAAwB,SAAQ,UAAU;IAC9C,OAAO,CAAC,YAAY,CAA0B;IAErC,IAAI,CACX,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,EAC5C,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GACjC,IAAI,CA8BN;IAED,OAAO,CAAC,cAAc;IAkBtB;kEAC8D;IACxD,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAiC5F;IAED,OAAO,IAAI,IAAI,CAKd;CACF;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,yBAAgC,CAAA;AAUvD;;;;;;GAMG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAE7C;AAED,yFAAyF;AACzF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAmB5D;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,MAAM,EAAE;IAAE,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAA;CAAE,EAC/C,QAAQ,EAAE,OAAO,GAChB,OAAO,CAIT;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C"}
|
package/dist/lib/ktx2-loader.js
CHANGED
|
@@ -3,6 +3,7 @@ import { DataTexture, LinearFilter, LinearMipmapLinearFilter, RGBAFormat, Unsign
|
|
|
3
3
|
// LottieLoader/TTFLoader, whose CDN URL imports (`lottie-web`, `opentype.js`)
|
|
4
4
|
// crash bun's test runtime for every consumer of the viewer barrel.
|
|
5
5
|
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
|
|
6
|
+
import { getViewerConfig } from './viewer-config';
|
|
6
7
|
/** Base width/height of a Basis-supercompressed KTX2 payload needing transcode
|
|
7
8
|
* (vkFormat 0 = ETC1S/UASTC) whose dimensions aren't block-aligned, or null
|
|
8
9
|
* for anything safe. Little-endian u32s: vkFormat at byte 12, pixelWidth at
|
|
@@ -125,7 +126,6 @@ class AlignmentSafeKTX2Loader extends KTX2Loader {
|
|
|
125
126
|
* the scene, so catalog `.ktx2` finishes still load).
|
|
126
127
|
*/
|
|
127
128
|
export const ktx2Loader = new AlignmentSafeKTX2Loader();
|
|
128
|
-
ktx2Loader.setTranscoderPath('https://cdn.jsdelivr.net/gh/pmndrs/drei-assets@master/basis/');
|
|
129
129
|
const configuredRenderers = new WeakSet();
|
|
130
130
|
const warnedRenderers = new WeakSet();
|
|
131
131
|
let resolveKtx2Ready;
|
|
@@ -144,6 +144,7 @@ export function whenKtx2Ready() {
|
|
|
144
144
|
}
|
|
145
145
|
/** Returns true once support has been detected for this renderer (KTX2 safe to load). */
|
|
146
146
|
export function ensureKtx2Support(renderer) {
|
|
147
|
+
ktx2Loader.setTranscoderPath(getViewerConfig().decoders.basisPath);
|
|
147
148
|
const key = renderer;
|
|
148
149
|
if (!key)
|
|
149
150
|
return false;
|
package/dist/lib/layer-pass.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type Camera, Object3D, type Scene } from 'three';
|
|
2
2
|
import { type NodeFrame, PassNode } from 'three/webgpu';
|
|
3
|
+
export declare function getLayoutRevision(): number;
|
|
4
|
+
export declare function isLayoutObserved(scene: Object3D): boolean;
|
|
3
5
|
export declare class LayerPassIndex {
|
|
4
6
|
readonly source: Scene;
|
|
5
7
|
private readonly members;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer-pass.d.ts","sourceRoot":"","sources":["../../src/lib/layer-pass.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAiB,QAAQ,EAAE,KAAK,KAAK,EAAW,MAAM,OAAO,CAAA;AACjF,OAAO,EAAE,KAAK,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"layer-pass.d.ts","sourceRoot":"","sources":["../../src/lib/layer-pass.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAiB,QAAQ,EAAE,KAAK,KAAK,EAAW,MAAM,OAAO,CAAA;AACjF,OAAO,EAAE,KAAK,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAYvD,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAEzD;AAkBD,qBAAa,cAAc;IAKvB,QAAQ,CAAC,MAAM,EAAE,KAAK;IAJxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAE3D,YACW,MAAM,EAAE,KAAK,EACtB,MAAM,EAAE,MAAM,EAAE,EAUjB;IAED,QAAQ,CAAC,OAAO,EAAE,QAAQ,QAQzB;IAED,OAAO,CAAC,MAAM,CA8Cb;IAED,OAAO,CAAC,MAAM;IAOd,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE;;;MAkCvC;IAED,OAAO,SAIN;CACF;AAiBD,qBAAa,aAAc,SAAQ,QAAQ;IAMvC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAEtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,UAAU,CAAO;IAEzB,YACmB,KAAK,EAAE,cAAc,EACtC,MAAM,EAAE,MAAM,EACG,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,QAAQ,EAYpC;IAEQ,OAAO,SAGf;IAEQ,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CA+DjD;CACF"}
|
package/dist/lib/layer-pass.js
CHANGED
|
@@ -5,6 +5,19 @@
|
|
|
5
5
|
import { Object3D, Vector2 } from 'three';
|
|
6
6
|
import { PassNode } from 'three/webgpu';
|
|
7
7
|
const maskObserver = Symbol('LayerPassIndex.maskObserver');
|
|
8
|
+
/**
|
|
9
|
+
* Bumped on every observed mask change and child insertion or removal, so a per-frame walk can
|
|
10
|
+
* tell when what is drawable may have changed (scene-matrices.ts). Only meaningful for scenes
|
|
11
|
+
* with a live index ({@link isLayoutObserved}).
|
|
12
|
+
*/
|
|
13
|
+
let layoutRevision = 0;
|
|
14
|
+
const observedScenes = new WeakSet();
|
|
15
|
+
export function getLayoutRevision() {
|
|
16
|
+
return layoutRevision;
|
|
17
|
+
}
|
|
18
|
+
export function isLayoutObserved(scene) {
|
|
19
|
+
return observedScenes.has(scene);
|
|
20
|
+
}
|
|
8
21
|
function maskOwner(object) {
|
|
9
22
|
const get = Object.getOwnPropertyDescriptor(object.layers, 'mask')?.get;
|
|
10
23
|
return get?.[maskObserver];
|
|
@@ -22,6 +35,7 @@ export class LayerPassIndex {
|
|
|
22
35
|
this.members.set(1 << layer, new Set());
|
|
23
36
|
try {
|
|
24
37
|
this.attach(source);
|
|
38
|
+
observedScenes.add(source);
|
|
25
39
|
}
|
|
26
40
|
catch (error) {
|
|
27
41
|
this.dispose();
|
|
@@ -45,7 +59,11 @@ export class LayerPassIndex {
|
|
|
45
59
|
throw new Error('LayerPassIndex requires one index per scene and unshared Layers');
|
|
46
60
|
}
|
|
47
61
|
let mask = layers.mask;
|
|
62
|
+
// Passes switch the camera's layers every frame; that changes nothing in the scene.
|
|
63
|
+
const isCamera = object.isCamera === true;
|
|
48
64
|
const sync = () => {
|
|
65
|
+
if (!isCamera)
|
|
66
|
+
layoutRevision++;
|
|
49
67
|
for (const [bit, members] of this.members) {
|
|
50
68
|
if ((mask & bit) !== 0 && object !== this.source)
|
|
51
69
|
members.add(object);
|
|
@@ -88,6 +106,7 @@ export class LayerPassIndex {
|
|
|
88
106
|
this.attach(child);
|
|
89
107
|
};
|
|
90
108
|
detach(object) {
|
|
109
|
+
layoutRevision++;
|
|
91
110
|
for (const child of object.children)
|
|
92
111
|
this.detach(child);
|
|
93
112
|
this.cleanups.get(object)?.();
|
|
@@ -136,6 +155,7 @@ export class LayerPassIndex {
|
|
|
136
155
|
return { drawable, shadowLight };
|
|
137
156
|
}
|
|
138
157
|
dispose() {
|
|
158
|
+
observedScenes.delete(this.source);
|
|
139
159
|
for (const cleanup of this.cleanups.values())
|
|
140
160
|
cleanup();
|
|
141
161
|
this.cleanups.clear();
|
|
@@ -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,EAKnB,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;AAwBF,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAE9E;AAiGD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAWtF;
|
|
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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getMaterialPresetByRef, materialColorPaint, parseMaterialColor, parseMaterialRef, resolveMaterial, } from '@pascal-app/core';
|
|
2
2
|
import { addAfterEffect, invalidate } from '@react-three/fiber';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
|
-
import { float, mix,
|
|
4
|
+
import { float, mix, normalView, positionViewDirection } from 'three/tsl';
|
|
5
5
|
import { MeshLambertNodeMaterial, MeshStandardNodeMaterial } from 'three/webgpu';
|
|
6
6
|
import { resolveCdnUrl } from './asset-url';
|
|
7
7
|
import { isKtx2Url, ktx2Loader, whenKtx2Ready } from './ktx2-loader';
|
|
@@ -162,35 +162,41 @@ export function resolveTextureRepeat(repeat, scale) {
|
|
|
162
162
|
}
|
|
163
163
|
return [fallback, fallback];
|
|
164
164
|
}
|
|
165
|
+
function textureOffset(texture) {
|
|
166
|
+
return texture.offset ?? [0, 0];
|
|
167
|
+
}
|
|
168
|
+
function getPlacementKey(texture) {
|
|
169
|
+
const [repeatX, repeatY] = resolveTextureRepeat(texture.repeat, texture.scale);
|
|
170
|
+
const [offsetX, offsetY] = textureOffset(texture);
|
|
171
|
+
return `${repeatX}x${repeatY}+${offsetX},${offsetY}`;
|
|
172
|
+
}
|
|
165
173
|
export function getTextureKey(material) {
|
|
166
174
|
const texture = material?.texture;
|
|
167
175
|
if (!texture)
|
|
168
176
|
return 'none';
|
|
169
|
-
const
|
|
170
|
-
|
|
177
|
+
const normal = texture.normalMap ? `-n:${texture.normalMap}*${texture.normalScale ?? 1}` : '';
|
|
178
|
+
const bump = texture.bumpMap ? `-b:${texture.bumpMap}*${texture.bumpScale ?? 1}` : '';
|
|
179
|
+
return `${texture.url}-${getPlacementKey(texture)}${normal}${bump}`;
|
|
171
180
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return undefined;
|
|
176
|
-
const cacheKey = getTextureKey(material);
|
|
181
|
+
/** One map of a native material's texture; every map shares the albedo's repeat and offset. */
|
|
182
|
+
function getTexture(textureConfig, url, slot) {
|
|
183
|
+
const cacheKey = `${url}-${getPlacementKey(textureConfig)}-${slot}`;
|
|
177
184
|
const cached = textureCache.get(cacheKey);
|
|
178
185
|
if (cached)
|
|
179
186
|
return cached;
|
|
180
|
-
const resolvedUrl = /^(?:asset|blob|data):/.test(
|
|
181
|
-
? textureConfig.url
|
|
182
|
-
: (resolveCdnUrl(textureConfig.url) ?? textureConfig.url);
|
|
187
|
+
const resolvedUrl = /^(?:asset|blob|data):/.test(url) ? url : (resolveCdnUrl(url) ?? url);
|
|
183
188
|
const texture = loadTexture(resolvedUrl, cacheKey);
|
|
184
189
|
texture.wrapS = THREE.RepeatWrapping;
|
|
185
190
|
texture.wrapT = THREE.RepeatWrapping;
|
|
186
191
|
const [repeatX, repeatY] = resolveTextureRepeat(textureConfig.repeat, textureConfig.scale);
|
|
187
192
|
texture.repeat.set(repeatX, repeatY);
|
|
193
|
+
texture.offset.set(...textureOffset(textureConfig));
|
|
188
194
|
texture.updateMatrix();
|
|
189
|
-
texture.colorSpace = THREE.SRGBColorSpace;
|
|
195
|
+
texture.colorSpace = slot === 'map' ? THREE.SRGBColorSpace : THREE.NoColorSpace;
|
|
190
196
|
stampPascalTextureRef(texture, {
|
|
191
197
|
kind: 'project-asset',
|
|
192
198
|
src: resolvedUrl,
|
|
193
|
-
slot
|
|
199
|
+
slot,
|
|
194
200
|
});
|
|
195
201
|
textureCache.set(cacheKey, texture);
|
|
196
202
|
return texture;
|
|
@@ -272,9 +278,14 @@ async function loadPresetTexture(path, props, slot) {
|
|
|
272
278
|
// materials can be created while a capture canvas's renderer is still
|
|
273
279
|
// initializing, and failing here would cache the material permanently
|
|
274
280
|
// texture-less (white).
|
|
275
|
-
const
|
|
276
|
-
? whenKtx2Ready().then(() => ktx2Loader.loadAsync(
|
|
277
|
-
: textureLoader.loadAsync(
|
|
281
|
+
const loadFrom = (url) => isKtx2Url(url)
|
|
282
|
+
? whenKtx2Ready().then(() => ktx2Loader.loadAsync(url))
|
|
283
|
+
: textureLoader.loadAsync(url);
|
|
284
|
+
// A catalog map ships in the app's public folder before the asset CDN has it
|
|
285
|
+
// (a branch, a deploy ahead of the CDN): a CDN miss retries the app's own copy.
|
|
286
|
+
const load = resolvedPath !== path && path.startsWith('/')
|
|
287
|
+
? loadFrom(resolvedPath).catch(() => loadFrom(path))
|
|
288
|
+
: loadFrom(resolvedPath);
|
|
278
289
|
const promise = load
|
|
279
290
|
.then((texture) => {
|
|
280
291
|
applyTextureProperties(texture, props, slot);
|
|
@@ -383,7 +394,9 @@ export function materialCastsShadow(material) {
|
|
|
383
394
|
* This is what makes glass read as a surface instead of a flat blue tint.
|
|
384
395
|
*/
|
|
385
396
|
function applyGlassFresnel(material) {
|
|
386
|
-
|
|
397
|
+
// The daylight look swaps in its tuned glass for flagged materials (lib/daylight/material-hooks).
|
|
398
|
+
material.userData.isGlass = true;
|
|
399
|
+
const facing = normalView.dot(positionViewDirection).clamp(0, 1);
|
|
387
400
|
const fresnel = facing.oneMinus().pow(3);
|
|
388
401
|
material.opacityNode = mix(float(material.opacity), float(0.92), fresnel);
|
|
389
402
|
material.envMapIntensity = 1.4;
|
|
@@ -449,22 +462,36 @@ export function createMaterial(material, shading = 'rendered') {
|
|
|
449
462
|
if (materialCache.has(cacheKey)) {
|
|
450
463
|
return materialCache.get(cacheKey);
|
|
451
464
|
}
|
|
452
|
-
const
|
|
465
|
+
const texture = material?.texture?.url ? material.texture : undefined;
|
|
453
466
|
const materialParams = {
|
|
454
467
|
color: props.color,
|
|
455
468
|
opacity: props.opacity,
|
|
456
469
|
transparent: props.transparent,
|
|
457
470
|
side: sideMap[props.side],
|
|
458
471
|
};
|
|
459
|
-
if (
|
|
460
|
-
materialParams.map = map;
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
472
|
+
if (texture)
|
|
473
|
+
materialParams.map = getTexture(texture, texture.url, 'map');
|
|
474
|
+
let threeMaterial;
|
|
475
|
+
if (shading === 'solid') {
|
|
476
|
+
threeMaterial = new MeshLambertNodeMaterial(materialParams);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
const standard = new MeshStandardNodeMaterial({
|
|
464
480
|
...materialParams,
|
|
465
481
|
roughness: props.roughness,
|
|
466
482
|
metalness: props.metalness,
|
|
467
483
|
});
|
|
484
|
+
if (texture?.normalMap) {
|
|
485
|
+
standard.normalMap = getTexture(texture, texture.normalMap, 'normalMap');
|
|
486
|
+
const normalScale = texture.normalScale ?? 1;
|
|
487
|
+
standard.normalScale.set(normalScale, normalScale);
|
|
488
|
+
}
|
|
489
|
+
if (texture?.bumpMap) {
|
|
490
|
+
standard.bumpMap = getTexture(texture, texture.bumpMap, 'bumpMap');
|
|
491
|
+
standard.bumpScale = texture.bumpScale ?? 1;
|
|
492
|
+
}
|
|
493
|
+
threeMaterial = standard;
|
|
494
|
+
}
|
|
468
495
|
// Explicit source transparency keeps its opacity; the glass preset owns this styling.
|
|
469
496
|
if (glassPreset)
|
|
470
497
|
maybeApplyGlassFresnel(threeMaterial);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type MeasurementPoint } from '@pascal-app/core';
|
|
2
|
+
export declare function triangulateMeasurementPolygon(points: readonly MeasurementPoint[]): number[][];
|
|
3
|
+
export declare function measurementPolygonLabelAnchor(points: readonly MeasurementPoint[]): MeasurementPoint | null;
|
|
4
|
+
//# sourceMappingURL=measurement-label.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measurement-label.d.ts","sourceRoot":"","sources":["../../src/lib/measurement-label.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAA0C,MAAM,kBAAkB,CAAA;AA4BhG,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,EAAE,EAAE,CAE7F;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAClC,gBAAgB,GAAG,IAAI,CAiCzB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { measurementCentroid, measurementNormal } from '@pascal-app/core';
|
|
2
|
+
import { ShapeUtils, Vector2, Vector3 } from 'three';
|
|
3
|
+
function projectMeasurementPolygon(points) {
|
|
4
|
+
const normalValue = measurementNormal(points);
|
|
5
|
+
const originValue = points[0];
|
|
6
|
+
if (!(normalValue && originValue))
|
|
7
|
+
return null;
|
|
8
|
+
const normal = new Vector3(...normalValue);
|
|
9
|
+
const reference = Math.abs(normal.y) < 0.9 ? new Vector3(0, 1, 0) : new Vector3(1, 0, 0);
|
|
10
|
+
const tangent = new Vector3().crossVectors(reference, normal).normalize();
|
|
11
|
+
const bitangent = new Vector3().crossVectors(normal, tangent).normalize();
|
|
12
|
+
const origin = new Vector3(...originValue);
|
|
13
|
+
const contour = points.map((point) => {
|
|
14
|
+
const relative = new Vector3(...point).sub(origin);
|
|
15
|
+
return new Vector2(relative.dot(tangent), relative.dot(bitangent));
|
|
16
|
+
});
|
|
17
|
+
return { contour, triangles: ShapeUtils.triangulateShape(contour, []) };
|
|
18
|
+
}
|
|
19
|
+
export function triangulateMeasurementPolygon(points) {
|
|
20
|
+
return projectMeasurementPolygon(points)?.triangles ?? [];
|
|
21
|
+
}
|
|
22
|
+
export function measurementPolygonLabelAnchor(points) {
|
|
23
|
+
const projection = projectMeasurementPolygon(points);
|
|
24
|
+
if (!projection || projection.triangles.length === 0)
|
|
25
|
+
return measurementCentroid(points);
|
|
26
|
+
let largestTriangle = null;
|
|
27
|
+
let largestArea = Number.NEGATIVE_INFINITY;
|
|
28
|
+
for (const triangle of projection.triangles) {
|
|
29
|
+
const [firstIndex, secondIndex, thirdIndex] = triangle;
|
|
30
|
+
const first = firstIndex === undefined ? null : projection.contour[firstIndex];
|
|
31
|
+
const second = secondIndex === undefined ? null : projection.contour[secondIndex];
|
|
32
|
+
const third = thirdIndex === undefined ? null : projection.contour[thirdIndex];
|
|
33
|
+
if (!(first && second && third))
|
|
34
|
+
continue;
|
|
35
|
+
const area = Math.abs((second.x - first.x) * (third.y - first.y) - (second.y - first.y) * (third.x - first.x));
|
|
36
|
+
if (area > largestArea) {
|
|
37
|
+
largestArea = area;
|
|
38
|
+
largestTriangle = triangle;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!largestTriangle)
|
|
42
|
+
return measurementCentroid(points);
|
|
43
|
+
const [firstIndex, secondIndex, thirdIndex] = largestTriangle;
|
|
44
|
+
const first = firstIndex === undefined ? null : points[firstIndex];
|
|
45
|
+
const second = secondIndex === undefined ? null : points[secondIndex];
|
|
46
|
+
const third = thirdIndex === undefined ? null : points[thirdIndex];
|
|
47
|
+
if (!(first && second && third))
|
|
48
|
+
return measurementCentroid(points);
|
|
49
|
+
return [
|
|
50
|
+
(first[0] + second[0] + third[0]) / 3,
|
|
51
|
+
(first[1] + second[1] + third[1]) / 3,
|
|
52
|
+
(first[2] + second[2] + third[2]) / 3,
|
|
53
|
+
];
|
|
54
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const MEASUREMENT_ACTIVE_COLOR = "#6366f1";
|
|
2
|
+
export declare const MEASUREMENT_DANGLING_COLOR = "#dc2626";
|
|
3
|
+
export declare const MEASUREMENT_PERSISTENT_COLOR = "#111827";
|
|
4
|
+
export declare function measurementPresentationColor(dangling: boolean, active: boolean): string;
|
|
5
|
+
//# sourceMappingURL=measurement-presentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measurement-presentation.d.ts","sourceRoot":"","sources":["../../src/lib/measurement-presentation.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,YAAY,CAAA;AACjD,eAAO,MAAM,0BAA0B,YAAY,CAAA;AAEnD,eAAO,MAAM,4BAA4B,YAAY,CAAA;AAErD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAGvF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const MEASUREMENT_ACTIVE_COLOR = '#6366f1';
|
|
2
|
+
export const MEASUREMENT_DANGLING_COLOR = '#dc2626';
|
|
3
|
+
export const MEASUREMENT_PERSISTENT_COLOR = '#111827';
|
|
4
|
+
export function measurementPresentationColor(dangling, active) {
|
|
5
|
+
if (dangling)
|
|
6
|
+
return MEASUREMENT_DANGLING_COLOR;
|
|
7
|
+
return active ? MEASUREMENT_ACTIVE_COLOR : MEASUREMENT_PERSISTENT_COLOR;
|
|
8
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merged-outline-node.d.ts","sourceRoot":"","sources":["../../src/lib/merged-outline-node.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,OAAO,EAIL,QAAQ,EAKT,MAAM,OAAO,CAAA;AA2Bd,OAAO,EAML,QAAQ,EACT,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"merged-outline-node.d.ts","sourceRoot":"","sources":["../../src/lib/merged-outline-node.ts"],"names":[],"mappings":"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"}
|