@treasuryspatial/viewer-kit 0.2.31

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.
Files changed (80) hide show
  1. package/README.md +5 -0
  2. package/dist/camera.d.ts +28 -0
  3. package/dist/camera.d.ts.map +1 -0
  4. package/dist/camera.js +63 -0
  5. package/dist/engine/ViewerEngine.d.ts +41 -0
  6. package/dist/engine/ViewerEngine.d.ts.map +1 -0
  7. package/dist/engine/ViewerEngine.js +344 -0
  8. package/dist/engine/createViewer.d.ts +3 -0
  9. package/dist/engine/createViewer.d.ts.map +1 -0
  10. package/dist/engine/createViewer.js +7 -0
  11. package/dist/engine/types.d.ts +284 -0
  12. package/dist/engine/types.d.ts.map +1 -0
  13. package/dist/engine/types.js +1 -0
  14. package/dist/exports/download.d.ts +2 -0
  15. package/dist/exports/download.d.ts.map +1 -0
  16. package/dist/exports/download.js +10 -0
  17. package/dist/exports/three-export.d.ts +4 -0
  18. package/dist/exports/three-export.d.ts.map +1 -0
  19. package/dist/exports/three-export.js +25 -0
  20. package/dist/index.d.ts +18 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +12 -0
  23. package/dist/materials/architectural.d.ts +7 -0
  24. package/dist/materials/architectural.d.ts.map +1 -0
  25. package/dist/materials/architectural.js +187 -0
  26. package/dist/materials/catalogue-data.d.ts +149 -0
  27. package/dist/materials/catalogue-data.d.ts.map +1 -0
  28. package/dist/materials/catalogue-data.js +158 -0
  29. package/dist/materials/catalogue.d.ts +5 -0
  30. package/dist/materials/catalogue.d.ts.map +1 -0
  31. package/dist/materials/catalogue.js +23 -0
  32. package/dist/materials/presets.d.ts +21 -0
  33. package/dist/materials/presets.d.ts.map +1 -0
  34. package/dist/materials/presets.js +217 -0
  35. package/dist/materials/renderMetadata.d.ts +15 -0
  36. package/dist/materials/renderMetadata.d.ts.map +1 -0
  37. package/dist/materials/renderMetadata.js +64 -0
  38. package/dist/materials/types.d.ts +50 -0
  39. package/dist/materials/types.d.ts.map +1 -0
  40. package/dist/materials/types.js +1 -0
  41. package/dist/presets/defaults.d.ts +4 -0
  42. package/dist/presets/defaults.d.ts.map +1 -0
  43. package/dist/presets/defaults.js +45 -0
  44. package/dist/presets/sciencePresets.d.ts +7 -0
  45. package/dist/presets/sciencePresets.d.ts.map +1 -0
  46. package/dist/presets/sciencePresets.js +478 -0
  47. package/dist/sky/scienceSky.d.ts +10 -0
  48. package/dist/sky/scienceSky.d.ts.map +1 -0
  49. package/dist/sky/scienceSky.js +85 -0
  50. package/dist/systems/debugSystem.d.ts +12 -0
  51. package/dist/systems/debugSystem.d.ts.map +1 -0
  52. package/dist/systems/debugSystem.js +283 -0
  53. package/dist/systems/environmentSystem.d.ts +31 -0
  54. package/dist/systems/environmentSystem.d.ts.map +1 -0
  55. package/dist/systems/environmentSystem.js +277 -0
  56. package/dist/systems/lightingSystem.d.ts +15 -0
  57. package/dist/systems/lightingSystem.d.ts.map +1 -0
  58. package/dist/systems/lightingSystem.js +100 -0
  59. package/dist/systems/postfxSystem.d.ts +31 -0
  60. package/dist/systems/postfxSystem.d.ts.map +1 -0
  61. package/dist/systems/postfxSystem.js +220 -0
  62. package/dist/systems/rendererSystem.d.ts +4 -0
  63. package/dist/systems/rendererSystem.d.ts.map +1 -0
  64. package/dist/systems/rendererSystem.js +42 -0
  65. package/dist/uploads/grasshopper.d.ts +13 -0
  66. package/dist/uploads/grasshopper.d.ts.map +1 -0
  67. package/dist/uploads/grasshopper.js +182 -0
  68. package/dist/uploads/index.d.ts +8 -0
  69. package/dist/uploads/index.d.ts.map +1 -0
  70. package/dist/uploads/index.js +29 -0
  71. package/dist/uploads/mesh.d.ts +8 -0
  72. package/dist/uploads/mesh.d.ts.map +1 -0
  73. package/dist/uploads/mesh.js +109 -0
  74. package/dist/uploads/rhino3dm.d.ts +7 -0
  75. package/dist/uploads/rhino3dm.d.ts.map +1 -0
  76. package/dist/uploads/rhino3dm.js +33 -0
  77. package/dist/uploads/types.d.ts +68 -0
  78. package/dist/uploads/types.d.ts.map +1 -0
  79. package/dist/uploads/types.js +1 -0
  80. package/package.json +38 -0
