@treasuryspatial/viewer-kit 0.2.44 → 0.2.50
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/autoGenerate.d.ts +1 -0
- package/dist/autoGenerate.d.ts.map +1 -1
- package/dist/autoGenerate.js +10 -2
- package/dist/camera.d.ts +1 -0
- package/dist/camera.d.ts.map +1 -1
- package/dist/camera.js +8 -1
- package/dist/engine/ViewerEngine.d.ts +20 -0
- package/dist/engine/ViewerEngine.d.ts.map +1 -1
- package/dist/engine/ViewerEngine.js +254 -63
- package/dist/engine/types.d.ts +69 -3
- package/dist/engine/types.d.ts.map +1 -1
- package/dist/exports/download.d.ts +6 -0
- package/dist/exports/download.d.ts.map +1 -1
- package/dist/exports/download.js +142 -0
- package/dist/exports/three-export.d.ts +4 -1
- package/dist/exports/three-export.d.ts.map +1 -1
- package/dist/exports/three-export.js +138 -4
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/materials/architectural.d.ts +3 -3
- package/dist/materials/architectural.d.ts.map +1 -1
- package/dist/materials/architectural.js +295 -37
- package/dist/materials/catalogue-data.d.ts +15 -0
- package/dist/materials/catalogue-data.d.ts.map +1 -1
- package/dist/materials/catalogue-data.js +16 -0
- package/dist/materials/presets.d.ts +15 -8
- package/dist/materials/presets.d.ts.map +1 -1
- package/dist/materials/presets.js +140 -39
- package/dist/materials/resolve.d.ts +42 -0
- package/dist/materials/resolve.d.ts.map +1 -1
- package/dist/materials/resolve.js +228 -13
- package/dist/materials/types.d.ts +32 -3
- package/dist/materials/types.d.ts.map +1 -1
- package/dist/presets/defaults.d.ts.map +1 -1
- package/dist/presets/defaults.js +17 -1
- package/dist/presets/sciencePresets.d.ts.map +1 -1
- package/dist/presets/sciencePresets.js +167 -50
- package/dist/scene.d.ts +28 -4
- package/dist/scene.d.ts.map +1 -1
- package/dist/scene.js +196 -31
- package/dist/sceneSemanticRegistry.d.ts +64 -0
- package/dist/sceneSemanticRegistry.d.ts.map +1 -0
- package/dist/sceneSemanticRegistry.js +199 -0
- package/dist/sky/scienceSky.d.ts.map +1 -1
- package/dist/sky/scienceSky.js +16 -0
- package/dist/systems/debugSystem.d.ts +24 -1
- package/dist/systems/debugSystem.d.ts.map +1 -1
- package/dist/systems/debugSystem.js +324 -77
- package/dist/systems/environmentSystem.d.ts +5 -4
- package/dist/systems/environmentSystem.d.ts.map +1 -1
- package/dist/systems/environmentSystem.js +138 -62
- package/dist/systems/lightingSystem.d.ts +10 -1
- package/dist/systems/lightingSystem.d.ts.map +1 -1
- package/dist/systems/lightingSystem.js +118 -17
- package/dist/systems/postfxSystem.d.ts +5 -1
- package/dist/systems/postfxSystem.d.ts.map +1 -1
- package/dist/systems/postfxSystem.js +84 -1
- package/dist/systems/rendererSystem.d.ts.map +1 -1
- package/dist/systems/rendererSystem.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/uploads/geometry3dm.d.ts.map +1 -1
- package/dist/uploads/geometry3dm.js +1 -0
- package/dist/uploads/grasshopper.d.ts.map +1 -1
- package/dist/uploads/grasshopper.js +63 -5
- package/dist/uploads/mesh.js +5 -5
- package/dist/uploads/types.d.ts +4 -0
- package/dist/uploads/types.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/scene.js
CHANGED
|
@@ -8,15 +8,164 @@ export const DEFAULT_CAMERA_RIG = {
|
|
|
8
8
|
direction: [1, 0.7, 1],
|
|
9
9
|
mode: "iso",
|
|
10
10
|
};
|
|
11
|
+
const UNIT_TO_METERS = {
|
|
12
|
+
mm: 0.001,
|
|
13
|
+
millimeter: 0.001,
|
|
14
|
+
millimeters: 0.001,
|
|
15
|
+
cm: 0.01,
|
|
16
|
+
centimeter: 0.01,
|
|
17
|
+
centimeters: 0.01,
|
|
18
|
+
m: 1,
|
|
19
|
+
meter: 1,
|
|
20
|
+
meters: 1,
|
|
21
|
+
ft: 0.3048,
|
|
22
|
+
foot: 0.3048,
|
|
23
|
+
feet: 0.3048,
|
|
24
|
+
in: 0.0254,
|
|
25
|
+
inch: 0.0254,
|
|
26
|
+
inches: 0.0254,
|
|
27
|
+
};
|
|
28
|
+
const DEFAULT_SCENE_CLIPPING = {
|
|
29
|
+
nearSafety: 1.6,
|
|
30
|
+
farSafety: 1.15,
|
|
31
|
+
minimumFar: 350,
|
|
32
|
+
};
|
|
33
|
+
const PLAN_PRESENTATION_ELEVATION = 0.012;
|
|
34
|
+
export const resolveSceneUnitScale = (units) => {
|
|
35
|
+
const normalized = units?.trim().toLowerCase();
|
|
36
|
+
if (!normalized)
|
|
37
|
+
return 1;
|
|
38
|
+
return UNIT_TO_METERS[normalized] ?? 1;
|
|
39
|
+
};
|
|
40
|
+
export const applyUnitScaleToGroup = (group, units) => {
|
|
41
|
+
if (!group)
|
|
42
|
+
return 1;
|
|
43
|
+
const nextScale = resolveSceneUnitScale(units);
|
|
44
|
+
if (!Number.isFinite(nextScale) || nextScale <= 0)
|
|
45
|
+
return 1;
|
|
46
|
+
const currentScale = typeof group.userData?.__sceneUnitScale === "number" && Number.isFinite(group.userData.__sceneUnitScale)
|
|
47
|
+
? group.userData.__sceneUnitScale
|
|
48
|
+
: 1;
|
|
49
|
+
if (Math.abs(currentScale - nextScale) < 1e-9)
|
|
50
|
+
return nextScale;
|
|
51
|
+
const ratio = nextScale / currentScale;
|
|
52
|
+
if (!Number.isFinite(ratio) || ratio <= 0)
|
|
53
|
+
return currentScale;
|
|
54
|
+
group.scale.multiplyScalar(ratio);
|
|
55
|
+
group.updateMatrixWorld(true);
|
|
56
|
+
group.userData = {
|
|
57
|
+
...(group.userData ?? {}),
|
|
58
|
+
__sceneUnitScale: nextScale,
|
|
59
|
+
__sceneUnits: units ?? null,
|
|
60
|
+
};
|
|
61
|
+
return nextScale;
|
|
62
|
+
};
|
|
63
|
+
const resolveCameraKind = (handle, requested) => requested ?? handle.getCameraState().kind ?? "perspective";
|
|
64
|
+
const computeClipRange = (distance, radius, clipping) => {
|
|
65
|
+
const resolved = { ...DEFAULT_SCENE_CLIPPING, ...(clipping ?? {}) };
|
|
66
|
+
let near = Math.max(0.01, distance - radius * resolved.nearSafety);
|
|
67
|
+
const maxNear = distance * 0.1;
|
|
68
|
+
if (Number.isFinite(maxNear) && maxNear > 0) {
|
|
69
|
+
near = Math.min(near, maxNear);
|
|
70
|
+
}
|
|
71
|
+
const dynamicMinimumFar = Math.max(1, distance * 1.5, radius * 6);
|
|
72
|
+
const minimumFar = Math.min(resolved.minimumFar, dynamicMinimumFar);
|
|
73
|
+
const far = Math.max(distance + radius * resolved.farSafety, near + Math.max(radius * 2, 1), minimumFar);
|
|
74
|
+
return { near, far };
|
|
75
|
+
};
|
|
76
|
+
const applyPlanPresentationStyling = (group) => {
|
|
77
|
+
if (!group || typeof group.traverse !== "function")
|
|
78
|
+
return;
|
|
79
|
+
const currentElevation = typeof group.userData?.__planElevation === "number" && Number.isFinite(group.userData.__planElevation)
|
|
80
|
+
? group.userData.__planElevation
|
|
81
|
+
: 0;
|
|
82
|
+
const delta = PLAN_PRESENTATION_ELEVATION - currentElevation;
|
|
83
|
+
if (Math.abs(delta) > 1e-9) {
|
|
84
|
+
group.position.y += delta;
|
|
85
|
+
group.userData = {
|
|
86
|
+
...(group.userData ?? {}),
|
|
87
|
+
__planElevation: PLAN_PRESENTATION_ELEVATION,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
group.traverse((child) => {
|
|
91
|
+
if (child instanceof THREE.Mesh) {
|
|
92
|
+
child.renderOrder = 1;
|
|
93
|
+
child.frustumCulled = false;
|
|
94
|
+
const materials = Array.isArray(child.material) ? child.material : [child.material];
|
|
95
|
+
materials.forEach((material) => {
|
|
96
|
+
if (!material)
|
|
97
|
+
return;
|
|
98
|
+
if ("color" in material && material.color) {
|
|
99
|
+
material.color.setHex(0x2f855a);
|
|
100
|
+
}
|
|
101
|
+
if ("roughness" in material) {
|
|
102
|
+
material.roughness = 1;
|
|
103
|
+
}
|
|
104
|
+
if ("metalness" in material) {
|
|
105
|
+
material.metalness = 0;
|
|
106
|
+
}
|
|
107
|
+
if ("emissive" in material && material.emissive) {
|
|
108
|
+
material.emissive.setHex(0x1f6f49);
|
|
109
|
+
}
|
|
110
|
+
if ("emissiveIntensity" in material) {
|
|
111
|
+
material.emissiveIntensity = 0.18;
|
|
112
|
+
}
|
|
113
|
+
material.transparent = true;
|
|
114
|
+
material.opacity = Math.min(material.opacity ?? 1, 0.9);
|
|
115
|
+
material.depthWrite = false;
|
|
116
|
+
material.toneMapped = false;
|
|
117
|
+
material.side = THREE.DoubleSide;
|
|
118
|
+
material.polygonOffset = true;
|
|
119
|
+
material.polygonOffsetFactor = 1.5;
|
|
120
|
+
material.polygonOffsetUnits = 2;
|
|
121
|
+
material.needsUpdate = true;
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (child instanceof THREE.Line) {
|
|
126
|
+
child.renderOrder = 200;
|
|
127
|
+
child.frustumCulled = false;
|
|
128
|
+
const material = child.material;
|
|
129
|
+
if (material instanceof THREE.LineBasicMaterial) {
|
|
130
|
+
material.color.setHex(0x1f1f1f);
|
|
131
|
+
material.transparent = true;
|
|
132
|
+
material.opacity = 1;
|
|
133
|
+
material.depthTest = false;
|
|
134
|
+
material.depthWrite = false;
|
|
135
|
+
material.toneMapped = false;
|
|
136
|
+
material.needsUpdate = true;
|
|
137
|
+
}
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (child instanceof THREE.Points) {
|
|
141
|
+
child.renderOrder = 220;
|
|
142
|
+
child.frustumCulled = false;
|
|
143
|
+
const material = child.material;
|
|
144
|
+
if (material instanceof THREE.PointsMaterial) {
|
|
145
|
+
material.color.setHex(0x1f1f1f);
|
|
146
|
+
material.size = Math.max(material.size ?? 0, 10);
|
|
147
|
+
material.sizeAttenuation = false;
|
|
148
|
+
material.depthTest = false;
|
|
149
|
+
material.depthWrite = false;
|
|
150
|
+
material.toneMapped = false;
|
|
151
|
+
material.needsUpdate = true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
};
|
|
11
156
|
export function computeSceneStats(root) {
|
|
12
157
|
let meshCount = 0;
|
|
13
158
|
let vertexCount = 0;
|
|
14
159
|
let triangleCount = 0;
|
|
160
|
+
let shadowCastingMeshCount = 0;
|
|
161
|
+
let shadowReceivingMeshCount = 0;
|
|
15
162
|
if (!root || typeof root.traverse !== "function") {
|
|
16
163
|
return {
|
|
17
164
|
meshCount,
|
|
18
165
|
vertexCount,
|
|
19
166
|
triangleCount,
|
|
167
|
+
shadowCastingMeshCount,
|
|
168
|
+
shadowReceivingMeshCount,
|
|
20
169
|
size: { x: 0, y: 0, z: 0 },
|
|
21
170
|
};
|
|
22
171
|
}
|
|
@@ -24,6 +173,10 @@ export function computeSceneStats(root) {
|
|
|
24
173
|
const mesh = child;
|
|
25
174
|
if (mesh.isMesh) {
|
|
26
175
|
meshCount += 1;
|
|
176
|
+
if (mesh.castShadow)
|
|
177
|
+
shadowCastingMeshCount += 1;
|
|
178
|
+
if (mesh.receiveShadow)
|
|
179
|
+
shadowReceivingMeshCount += 1;
|
|
27
180
|
const geometry = mesh.geometry;
|
|
28
181
|
const position = geometry.getAttribute("position");
|
|
29
182
|
if (position) {
|
|
@@ -45,12 +198,15 @@ export function computeSceneStats(root) {
|
|
|
45
198
|
meshCount,
|
|
46
199
|
vertexCount,
|
|
47
200
|
triangleCount: Math.round(triangleCount),
|
|
201
|
+
shadowCastingMeshCount,
|
|
202
|
+
shadowReceivingMeshCount,
|
|
48
203
|
size: { x: size.x, y: size.y, z: size.z },
|
|
49
204
|
};
|
|
50
205
|
}
|
|
51
|
-
export const setCameraToBounds = (handle, bounds, config) => {
|
|
206
|
+
export const setCameraToBounds = (handle, bounds, config, options) => {
|
|
52
207
|
if (bounds.isEmpty())
|
|
53
208
|
return;
|
|
209
|
+
const cameraKind = resolveCameraKind(handle, options?.kind);
|
|
54
210
|
const fov = handle.getCameraState().fov ?? 60;
|
|
55
211
|
const { position, target } = computeCameraFrame(bounds, fov, config);
|
|
56
212
|
if (![position.x, position.y, position.z, target.x, target.y, target.z].every(Number.isFinite)) {
|
|
@@ -59,46 +215,41 @@ export const setCameraToBounds = (handle, bounds, config) => {
|
|
|
59
215
|
const sphere = new THREE.Sphere();
|
|
60
216
|
bounds.getBoundingSphere(sphere);
|
|
61
217
|
const distance = position.distanceTo(target);
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
const maxNear = distance * 0.1;
|
|
66
|
-
if (Number.isFinite(maxNear) && maxNear > 0) {
|
|
67
|
-
near = Math.min(near, maxNear);
|
|
68
|
-
}
|
|
69
|
-
const minSkyFar = 350;
|
|
70
|
-
const far = Math.max(distance + sphere.radius * safetyFar, near + sphere.radius * 2, minSkyFar);
|
|
218
|
+
const { near, far } = computeClipRange(distance, sphere.radius, options?.clipping);
|
|
219
|
+
const size = bounds.getSize(new THREE.Vector3());
|
|
220
|
+
const orthographicHeight = Math.max(size.x, size.y, size.z, 0.05) * (config?.padding ?? 1.22);
|
|
71
221
|
handle.setCamera({
|
|
222
|
+
kind: cameraKind,
|
|
72
223
|
position: [position.x, position.y, position.z],
|
|
73
224
|
target: [target.x, target.y, target.z],
|
|
225
|
+
orthographicHeight: cameraKind === "orthographic" ? orthographicHeight : undefined,
|
|
74
226
|
near,
|
|
75
227
|
far,
|
|
76
228
|
});
|
|
77
229
|
};
|
|
78
|
-
export const setCameraTopDown = (handle, bounds) => {
|
|
230
|
+
export const setCameraTopDown = (handle, bounds, options) => {
|
|
79
231
|
if (bounds.isEmpty())
|
|
80
232
|
return;
|
|
233
|
+
const cameraKind = resolveCameraKind(handle, options?.kind);
|
|
81
234
|
const center = bounds.getCenter(new THREE.Vector3());
|
|
82
235
|
const size = bounds.getSize(new THREE.Vector3());
|
|
83
|
-
const span = Math.max(size.x, size.z,
|
|
236
|
+
const span = Math.max(size.x, size.z, 0.05);
|
|
84
237
|
const height = span * 1.5;
|
|
85
238
|
const position = new THREE.Vector3(center.x, center.y + height, center.z);
|
|
86
239
|
const target = center.clone();
|
|
87
240
|
const sphere = new THREE.Sphere();
|
|
88
241
|
bounds.getBoundingSphere(sphere);
|
|
89
242
|
const distance = position.distanceTo(target);
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
near = Math.min(near, maxNear);
|
|
96
|
-
}
|
|
97
|
-
const minSkyFar = 350;
|
|
98
|
-
const far = Math.max(distance + sphere.radius * safetyFar, near + sphere.radius * 2, minSkyFar);
|
|
243
|
+
const { near, far } = computeClipRange(distance, sphere.radius, options?.clipping ?? {
|
|
244
|
+
nearSafety: 1.8,
|
|
245
|
+
farSafety: 1.2,
|
|
246
|
+
});
|
|
247
|
+
const orthographicHeight = Math.max(span * 1.1, 0.05);
|
|
99
248
|
handle.setCamera({
|
|
249
|
+
kind: cameraKind,
|
|
100
250
|
position: [position.x, position.y, position.z],
|
|
101
251
|
target: [target.x, target.y, target.z],
|
|
252
|
+
orthographicHeight: cameraKind === "orthographic" ? orthographicHeight : undefined,
|
|
102
253
|
near,
|
|
103
254
|
far,
|
|
104
255
|
});
|
|
@@ -209,11 +360,17 @@ export const normalizeRenderGroup = (group, options = {}) => {
|
|
|
209
360
|
}
|
|
210
361
|
};
|
|
211
362
|
export function applyGroupToViewer(options) {
|
|
212
|
-
const { viewer, group, cameraRig, viewMode = "auto", frameConfig, materialsConfig, floorLevel, ceilingHeight, } = options;
|
|
363
|
+
const { viewer, group, cameraRig, preserveSceneAnchor = false, viewMode = "auto", frameConfig, presentation, materialsConfig, materialsPolicy, floorLevel, ceilingHeight, preserveCamera = false, } = options;
|
|
213
364
|
if (!group)
|
|
214
365
|
return null;
|
|
215
|
-
const
|
|
216
|
-
const
|
|
366
|
+
const sceneAnchor = preserveSceneAnchor && viewer ? new THREE.Vector3(...viewer.getCameraState().target) : undefined;
|
|
367
|
+
const normalization = normalizeObject3d(group, sceneAnchor ? { ...cameraRig, anchor: sceneAnchor } : cameraRig);
|
|
368
|
+
let bounds = normalization.bounds;
|
|
369
|
+
if (presentation?.kind === "plan2d") {
|
|
370
|
+
applyPlanPresentationStyling(group);
|
|
371
|
+
group.updateMatrixWorld(true);
|
|
372
|
+
bounds = new THREE.Box3().setFromObject(group);
|
|
373
|
+
}
|
|
217
374
|
const resolvedFloor = cameraRig?.floorToZero
|
|
218
375
|
? 0
|
|
219
376
|
: typeof floorLevel === "number"
|
|
@@ -225,16 +382,24 @@ export function applyGroupToViewer(options) {
|
|
|
225
382
|
const stats = computeSceneStats(group);
|
|
226
383
|
if (viewer) {
|
|
227
384
|
viewer.setSceneRoot(group);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
385
|
+
if (!preserveCamera) {
|
|
386
|
+
const shouldTopDown = viewMode === "2d" || (viewMode === "auto" && presentation?.kind === "plan2d");
|
|
387
|
+
if (shouldTopDown) {
|
|
388
|
+
setCameraTopDown(viewer, bounds, {
|
|
389
|
+
kind: presentation?.cameraKind,
|
|
390
|
+
clipping: presentation?.clipping,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
setCameraToBounds(viewer, bounds, frameConfig, {
|
|
395
|
+
kind: presentation?.cameraKind,
|
|
396
|
+
clipping: presentation?.clipping,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
234
399
|
}
|
|
235
400
|
}
|
|
236
401
|
if (materialsConfig) {
|
|
237
|
-
applyMaterialsToGroup(group, materialsConfig, resolvedFloor, resolvedHeight);
|
|
402
|
+
applyMaterialsToGroup(group, materialsConfig, resolvedFloor, resolvedHeight, materialsPolicy);
|
|
238
403
|
viewer?.invalidate?.();
|
|
239
404
|
}
|
|
240
405
|
return { bounds, stats, normalization, resolvedFloor, resolvedHeight };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
export type SceneSemanticBounds = {
|
|
3
|
+
min: [number, number, number];
|
|
4
|
+
max: [number, number, number];
|
|
5
|
+
size: {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
z: number;
|
|
9
|
+
};
|
|
10
|
+
center: [number, number, number];
|
|
11
|
+
};
|
|
12
|
+
export type SceneSemanticObject = {
|
|
13
|
+
registryId: string;
|
|
14
|
+
threeUuid: string;
|
|
15
|
+
object: THREE.Mesh;
|
|
16
|
+
objectName?: string;
|
|
17
|
+
objectId?: string;
|
|
18
|
+
meshId?: string;
|
|
19
|
+
sourceId?: string;
|
|
20
|
+
buildResultId?: string;
|
|
21
|
+
surfaceDomainId?: string;
|
|
22
|
+
surfaceType?: string;
|
|
23
|
+
surfaceClass?: string;
|
|
24
|
+
spanId?: string;
|
|
25
|
+
cellId?: string;
|
|
26
|
+
verticalBandId?: string;
|
|
27
|
+
floorBandId?: string;
|
|
28
|
+
roofBandId?: string;
|
|
29
|
+
frameId?: string;
|
|
30
|
+
faceId?: string;
|
|
31
|
+
role?: string;
|
|
32
|
+
layer?: string;
|
|
33
|
+
className?: string;
|
|
34
|
+
subclassName?: string;
|
|
35
|
+
surface?: string;
|
|
36
|
+
visible: boolean;
|
|
37
|
+
castShadow: boolean;
|
|
38
|
+
receiveShadow: boolean;
|
|
39
|
+
vertexCount: number;
|
|
40
|
+
triangleCount: number;
|
|
41
|
+
bounds: SceneSemanticBounds;
|
|
42
|
+
data: Record<string, string>;
|
|
43
|
+
userData: Record<string, string | number | boolean | null>;
|
|
44
|
+
};
|
|
45
|
+
export type SceneSemanticRegistry = {
|
|
46
|
+
objects: SceneSemanticObject[];
|
|
47
|
+
byRegistryId: Record<string, SceneSemanticObject>;
|
|
48
|
+
byThreeUuid: Record<string, SceneSemanticObject>;
|
|
49
|
+
bySurfaceDomainId: Record<string, string[]>;
|
|
50
|
+
byCellId: Record<string, string[]>;
|
|
51
|
+
bySurfaceClass: Record<string, string[]>;
|
|
52
|
+
dataKeys: string[];
|
|
53
|
+
counts: {
|
|
54
|
+
objectCount: number;
|
|
55
|
+
meshCount: number;
|
|
56
|
+
surfaceDomainCount: number;
|
|
57
|
+
cellCount: number;
|
|
58
|
+
surfaceClassCount: number;
|
|
59
|
+
dataKeyCount: number;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
export declare function buildSceneSemanticRegistry(root?: THREE.Object3D | null): SceneSemanticRegistry;
|
|
63
|
+
export declare function findSceneSemanticObjectByThreeUuid(registry: SceneSemanticRegistry | null | undefined, threeUuid: string | null | undefined): SceneSemanticObject | null;
|
|
64
|
+
//# sourceMappingURL=sceneSemanticRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneSemanticRegistry.d.ts","sourceRoot":"","sources":["../src/sceneSemanticRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
const pickString = (userData, ...keys) => {
|
|
3
|
+
for (const key of keys) {
|
|
4
|
+
const value = userData[key];
|
|
5
|
+
if (value === null || value === undefined)
|
|
6
|
+
continue;
|
|
7
|
+
const normalized = String(value).trim();
|
|
8
|
+
if (normalized.length > 0)
|
|
9
|
+
return normalized;
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
};
|
|
13
|
+
const toSerializableUserData = (userData) => {
|
|
14
|
+
const output = {};
|
|
15
|
+
for (const [key, value] of Object.entries(userData)) {
|
|
16
|
+
if (key.startsWith("__"))
|
|
17
|
+
continue;
|
|
18
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
19
|
+
output[key] = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return output;
|
|
23
|
+
};
|
|
24
|
+
const collectDataValues = (userData) => {
|
|
25
|
+
const data = {};
|
|
26
|
+
const nestedData = userData.data;
|
|
27
|
+
if (nestedData && typeof nestedData === "object" && !Array.isArray(nestedData)) {
|
|
28
|
+
for (const [key, value] of Object.entries(nestedData)) {
|
|
29
|
+
if (value === null || value === undefined)
|
|
30
|
+
continue;
|
|
31
|
+
const normalized = String(value).trim();
|
|
32
|
+
if (normalized.length > 0) {
|
|
33
|
+
data[key] = normalized;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
for (const [key, value] of Object.entries(userData)) {
|
|
38
|
+
if (!key.startsWith("data:") || value === null || value === undefined)
|
|
39
|
+
continue;
|
|
40
|
+
const normalized = String(value).trim();
|
|
41
|
+
if (normalized.length > 0) {
|
|
42
|
+
data[key.slice("data:".length)] = normalized;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return data;
|
|
46
|
+
};
|
|
47
|
+
const computeTriangleCount = (geometry) => {
|
|
48
|
+
if (!geometry)
|
|
49
|
+
return 0;
|
|
50
|
+
const index = geometry.getIndex();
|
|
51
|
+
if (index)
|
|
52
|
+
return Math.floor(index.count / 3);
|
|
53
|
+
const position = geometry.getAttribute("position");
|
|
54
|
+
return position ? Math.floor(position.count / 3) : 0;
|
|
55
|
+
};
|
|
56
|
+
const computeVertexCount = (geometry) => {
|
|
57
|
+
if (!geometry)
|
|
58
|
+
return 0;
|
|
59
|
+
const position = geometry.getAttribute("position");
|
|
60
|
+
return position?.count ?? 0;
|
|
61
|
+
};
|
|
62
|
+
const computeBounds = (object) => {
|
|
63
|
+
const box = new THREE.Box3().setFromObject(object);
|
|
64
|
+
if (box.isEmpty()) {
|
|
65
|
+
return {
|
|
66
|
+
min: [0, 0, 0],
|
|
67
|
+
max: [0, 0, 0],
|
|
68
|
+
size: { x: 0, y: 0, z: 0 },
|
|
69
|
+
center: [0, 0, 0],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const size = new THREE.Vector3();
|
|
73
|
+
const center = new THREE.Vector3();
|
|
74
|
+
box.getSize(size);
|
|
75
|
+
box.getCenter(center);
|
|
76
|
+
return {
|
|
77
|
+
min: [box.min.x, box.min.y, box.min.z],
|
|
78
|
+
max: [box.max.x, box.max.y, box.max.z],
|
|
79
|
+
size: { x: size.x, y: size.y, z: size.z },
|
|
80
|
+
center: [center.x, center.y, center.z],
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
const appendIndex = (target, key, registryId) => {
|
|
84
|
+
if (!key)
|
|
85
|
+
return;
|
|
86
|
+
if (!target[key]) {
|
|
87
|
+
target[key] = [];
|
|
88
|
+
}
|
|
89
|
+
target[key].push(registryId);
|
|
90
|
+
};
|
|
91
|
+
const makeUniqueRegistryId = (baseId, existing) => {
|
|
92
|
+
if (!existing[baseId])
|
|
93
|
+
return baseId;
|
|
94
|
+
let index = 2;
|
|
95
|
+
while (existing[`${baseId}#${index}`]) {
|
|
96
|
+
index += 1;
|
|
97
|
+
}
|
|
98
|
+
return `${baseId}#${index}`;
|
|
99
|
+
};
|
|
100
|
+
const buildSemanticObject = (mesh, existing) => {
|
|
101
|
+
const userData = (mesh.userData ?? {});
|
|
102
|
+
const meshId = pickString(userData, "meshId", "b2:meshId");
|
|
103
|
+
const objectId = pickString(userData, "objectId", "id", "b2:id", "packet");
|
|
104
|
+
const cellId = pickString(userData, "cellId", "b2:cellId");
|
|
105
|
+
const surfaceDomainId = pickString(userData, "surfaceDomainId", "b2:surfaceDomainId");
|
|
106
|
+
const baseId = meshId ?? objectId ?? cellId ?? surfaceDomainId ?? mesh.uuid;
|
|
107
|
+
const registryId = makeUniqueRegistryId(baseId, existing);
|
|
108
|
+
const data = collectDataValues(userData);
|
|
109
|
+
const surfaceClass = pickString(userData, "surfaceClass", "b2:surfaceClass", "surface");
|
|
110
|
+
return {
|
|
111
|
+
registryId,
|
|
112
|
+
threeUuid: mesh.uuid,
|
|
113
|
+
object: mesh,
|
|
114
|
+
objectName: mesh.name || undefined,
|
|
115
|
+
objectId,
|
|
116
|
+
meshId,
|
|
117
|
+
sourceId: pickString(userData, "sourceId", "b2:sourceId"),
|
|
118
|
+
buildResultId: pickString(userData, "buildResultId", "b2:buildResultId"),
|
|
119
|
+
surfaceDomainId,
|
|
120
|
+
surfaceType: pickString(userData, "surfaceType", "b2:surfaceType"),
|
|
121
|
+
surfaceClass,
|
|
122
|
+
spanId: pickString(userData, "spanId", "b2:spanId"),
|
|
123
|
+
cellId,
|
|
124
|
+
verticalBandId: pickString(userData, "verticalBandId", "b2:verticalBandId"),
|
|
125
|
+
floorBandId: pickString(userData, "floorBandId", "b2:floorBandId"),
|
|
126
|
+
roofBandId: pickString(userData, "roofBandId", "b2:roofBandId"),
|
|
127
|
+
frameId: pickString(userData, "frameId", "b2:frameId"),
|
|
128
|
+
faceId: pickString(userData, "faceId", "b2:faceId"),
|
|
129
|
+
role: pickString(userData, "role", "b2:role"),
|
|
130
|
+
layer: pickString(userData, "layer", "b2:layer"),
|
|
131
|
+
className: pickString(userData, "class", "className"),
|
|
132
|
+
subclassName: pickString(userData, "subclass", "subclassName"),
|
|
133
|
+
surface: pickString(userData, "surface"),
|
|
134
|
+
visible: mesh.visible,
|
|
135
|
+
castShadow: mesh.castShadow,
|
|
136
|
+
receiveShadow: mesh.receiveShadow,
|
|
137
|
+
vertexCount: computeVertexCount(mesh.geometry),
|
|
138
|
+
triangleCount: computeTriangleCount(mesh.geometry),
|
|
139
|
+
bounds: computeBounds(mesh),
|
|
140
|
+
data,
|
|
141
|
+
userData: toSerializableUserData(userData),
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
export function buildSceneSemanticRegistry(root) {
|
|
145
|
+
const byRegistryId = {};
|
|
146
|
+
const byThreeUuid = {};
|
|
147
|
+
const bySurfaceDomainId = {};
|
|
148
|
+
const byCellId = {};
|
|
149
|
+
const bySurfaceClass = {};
|
|
150
|
+
const dataKeys = new Set();
|
|
151
|
+
const surfaceDomainIds = new Set();
|
|
152
|
+
const cellIds = new Set();
|
|
153
|
+
const surfaceClasses = new Set();
|
|
154
|
+
if (root && typeof root.traverse === "function") {
|
|
155
|
+
root.traverse((child) => {
|
|
156
|
+
const mesh = child;
|
|
157
|
+
if (!mesh.isMesh || !mesh.geometry)
|
|
158
|
+
return;
|
|
159
|
+
if (mesh.userData?.excludeFromSemanticRegistry === true)
|
|
160
|
+
return;
|
|
161
|
+
const entry = buildSemanticObject(mesh, byRegistryId);
|
|
162
|
+
byRegistryId[entry.registryId] = entry;
|
|
163
|
+
byThreeUuid[entry.threeUuid] = entry;
|
|
164
|
+
appendIndex(bySurfaceDomainId, entry.surfaceDomainId, entry.registryId);
|
|
165
|
+
appendIndex(byCellId, entry.cellId, entry.registryId);
|
|
166
|
+
appendIndex(bySurfaceClass, entry.surfaceClass, entry.registryId);
|
|
167
|
+
if (entry.surfaceDomainId)
|
|
168
|
+
surfaceDomainIds.add(entry.surfaceDomainId);
|
|
169
|
+
if (entry.cellId)
|
|
170
|
+
cellIds.add(entry.cellId);
|
|
171
|
+
if (entry.surfaceClass)
|
|
172
|
+
surfaceClasses.add(entry.surfaceClass);
|
|
173
|
+
Object.keys(entry.data).forEach((key) => dataKeys.add(key));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
const objects = Object.values(byRegistryId);
|
|
177
|
+
return {
|
|
178
|
+
objects,
|
|
179
|
+
byRegistryId,
|
|
180
|
+
byThreeUuid,
|
|
181
|
+
bySurfaceDomainId,
|
|
182
|
+
byCellId,
|
|
183
|
+
bySurfaceClass,
|
|
184
|
+
dataKeys: Array.from(dataKeys).sort((a, b) => a.localeCompare(b)),
|
|
185
|
+
counts: {
|
|
186
|
+
objectCount: objects.length,
|
|
187
|
+
meshCount: objects.length,
|
|
188
|
+
surfaceDomainCount: surfaceDomainIds.size,
|
|
189
|
+
cellCount: cellIds.size,
|
|
190
|
+
surfaceClassCount: surfaceClasses.size,
|
|
191
|
+
dataKeyCount: dataKeys.size,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
export function findSceneSemanticObjectByThreeUuid(registry, threeUuid) {
|
|
196
|
+
if (!registry || !threeUuid)
|
|
197
|
+
return null;
|
|
198
|
+
return registry.byThreeUuid[threeUuid] ?? null;
|
|
199
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scienceSky.d.ts","sourceRoot":"","sources":["../../src/sky/scienceSky.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,sBAAsB,CAAC,KAAK,CAAC,CAAC;CACrC,CAAC;
|
|
1
|
+
{"version":3,"file":"scienceSky.d.ts","sourceRoot":"","sources":["../../src/sky/scienceSky.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,sBAAsB,CAAC,KAAK,CAAC,CAAC;CACrC,CAAC;AAmGF,wBAAgB,qBAAqB,IAAI,gBAAgB,EAAE,CAE1D;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE5E"}
|
package/dist/sky/scienceSky.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const HDR_BASE = "https://assets.treasury.space/science/hdr/shared";
|
|
2
|
+
const SKY_IMAGE_BASE = "https://assets.treasury.space/science/sky/shared";
|
|
2
3
|
const SCIENCE_SKY_OPTIONS = [
|
|
3
4
|
{
|
|
4
5
|
id: "preset",
|
|
@@ -31,6 +32,21 @@ const SCIENCE_SKY_OPTIONS = [
|
|
|
31
32
|
hdr: { src: `${HDR_BASE}/canary_wharf_4k.hdr`, exposure: 1.1 },
|
|
32
33
|
},
|
|
33
34
|
},
|
|
35
|
+
{
|
|
36
|
+
id: "spacex-interface",
|
|
37
|
+
label: "SpaceX Interface",
|
|
38
|
+
description: "Authored 2:1 LDR panorama wrap from the launch photo. Background only; not HDR lighting.",
|
|
39
|
+
sky: {
|
|
40
|
+
mode: "image",
|
|
41
|
+
image: {
|
|
42
|
+
src: `${SKY_IMAGE_BASE}/space_x_panorama_wrap_4096x2048_v2.jpg`,
|
|
43
|
+
projection: "equirectangular",
|
|
44
|
+
rotationY: 1.1,
|
|
45
|
+
showBackground: true,
|
|
46
|
+
showLighting: false,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
34
50
|
{
|
|
35
51
|
id: "kloofendal",
|
|
36
52
|
label: "Kloofendal Sky",
|
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
import * as THREE from "three";
|
|
2
2
|
import type { RenderPresetDefinition } from "../engine/types";
|
|
3
|
+
export declare const AO_DEPTH_PROXY_USER_DATA_KEY = "treasuryAoDepthProxy";
|
|
4
|
+
export type DebugSystemState = {
|
|
5
|
+
groundEnabled: boolean;
|
|
6
|
+
gridEnabled: boolean;
|
|
7
|
+
groundY: number | null;
|
|
8
|
+
gridY: number | null;
|
|
9
|
+
gridSize: number | null;
|
|
10
|
+
gridDivisions: number | null;
|
|
11
|
+
gridStep: number | null;
|
|
12
|
+
gridMajorEvery: number | null;
|
|
13
|
+
gridSuperMajorEvery: number | null;
|
|
14
|
+
groundMode: "finite" | "infinite" | null;
|
|
15
|
+
gridMode: "finite" | "infinite" | null;
|
|
16
|
+
};
|
|
3
17
|
export declare class DebugSystem {
|
|
4
18
|
private scene;
|
|
5
19
|
private objects;
|
|
20
|
+
private ground;
|
|
21
|
+
private groundAoProxy;
|
|
22
|
+
private grid;
|
|
23
|
+
private groundInfinite;
|
|
24
|
+
private gridInfinite;
|
|
25
|
+
private gridDivisionSize;
|
|
26
|
+
private state;
|
|
6
27
|
constructor(scene: THREE.Scene);
|
|
7
|
-
|
|
28
|
+
update(anchor?: THREE.Vector3 | null): void;
|
|
29
|
+
getState(): DebugSystemState;
|
|
30
|
+
apply(preset: RenderPresetDefinition, bounds?: THREE.Box3 | null, root?: THREE.Object3D | null): void;
|
|
8
31
|
dispose(): void;
|
|
9
32
|
private add;
|
|
10
33
|
private clear;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debugSystem.d.ts","sourceRoot":"","sources":["../../src/systems/debugSystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAqB,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"debugSystem.d.ts","sourceRoot":"","sources":["../../src/systems/debugSystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAqB,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAqDjF,eAAO,MAAM,4BAA4B,yBAAyB,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,UAAU,EAAE,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;IACzC,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;CACxC,CAAC;AAoRF,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,aAAa,CAA2B;IAChD,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,KAAK,CAYX;gBAEU,KAAK,EAAE,KAAK,CAAC,KAAK;IAI9B,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI;IAiB3C,QAAQ,IAAI,gBAAgB;IAI5B,KAAK,CAAC,MAAM,EAAE,sBAAsB,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI;IA8KrG,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,GAAG;IAKX,OAAO,CAAC,KAAK;CAwDd"}
|