@@ -0,0 +1,284 @@
1
+ export type AssetKind = "hdr" | "texture" | "cubeface";
2
+ export type AssetResolverResult = {
3
+ url: string;
4
+ headers?: Record<string, string>;
5
+ };
6
+ export type AssetResolver = (src: string, kind: AssetKind) => Promise<AssetResolverResult>;
7
+ export type ToneMappingMode = "neutral" | "aces" | "linear";
8
+ export type RendererConfig = {
9
+ toneMapping?: ToneMappingMode;
10
+ toneMappingExposure?: number;
11
+ outputColorSpace?: "srgb" | "linear";
12
+ maxPixelRatio?: number;
13
+ antialias?: boolean;
14
+ alpha?: boolean;
15
+ preserveDrawingBuffer?: boolean;
16
+ shadowMap?: {
17
+ enabled?: boolean;
18
+ type?: "pcfsoft" | "pcf" | "basic";
19
+ };
20
+ };
21
+ export type SkyGradientConfig = {
22
+ topColor: string;
23
+ horizonColor: string;
24
+ sunPosition: [number, number, number];
25
+ sunIntensity: number;
26
+ sunSize: number;
27
+ };
28
+ export type SkyHdrConfig = {
29
+ src: string;
30
+ exposure?: number;
31
+ rotationY?: number;
32
+ rotation?: {
33
+ yaw?: number;
34
+ pitch?: number;
35
+ roll?: number;
36
+ };
37
+ showBackground?: boolean;
38
+ showLighting?: boolean;
39
+ pmremResolution?: 256 | 512 | 1024;
40
+ usePmrem?: boolean;
41
+ };
42
+ export type SkyCubeConfig = {
43
+ px: string;
44
+ nx: string;
45
+ py: string;
46
+ ny: string;
47
+ pz: string;
48
+ nz: string;
49
+ exposure?: number;
50
+ rotationY?: number;
51
+ rotation?: {
52
+ yaw?: number;
53
+ pitch?: number;
54
+ roll?: number;
55
+ };
56
+ showBackground?: boolean;
57
+ showLighting?: boolean;
58
+ pmremResolution?: 256 | 512 | 1024;
59
+ usePmrem?: boolean;
60
+ };
61
+ export type SkyDefinition = {
62
+ mode: "none";
63
+ } | {
64
+ mode: "gradient";
65
+ gradient: SkyGradientConfig;
66
+ } | {
67
+ mode: "hdr";
68
+ hdr: SkyHdrConfig;
69
+ } | {
70
+ mode: "cube";
71
+ cube: SkyCubeConfig;
72
+ };
73
+ export type LightingRigConfig = {
74
+ rig?: "studio" | "neutral" | "gallery" | "none";
75
+ ambient?: {
76
+ color: string;
77
+ intensity: number;
78
+ };
79
+ hemisphere?: {
80
+ skyColor: string;
81
+ groundColor: string;
82
+ intensity: number;
83
+ };
84
+ key?: {
85
+ color: string;
86
+ intensity: number;
87
+ position: [number, number, number];
88
+ castShadow?: boolean;
89
+ };
90
+ fill?: {
91
+ color: string;
92
+ intensity: number;
93
+ position: [number, number, number];
94
+ };
95
+ shadow?: {
96
+ cameraSize?: number;
97
+ near?: number;
98
+ far?: number;
99
+ bias?: number;
100
+ radius?: number;
101
+ mapSize?: number;
102
+ };
103
+ };
104
+ export type PostFxConfig = {
105
+ ao?: {
106
+ enabled: boolean;
107
+ intensity?: number;
108
+ radius?: number;
109
+ distanceFalloff?: number;
110
+ halfRes?: boolean;
111
+ quality?: "low" | "medium" | "high";
112
+ color?: string;
113
+ };
114
+ bloom?: {
115
+ enabled: boolean;
116
+ intensity?: number;
117
+ radius?: number;
118
+ threshold?: number;
119
+ smoothing?: number;
120
+ };
121
+ vignette?: {
122
+ enabled: boolean;
123
+ offset?: number;
124
+ darkness?: number;
125
+ };
126
+ };
127
+ export type SceneExtrasConfig = {
128
+ grid?: boolean;
129
+ ground?: boolean;
130
+ axes?: boolean;
131
+ origin?: boolean;
132
+ lightTarget?: [number, number, number];
133
+ groundColor?: number;
134
+ groundRoughness?: number;
135
+ groundMetalness?: number;
136
+ groundSize?: number;
137
+ groundOffset?: number;
138
+ groundAutoScale?: number;
139
+ groundAutoScaleHdr?: number;
140
+ gridColor?: number;
141
+ gridColorSecondary?: number;
142
+ gridOpacity?: number;
143
+ gridDivisions?: number;
144
+ gridSize?: number;
145
+ gridAutoScale?: number;
146
+ gridAutoScaleHdr?: number;
147
+ gridHeightOffset?: number;
148
+ originHighlight?: boolean;
149
+ originLineColor?: number;
150
+ originLineLength?: number;
151
+ originLineThickness?: number;
152
+ axisLabelScale?: number;
153
+ axesLabels?: {
154
+ lowerCase?: boolean;
155
+ upperCase?: boolean;
156
+ offset?: number;
157
+ secondaryOffset?: number;
158
+ };
159
+ originColor?: number;
160
+ originSize?: number;
161
+ axesPosition?: [number, number, number];
162
+ };
163
+ export type RenderPresetDefinition = {
164
+ id: string;
165
+ label?: string;
166
+ materialsPresetId?: string;
167
+ renderer?: RendererConfig;
168
+ sky?: SkyDefinition;
169
+ lighting?: LightingRigConfig;
170
+ interiorLights?: Array<{
171
+ position: [number, number, number];
172
+ intensity: number;
173
+ color?: string;
174
+ distance?: number;
175
+ }>;
176
+ postfx?: PostFxConfig;
177
+ sceneExtras?: SceneExtrasConfig;
178
+ };
179
+ export type PresetCatalog = Record<string, RenderPresetDefinition>;
180
+ export type ViewerSnapshot = {
181
+ capturedAt: string;
182
+ presetId: string;
183
+ renderer: {
184
+ toneMapping: string;
185
+ toneMappingExposure: number;
186
+ outputColorSpace: string;
187
+ };
188
+ environment: {
189
+ mode: "none" | "gradient" | "hdr" | "cube";
190
+ backgroundEnabled: boolean;
191
+ lightingEnabled: boolean;
192
+ };
193
+ postfx: {
194
+ aoEnabled: boolean;
195
+ bloomEnabled: boolean;
196
+ vignetteEnabled: boolean;
197
+ };
198
+ };
199
+ export type ViewerDebugInfo = {
200
+ presetId: string;
201
+ camera: CameraState;
202
+ canvas: {
203
+ width: number;
204
+ height: number;
205
+ clientWidth: number;
206
+ clientHeight: number;
207
+ };
208
+ renderer: {
209
+ toneMapping: string;
210
+ toneMappingExposure: number;
211
+ outputColorSpace: string;
212
+ pixelRatio: number;
213
+ clearColor: string;
214
+ clearAlpha: number;
215
+ };
216
+ renderInfo: {
217
+ calls: number;
218
+ triangles: number;
219
+ lines: number;
220
+ points: number;
221
+ };
222
+ scene: {
223
+ children: number;
224
+ rootChildren: number;
225
+ lights: number;
226
+ };
227
+ environment: {
228
+ mode: "none" | "gradient" | "hdr" | "cube";
229
+ backgroundEnabled: boolean;
230
+ lightingEnabled: boolean;
231
+ };
232
+ postfx: {
233
+ aoEnabled: boolean;
234
+ bloomEnabled: boolean;
235
+ vignetteEnabled: boolean;
236
+ };
237
+ };
238
+ export type CameraState = {
239
+ position: [number, number, number];
240
+ target: [number, number, number];
241
+ fov: number;
242
+ near?: number;
243
+ far?: number;
244
+ };
245
+ export type ViewerCreateOptions = {
246
+ container: HTMLElement;
247
+ presetId?: string;
248
+ presets?: PresetCatalog;
249
+ assetResolver?: AssetResolver;
250
+ renderer?: {
251
+ antialias?: boolean;
252
+ alpha?: boolean;
253
+ preserveDrawingBuffer?: boolean;
254
+ };
255
+ camera?: {
256
+ fov?: number;
257
+ near?: number;
258
+ far?: number;
259
+ position?: [number, number, number];
260
+ target?: [number, number, number];
261
+ };
262
+ usePostprocessing?: boolean;
263
+ hooks?: {
264
+ onReady?: (handle: ViewerHandle) => void;
265
+ onError?: (error: unknown) => void;
266
+ };
267
+ };
268
+ export type ViewerHandle = {
269
+ start(): void;
270
+ stop(): void;
271
+ resize(): void;
272
+ invalidate(): void;
273
+ dispose(): void;
274
+ setPreset(presetId: string): void;
275
+ setRuntimePreset(preset: RenderPresetDefinition): void;
276
+ setSceneRoot(root: unknown): void;
277
+ setCamera(state: Partial<CameraState>): void;
278
+ getCameraState(): CameraState;
279
+ capturePng(): Promise<Blob>;
280
+ getSnapshot(): ViewerSnapshot;
281
+ getDebugInfo?: () => ViewerDebugInfo;
282
+ getCanvas?: () => HTMLCanvasElement;
283
+ };
284
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function downloadBlob(blob: Blob, filename: string): void;
2
+ //# sourceMappingURL=download.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/exports/download.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,QASxD"}
@@ -0,0 +1,10 @@
1
+ export function downloadBlob(blob, filename) {
2
+ const url = URL.createObjectURL(blob);
3
+ const link = document.createElement("a");
4
+ link.href = url;
5
+ link.download = filename;
6
+ document.body.appendChild(link);
7
+ link.click();
8
+ link.remove();
9
+ setTimeout(() => URL.revokeObjectURL(url), 0);
10
+ }
@@ -0,0 +1,4 @@
1
+ import * as THREE from "three";
2
+ export type ExportFormat = "glb" | "obj";
3
+ export declare function exportObject(object: THREE.Object3D, format: ExportFormat): Promise<Blob>;
4
+ //# sourceMappingURL=three-export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"three-export.d.ts","sourceRoot":"","sources":["../../src/exports/three-export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,CAAC;AAEzC,wBAAsB,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B9F"}
@@ -0,0 +1,25 @@
1
+ export async function exportObject(object, format) {
2
+ if (format === "glb") {
3
+ const { GLTFExporter } = await import("three/examples/jsm/exporters/GLTFExporter.js");
4
+ const exporter = new GLTFExporter();
5
+ const arrayBuffer = await new Promise((resolve, reject) => {
6
+ exporter.parse(object, (result) => {
7
+ if (result instanceof ArrayBuffer) {
8
+ resolve(result);
9
+ return;
10
+ }
11
+ try {
12
+ resolve(new TextEncoder().encode(JSON.stringify(result)).buffer);
13
+ }
14
+ catch (error) {
15
+ reject(error);
16
+ }
17
+ }, (error) => reject(error), { binary: true });
18
+ });
19
+ return new Blob([arrayBuffer], { type: "model/gltf-binary" });
20
+ }
21
+ const { OBJExporter } = await import("three/examples/jsm/exporters/OBJExporter.js");
22
+ const exporter = new OBJExporter();
23
+ const text = exporter.parse(object);
24
+ return new Blob([text], { type: "text/plain" });
25
+ }
@@ -0,0 +1,18 @@
1
+ export type { ViewerCreateOptions, ViewerHandle, ViewerSnapshot, CameraState, RenderPresetDefinition, PresetCatalog, LightingRigConfig, PostFxConfig, SceneExtrasConfig, SkyDefinition, SkyHdrConfig, SkyCubeConfig, ViewerDebugInfo, } from "./engine/types";
2
+ export type { CameraFrameConfig, CameraFrameMode, CameraNormalizationConfig, CameraNormalizationResult, } from "./camera";
3
+ export { createViewer } from "./engine/createViewer";
4
+ export { computeCameraFrame, normalizeObject3d } from "./camera";
5
+ export { DEFAULT_PRESET_ID, DEFAULT_PRESETS } from "./presets/defaults";
6
+ export { SCIENCE_PRESETS, SCIENCE_PRESET_SUMMARIES, SCIENCE_DEFAULT_PRESET_ID, buildViewerPresets, buildSciencePresets, } from "./presets/sciencePresets";
7
+ export { listScienceSkyOptions, getScienceSkyOption } from "./sky/scienceSky";
8
+ export type { ScienceSkyOption } from "./sky/scienceSky";
9
+ export type { MaterialCatalogue, MaterialDefinition, MaterialId, MaterialColor, SurfaceMaterialConfig, MaterialsConfig, } from "./materials/types";
10
+ export { getMaterialCatalogue, findMaterial, listMaterialsByCategory } from "./materials/catalogue";
11
+ export { getRenderMaterialMetadata } from "./materials/renderMetadata";
12
+ export { BASELINE_MATERIAL_PRESET_ID, MATERIAL_PRESET_DATA, listMaterialPresets, getMaterialPreset, resolveMaterialSlot, resolveMaterialPresetMaterials, } from "./materials/presets";
13
+ export { applyMaterialsToGroup, buildSurfaceMaterial, buildCatalogMaterial, setTextureBaseUrl, } from "./materials/architectural";
14
+ export * from "./uploads";
15
+ export { exportObject } from "./exports/three-export";
16
+ export type { ExportFormat } from "./exports/three-export";
17
+ export { downloadBlob } from "./exports/download";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,qBAAqB,EACrB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ export { createViewer } from "./engine/createViewer";
2
+ export { computeCameraFrame, normalizeObject3d } from "./camera";
3
+ export { DEFAULT_PRESET_ID, DEFAULT_PRESETS } from "./presets/defaults";
4
+ export { SCIENCE_PRESETS, SCIENCE_PRESET_SUMMARIES, SCIENCE_DEFAULT_PRESET_ID, buildViewerPresets, buildSciencePresets, } from "./presets/sciencePresets";
5
+ export { listScienceSkyOptions, getScienceSkyOption } from "./sky/scienceSky";
6
+ export { getMaterialCatalogue, findMaterial, listMaterialsByCategory } from "./materials/catalogue";
7
+ export { getRenderMaterialMetadata } from "./materials/renderMetadata";
8
+ export { BASELINE_MATERIAL_PRESET_ID, MATERIAL_PRESET_DATA, listMaterialPresets, getMaterialPreset, resolveMaterialSlot, resolveMaterialPresetMaterials, } from "./materials/presets";
9
+ export { applyMaterialsToGroup, buildSurfaceMaterial, buildCatalogMaterial, setTextureBaseUrl, } from "./materials/architectural";
10
+ export * from "./uploads";
11
+ export { exportObject } from "./exports/three-export";
12
+ export { downloadBlob } from "./exports/download";
@@ -0,0 +1,7 @@
1
+ import * as THREE from "three";
2
+ import type { MaterialId, MaterialsConfig, SurfaceMaterialConfig } from "./types";
3
+ export declare const setTextureBaseUrl: (baseUrl?: string) => void;
4
+ export declare function buildSurfaceMaterial(surface: "walls" | "floor" | "ceiling", config: SurfaceMaterialConfig): THREE.MeshStandardMaterial;
5
+ export declare function buildCatalogMaterial(materialId: MaterialId, overrides?: Partial<SurfaceMaterialConfig>): THREE.MeshStandardMaterial;
6
+ export declare function applyMaterialsToGroup(group: THREE.Group, materialsConfig?: MaterialsConfig | null, floorLevel?: number, ceilingHeight?: number): void;
7
+ //# sourceMappingURL=architectural.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"architectural.d.ts","sourceRoot":"","sources":["../../src/materials/architectural.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAalF,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,SAMjD,CAAC;AA0GF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,EAAE,MAAM,EAAE,qBAAqB,8BAEzG;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,8BAiBtG;AA4BD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,EACxC,UAAU,CAAC,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI,CAgCN"}
@@ -0,0 +1,187 @@
1
+ import * as THREE from "three";
2
+ import { findMaterial } from "./catalogue";
3
+ import { getRenderMaterialMetadata } from "./renderMetadata";
4
+ const clamp01 = (value) => Math.min(Math.max(value, 0), 1);
5
+ const colorFromRGB = (rgb) => new THREE.Color(rgb.r / 255, rgb.g / 255, rgb.b / 255);
6
+ const textureLoader = new THREE.TextureLoader();
7
+ const textureCache = new Map();
8
+ let textureBaseUrl = "";
9
+ export const setTextureBaseUrl = (baseUrl) => {
10
+ if (!baseUrl) {
11
+ textureBaseUrl = "";
12
+ return;
13
+ }
14
+ textureBaseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
15
+ };
16
+ const resolveTexturePath = (path) => {
17
+ if (!textureBaseUrl)
18
+ return path;
19
+ if (path.startsWith("/"))
20
+ return `${textureBaseUrl}${path}`;
21
+ return path;
22
+ };
23
+ const loadTexture = (path, scale) => {
24
+ if (!path)
25
+ return undefined;
26
+ const resolved = resolveTexturePath(path);
27
+ const cached = textureCache.get(resolved);
28
+ if (cached)
29
+ return cached;
30
+ const texture = textureLoader.load(resolved, () => {
31
+ texture.needsUpdate = true;
32
+ });
33
+ texture.wrapS = THREE.RepeatWrapping;
34
+ texture.wrapT = THREE.RepeatWrapping;
35
+ if (scale) {
36
+ texture.repeat.set(scale[0], scale[1]);
37
+ }
38
+ texture.flipY = false;
39
+ textureCache.set(resolved, texture);
40
+ return texture;
41
+ };
42
+ const applyTexturesToMaterial = (material, textures) => {
43
+ if (!textures)
44
+ return;
45
+ let changed = false;
46
+ if (textures.albedo) {
47
+ const map = loadTexture(textures.albedo, textures.scale);
48
+ if (map) {
49
+ map.colorSpace = THREE.SRGBColorSpace;
50
+ material.map = map;
51
+ changed = true;
52
+ }
53
+ }
54
+ if (textures.normal) {
55
+ const map = loadTexture(textures.normal, textures.scale);
56
+ if (map) {
57
+ map.colorSpace = THREE.LinearSRGBColorSpace;
58
+ material.normalMap = map;
59
+ changed = true;
60
+ }
61
+ }
62
+ if (textures.roughness) {
63
+ const map = loadTexture(textures.roughness, textures.scale);
64
+ if (map) {
65
+ map.colorSpace = THREE.LinearSRGBColorSpace;
66
+ material.roughnessMap = map;
67
+ changed = true;
68
+ }
69
+ }
70
+ if (textures.ao) {
71
+ const map = loadTexture(textures.ao, textures.scale);
72
+ if (map) {
73
+ map.colorSpace = THREE.LinearSRGBColorSpace;
74
+ material.aoMap = map;
75
+ changed = true;
76
+ }
77
+ }
78
+ if (changed) {
79
+ material.needsUpdate = true;
80
+ }
81
+ };
82
+ const buildMaterial = (surface, config) => {
83
+ const isCustom = config.type === "custom";
84
+ const catalogueMaterial = !isCustom ? findMaterial(config.type) : undefined;
85
+ const renderMetadata = !isCustom ? getRenderMaterialMetadata(config.type) : undefined;
86
+ const hasAlbedoTexture = Boolean(renderMetadata?.textures?.albedo) || Boolean(catalogueMaterial?.pbr?.texture);
87
+ const baseColor = catalogueMaterial && hasAlbedoTexture
88
+ ? new THREE.Color(catalogueMaterial.pbr.baseColor)
89
+ : colorFromRGB(config.color);
90
+ const material = new THREE.MeshStandardMaterial({
91
+ color: baseColor.clone(),
92
+ roughness: clamp01(config.roughness ?? catalogueMaterial?.pbr.roughness ?? 0.6),
93
+ metalness: clamp01(catalogueMaterial?.pbr.metalness ?? 0),
94
+ emissive: new THREE.Color(catalogueMaterial?.pbr.emissive ?? "#ffffff"),
95
+ emissiveIntensity: clamp01(catalogueMaterial?.pbr.emissiveIntensity ?? 0.05),
96
+ depthWrite: true,
97
+ depthTest: true,
98
+ side: THREE.DoubleSide,
99
+ });
100
+ material.envMapIntensity = clamp01(config.reflectance ?? 0.5);
101
+ if (catalogueMaterial?.pbr.transparent || typeof catalogueMaterial?.pbr.opacity === "number") {
102
+ material.transparent = catalogueMaterial?.pbr.transparent ?? true;
103
+ material.opacity = clamp01(catalogueMaterial?.pbr.opacity ?? 1);
104
+ material.depthWrite = false;
105
+ }
106
+ if (!isCustom) {
107
+ if (renderMetadata?.doubleSided === false) {
108
+ material.side = THREE.FrontSide;
109
+ }
110
+ applyTexturesToMaterial(material, renderMetadata?.textures);
111
+ }
112
+ material.name = `${surface}-material`;
113
+ return material;
114
+ };
115
+ export function buildSurfaceMaterial(surface, config) {
116
+ return buildMaterial(surface, config);
117
+ }
118
+ export function buildCatalogMaterial(materialId, overrides) {
119
+ const definition = findMaterial(materialId);
120
+ const fallbackColor = definition?.baseline?.color ?? "#ffffff";
121
+ const color = overrides?.color ?? {
122
+ r: parseInt(fallbackColor.slice(1, 3), 16),
123
+ g: parseInt(fallbackColor.slice(3, 5), 16),
124
+ b: parseInt(fallbackColor.slice(5, 7), 16),
125
+ };
126
+ const config = {
127
+ type: materialId,
128
+ color,
129
+ reflectance: overrides?.reflectance ?? 0.5,
130
+ roughness: overrides?.roughness ?? definition?.pbr?.roughness ?? 0.6,
131
+ pattern: overrides?.pattern,
132
+ patternScale: overrides?.patternScale,
133
+ };
134
+ return buildMaterial(materialId, config);
135
+ }
136
+ const classifySurfaceWorld = (bboxWorld, floorY, ceilingY) => {
137
+ const dx = bboxWorld.max.x - bboxWorld.min.x;
138
+ const dy = bboxWorld.max.y - bboxWorld.min.y;
139
+ const dz = bboxWorld.max.z - bboxWorld.min.z;
140
+ const centerY = (bboxWorld.min.y + bboxWorld.max.y) / 2;
141
+ const midY = (floorY + ceilingY) / 2;
142
+ const isBroadHorizontal = dy <= 0.35 && dx >= 0.8 && dz >= 0.8;
143
+ if (isBroadHorizontal) {
144
+ return centerY <= midY ? "floor" : "ceiling";
145
+ }
146
+ const isSlabLike = dy <= 1.0 && dx >= 0.8 && dz >= 0.8;
147
+ if (isSlabLike) {
148
+ if (bboxWorld.max.y <= floorY + 0.6)
149
+ return "floor";
150
+ if (bboxWorld.min.y >= ceilingY - 0.6)
151
+ return "ceiling";
152
+ return centerY <= midY ? "floor" : "ceiling";
153
+ }
154
+ return "walls";
155
+ };
156
+ export function applyMaterialsToGroup(group, materialsConfig, floorLevel, ceilingHeight) {
157
+ if (!group || typeof group.traverse !== "function")
158
+ return;
159
+ const floorY = typeof floorLevel === "number" ? floorLevel : 0;
160
+ const ceilingY = typeof ceilingHeight === "number" ? floorY + ceilingHeight : undefined;
161
+ const materialSet = materialsConfig
162
+ ? {
163
+ walls: buildSurfaceMaterial("walls", materialsConfig.walls),
164
+ floor: buildSurfaceMaterial("floor", materialsConfig.floor),
165
+ ceiling: buildSurfaceMaterial("ceiling", materialsConfig.ceiling),
166
+ }
167
+ : null;
168
+ group.updateMatrixWorld(true);
169
+ group.traverse((child) => {
170
+ if (!child?.isMesh)
171
+ return;
172
+ child.castShadow = true;
173
+ child.receiveShadow = true;
174
+ child.geometry.computeBoundingBox();
175
+ const bbox = child.geometry.boundingBox;
176
+ const taggedMaterialId = typeof child.userData?.material === "string" ? child.userData.material : null;
177
+ if (taggedMaterialId && findMaterial(taggedMaterialId)) {
178
+ child.material = buildCatalogMaterial(taggedMaterialId);
179
+ }
180
+ else if (bbox && materialSet && typeof ceilingY === "number") {
181
+ const bboxWorld = bbox.clone().applyMatrix4(child.matrixWorld);
182
+ const surface = classifySurfaceWorld(bboxWorld, floorY, ceilingY);
183
+ child.material = materialSet[surface].clone();
184
+ }
185
+ child.geometry.computeVertexNormals();
186
+ });
187
+ }