@inweb/viewer-three 26.5.0 → 26.5.2

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 (53) hide show
  1. package/dist/plugins/components/AxesHelperComponent.js +65 -0
  2. package/dist/plugins/components/AxesHelperComponent.js.map +1 -0
  3. package/dist/plugins/components/AxesHelperComponent.min.js +1 -0
  4. package/dist/plugins/components/AxesHelperComponent.module.js +39 -0
  5. package/dist/plugins/components/AxesHelperComponent.module.js.map +1 -0
  6. package/dist/plugins/components/ExtentsHelperComponent.js +55 -0
  7. package/dist/plugins/components/ExtentsHelperComponent.js.map +1 -0
  8. package/dist/plugins/components/ExtentsHelperComponent.min.js +1 -0
  9. package/dist/plugins/components/ExtentsHelperComponent.module.js +29 -0
  10. package/dist/plugins/components/ExtentsHelperComponent.module.js.map +1 -0
  11. package/dist/plugins/components/LightHelperComponent.js +65 -0
  12. package/dist/plugins/components/LightHelperComponent.js.map +1 -0
  13. package/dist/plugins/components/LightHelperComponent.min.js +1 -0
  14. package/dist/plugins/components/LightHelperComponent.module.js +40 -0
  15. package/dist/plugins/components/LightHelperComponent.module.js.map +1 -0
  16. package/dist/plugins/loaders/IFCXLoader.js +887 -0
  17. package/dist/plugins/loaders/IFCXLoader.js.map +1 -0
  18. package/dist/plugins/loaders/IFCXLoader.min.js +1 -0
  19. package/dist/plugins/loaders/IFCXLoader.module.js +726 -0
  20. package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -0
  21. package/dist/viewer-three.js +50355 -33683
  22. package/dist/viewer-three.js.map +1 -1
  23. package/dist/viewer-three.min.js +2 -7
  24. package/dist/viewer-three.module.js +192 -86
  25. package/dist/viewer-three.module.js.map +1 -1
  26. package/lib/Viewer/Viewer.d.ts +51 -68
  27. package/lib/Viewer/loaders/GLTFFileLoader.d.ts +9 -0
  28. package/lib/Viewer/loaders/GLTFLoadingManager.d.ts +9 -3
  29. package/lib/Viewer/loaders/GLTFModelLoader.d.ts +8 -0
  30. package/lib/Viewer/loaders/index.d.ts +67 -0
  31. package/lib/index-umd.d.ts +1 -0
  32. package/lib/index.d.ts +6 -4
  33. package/package.json +10 -7
  34. package/{src/Viewer → plugins}/components/AxesHelperComponent.ts +4 -4
  35. package/{src/Viewer → plugins}/components/ExtentsHelperComponent.ts +4 -4
  36. package/{src/Viewer → plugins}/components/LightHelperComponent.ts +4 -4
  37. package/plugins/loaders/IFCX/IFCXLoader.ts +71 -0
  38. package/plugins/loaders/IFCX/render.js +701 -0
  39. package/plugins/loaders/IFCXFileLoader.ts +76 -0
  40. package/plugins/loaders/IFCXLoader.ts +30 -0
  41. package/plugins/loaders/IFCXModelLoader.ts +75 -0
  42. package/src/Viewer/Viewer.ts +101 -148
  43. package/src/Viewer/commands/Explode.ts +2 -2
  44. package/src/Viewer/components/index.ts +2 -8
  45. package/src/Viewer/loaders/GLTFFileLoader.ts +73 -0
  46. package/src/Viewer/loaders/GLTFLoadingManager.ts +16 -8
  47. package/src/Viewer/loaders/GLTFModelLoader.ts +74 -0
  48. package/src/Viewer/loaders/index.ts +99 -0
  49. package/src/index-umd.ts +30 -0
  50. package/src/index.ts +9 -5
  51. package/lib/Viewer/components/AxesHelperComponent.d.ts +0 -10
  52. package/lib/Viewer/components/ExtentsHelperComponent.d.ts +0 -9
  53. package/lib/Viewer/components/LightHelperComponent.d.ts +0 -9
@@ -1,12 +1,8 @@
1
- import { draggersRegistry, commandsRegistry, componentsRegistry, Options, CANVAS_EVENTS } from "@inweb/viewer-core";
1
+ import { draggersRegistry, commandsRegistry, componentsRegistry, Loader, loadersRegistry, Options, CANVAS_EVENTS } from "@inweb/viewer-core";
2
2
 
3
3
  export * from "@inweb/viewer-core";
4
4
 
5
- import { Markup } from "@inweb/markup";
6
-
7
- export * from "@inweb/markup";
8
-
9
- import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Matrix4, Vector4, Raycaster, Controls, Clock, Box3, Sphere, MathUtils, Color, PMREMGenerator, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, LoadingManager, LoaderUtils, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
5
+ import { Line, Vector3, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, EventDispatcher, MOUSE, TOUCH, Spherical, Quaternion, Vector2, Plane, Object3D, Matrix4, Vector4, Raycaster, Controls, Clock, Box3, Sphere, MathUtils, Color, PMREMGenerator, AmbientLight, DirectionalLight, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, LoadingManager, LoaderUtils, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
10
6
 
11
7
  import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
12
8
 
@@ -16,6 +12,10 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
16
12
 
17
13
  import { EventEmitter2 } from "@inweb/eventemitter2";
18
14
 
15
+ import { Markup } from "@inweb/markup";
16
+
17
+ export * from "@inweb/markup";
18
+
19
19
  class PlaneHelper extends Line {
20
20
  constructor(plane, size = 1, color = 16776960, offset = new Vector3) {
21
21
  const positions = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0 ];
@@ -1519,7 +1519,7 @@ function calcExplodeDepth(object, depth) {
1519
1519
  return res;
1520
1520
  }
1521
1521
 
1522
- function explodeScene(scene, scale = 0, coeff = 4) {
1522
+ function explodeModel(scene, scale = 0, coeff = 4) {
1523
1523
  scale /= 100;
1524
1524
  if (!scene.explodeDepth) scene.explodeDepth = calcExplodeDepth(scene, 1);
1525
1525
  const maxDepth = scene.explodeDepth;
@@ -1542,7 +1542,7 @@ function explodeScene(scene, scale = 0, coeff = 4) {
1542
1542
  }
1543
1543
 
1544
1544
  function explode(viewer, index = 0) {
1545
- viewer.models.forEach((model => explodeScene(model.scene, index)));
1545
+ viewer.models.forEach((model => explodeModel(model, index)));
1546
1546
  viewer.scene.updateMatrixWorld();
1547
1547
  viewer.update();
1548
1548
  viewer.emitEvent({
@@ -2038,6 +2038,38 @@ class ExtentsComponent {
2038
2038
  }
2039
2039
  }
2040
2040
 
2041
+ class LightComponent {
2042
+ constructor(viewer) {
2043
+ this.geometryEnd = () => {
2044
+ this.ambientLight.removeFromParent();
2045
+ this.directionalLight.removeFromParent();
2046
+ if (this.viewer.extents.isEmpty()) return;
2047
+ const extentsCenter = this.viewer.extents.getCenter(new Vector3);
2048
+ const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere).radius * 2;
2049
+ this.directionalLight.position.set(.5, 0, .866).multiplyScalar(extentsSize).add(extentsCenter);
2050
+ this.directionalLight.target.position.copy(extentsCenter);
2051
+ this.viewer.scene.add(this.ambientLight);
2052
+ this.viewer.scene.add(this.directionalLight);
2053
+ };
2054
+ this.viewer = viewer;
2055
+ this.ambientLight = new AmbientLight(16777215, 0);
2056
+ this.viewer.scene.add(this.ambientLight);
2057
+ this.directionalLight = new DirectionalLight(16777215, 1);
2058
+ this.directionalLight.position.set(.5, 0, .866);
2059
+ this.viewer.scene.add(this.directionalLight);
2060
+ this.viewer.addEventListener("databasechunk", this.geometryEnd);
2061
+ this.viewer.addEventListener("clear", this.geometryEnd);
2062
+ }
2063
+ dispose() {
2064
+ this.ambientLight.removeFromParent();
2065
+ this.ambientLight.dispose();
2066
+ this.directionalLight.removeFromParent();
2067
+ this.directionalLight.dispose();
2068
+ this.viewer.removeEventListener("databasechunk", this.geometryEnd);
2069
+ this.viewer.removeEventListener("clear", this.geometryEnd);
2070
+ }
2071
+ }
2072
+
2041
2073
  class RenderLoopComponent {
2042
2074
  constructor(viewer) {
2043
2075
  this.animate = (time = 0) => {
@@ -2200,6 +2232,8 @@ components.registerComponent("BackgroundComponent", (viewer => new BackgroundCom
2200
2232
 
2201
2233
  components.registerComponent("RoomEnvironmentComponent", (viewer => new RoomEnvironmentComponent(viewer)));
2202
2234
 
2235
+ components.registerComponent("LightComponent", (viewer => new LightComponent(viewer)));
2236
+
2203
2237
  components.registerComponent("ResizeCanvasComponent", (viewer => new ResizeCanvasComponent(viewer)));
2204
2238
 
2205
2239
  components.registerComponent("RenderLoopComponent", (viewer => new RenderLoopComponent(viewer)));
@@ -2209,21 +2243,22 @@ components.registerComponent("SelectionComponent", (viewer => new SelectionCompo
2209
2243
  components.registerComponent("WCSHelperComponent", (viewer => new WCSHelperComponent(viewer)));
2210
2244
 
2211
2245
  class GLTFLoadingManager extends LoadingManager {
2212
- constructor(file, externalData = new Map, params = {}) {
2246
+ constructor(file, params = {}) {
2213
2247
  super();
2214
2248
  this.path = "";
2215
2249
  this.resourcePath = "";
2216
2250
  this.fileURL = "";
2217
2251
  this.dataURLs = new Map;
2218
2252
  this.path = params.path || "";
2253
+ const externalFiles = params.externalFiles || new Map;
2219
2254
  if (typeof file === "string") {
2220
2255
  this.fileURL = file;
2221
2256
  this.resourcePath = LoaderUtils.extractUrlBase(file);
2222
2257
  } else {
2223
- externalData.forEach(((value, key) => this.fileURL = value === file ? key : this.fileURL));
2224
- externalData.set(this.fileURL, file);
2258
+ externalFiles.forEach(((value, key) => this.fileURL = value === file ? key : this.fileURL));
2259
+ externalFiles.set(this.fileURL, file);
2225
2260
  }
2226
- externalData.forEach(((value, key) => {
2261
+ externalFiles.forEach(((value, key) => {
2227
2262
  let dataURL;
2228
2263
  if (typeof value === "string") dataURL = value; else dataURL = URL.createObjectURL(new Blob([ value ]));
2229
2264
  this.dataURLs.set(key, dataURL);
@@ -2239,6 +2274,91 @@ class GLTFLoadingManager extends LoadingManager {
2239
2274
  }
2240
2275
  }
2241
2276
 
2277
+ class GLTFModelLoader extends Loader {
2278
+ constructor(viewer) {
2279
+ super();
2280
+ this.viewer = viewer;
2281
+ }
2282
+ isSupport(model) {
2283
+ return typeof model === "object" && typeof model.database === "string" && typeof model.downloadResource === "function" && /.gltf$/i.test(model.database);
2284
+ }
2285
+ async load(model) {
2286
+ const url = `${model.httpClient.serverUrl}${model.path}/${model.database}`;
2287
+ const manager = new GLTFLoadingManager(url);
2288
+ const loader = new GLTFLoader(manager);
2289
+ loader.setRequestHeader(model.httpClient.headers);
2290
+ const progress = event => {
2291
+ const {lengthComputable: lengthComputable, loaded: loaded, total: total} = event;
2292
+ const progress = lengthComputable ? loaded / total : 1;
2293
+ this.viewer.emitEvent({
2294
+ type: "geometryprogress",
2295
+ data: progress,
2296
+ file: model.file,
2297
+ model: model
2298
+ });
2299
+ };
2300
+ const gltf = await loader.loadAsync(url, progress);
2301
+ if (!this.viewer.scene) return this;
2302
+ this.viewer.scene.add(gltf.scene);
2303
+ this.viewer.models.push(gltf.scene);
2304
+ this.viewer.syncOptions();
2305
+ this.viewer.syncOverlay();
2306
+ this.viewer.update();
2307
+ this.viewer.emitEvent({
2308
+ type: "databasechunk",
2309
+ data: gltf.scene,
2310
+ file: model.file,
2311
+ model: model
2312
+ });
2313
+ return this;
2314
+ }
2315
+ }
2316
+
2317
+ class GLTFFileLoader extends Loader {
2318
+ constructor(viewer) {
2319
+ super();
2320
+ this.viewer = viewer;
2321
+ }
2322
+ isSupport(file, format) {
2323
+ return (typeof file === "string" || file instanceof globalThis.File || file instanceof ArrayBuffer) && /(gltf|glb)$/i.test(format);
2324
+ }
2325
+ async load(buffer, format, params) {
2326
+ const manager = new GLTFLoadingManager(buffer, params);
2327
+ const loader = new GLTFLoader(manager);
2328
+ loader.setPath(manager.path);
2329
+ loader.setCrossOrigin(params.crossOrigin || loader.crossOrigin);
2330
+ loader.setWithCredentials(params.withCredentials || loader.withCredentials);
2331
+ const progress = event => {
2332
+ const {lengthComputable: lengthComputable, loaded: loaded, total: total} = event;
2333
+ const progress = lengthComputable ? loaded / total : 1;
2334
+ this.viewer.emitEvent({
2335
+ type: "geometryprogress",
2336
+ data: progress,
2337
+ file: buffer
2338
+ });
2339
+ };
2340
+ const gltf = await loader.loadAsync(manager.fileURL, progress);
2341
+ if (!this.viewer.scene) return this;
2342
+ this.viewer.scene.add(gltf.scene);
2343
+ this.viewer.models.push(gltf.scene);
2344
+ this.viewer.syncOptions();
2345
+ this.viewer.syncOverlay();
2346
+ this.viewer.update();
2347
+ this.viewer.emitEvent({
2348
+ type: "databasechunk",
2349
+ data: gltf.scene,
2350
+ file: buffer
2351
+ });
2352
+ return this;
2353
+ }
2354
+ }
2355
+
2356
+ const loaders = loadersRegistry("threejs");
2357
+
2358
+ loaders.registerLoader("gltf", (viewer => new GLTFModelLoader(viewer)));
2359
+
2360
+ loaders.registerLoader("gltf-file", (viewer => new GLTFFileLoader(viewer)));
2361
+
2242
2362
  class Viewer extends EventEmitter2 {
2243
2363
  constructor(client) {
2244
2364
  super();
@@ -2247,6 +2367,7 @@ class Viewer extends EventEmitter2 {
2247
2367
  this.canvasEvents = CANVAS_EVENTS;
2248
2368
  this.canvaseventlistener = event => this.emit(event);
2249
2369
  this.models = [];
2370
+ this.loaders = [];
2250
2371
  this.selected = [];
2251
2372
  this.extents = new Box3;
2252
2373
  this.target = new Vector3;
@@ -2372,97 +2493,80 @@ class Viewer extends EventEmitter2 {
2372
2493
  loadReferences(model) {
2373
2494
  return Promise.resolve(this);
2374
2495
  }
2375
- async open(file) {
2496
+ async open(file, params = {}) {
2376
2497
  if (!this.renderer) return this;
2377
- this.cancel();
2378
- this.clear();
2498
+ if (params.mode !== "a" && params.mode !== "append") {
2499
+ this.cancel();
2500
+ this.clear();
2501
+ }
2379
2502
  this.emitEvent({
2380
2503
  type: "open",
2381
- file: file,
2382
- model: file
2504
+ file: file
2383
2505
  });
2384
- let model = undefined;
2385
- if (file) {
2386
- const models = await file.getModels() || [];
2387
- model = models.find((model => model.default)) || models[0];
2506
+ let model = file;
2507
+ if (model && typeof model.getModels === "function") {
2508
+ const models = await model.getModels();
2509
+ model = models.find((model => model.default)) || models[0] || file;
2388
2510
  }
2389
- if (!model) throw new Error("No default model found");
2390
- const geometryType = model.database.split(".").pop();
2391
- if (geometryType !== "gltf") throw new Error(`Unknown geometry type: ${geometryType}`);
2392
- const url = `${model.httpClient.serverUrl}${model.path}/${model.database}`;
2393
- const params = {
2394
- requestHeader: model.httpClient.headers
2395
- };
2396
- await this.loadReferences(model);
2397
- await this.loadGltfFile(url, undefined, params);
2398
- return this;
2399
- }
2400
- cancel() {
2401
- this.emitEvent({
2402
- type: "cancel"
2403
- });
2404
- return this;
2405
- }
2406
- openGltfFile(file, externalData = new Map, params = {}) {
2407
- if (!this.renderer) return Promise.resolve(this);
2408
- this.cancel();
2409
- this.clear();
2511
+ if (!model) throw new Error(`Format not supported`);
2512
+ let format = params.format;
2513
+ if (!format && typeof model.type === "string") format = model.type.split(".").pop();
2514
+ if (!format && typeof file === "string") format = file.split(".").pop();
2515
+ if (!format && file instanceof globalThis.File) format = file.name.split(".").pop();
2516
+ const loader = loaders.createLoader(this, model, format);
2517
+ if (!loader) throw new Error(`Format not supported`);
2518
+ this.loaders.push(loader);
2410
2519
  this.emitEvent({
2411
- type: "open"
2520
+ type: "geometrystart",
2521
+ file: file,
2522
+ model: model
2412
2523
  });
2413
- return this.loadGltfFile(file, externalData, params);
2414
- }
2415
- async loadGltfFile(file, externalData = new Map, params = {}) {
2416
- const manager = new GLTFLoadingManager(file, externalData, params);
2417
2524
  try {
2418
- this.emitEvent({
2419
- type: "geometrystart"
2420
- });
2421
- const loader = new GLTFLoader(manager);
2422
- loader.setPath(manager.path);
2423
- loader.setRequestHeader(params.requestHeader);
2424
- loader.setCrossOrigin(params.crossOrigin || loader.crossOrigin);
2425
- loader.setWithCredentials(params.withCredentials || loader.withCredentials);
2426
- const gltf = await loader.loadAsync(manager.fileURL, (event => {
2427
- const {lengthComputable: lengthComputable, loaded: loaded, total: total} = event;
2428
- const progress = lengthComputable ? loaded / total : 1;
2429
- this.emitEvent({
2430
- type: "geometryprogress",
2431
- data: progress
2432
- });
2433
- }));
2434
- if (!this.scene) return this;
2435
- if (!gltf.scene) throw new Error("No glTF scene found");
2436
- this.models.push(gltf);
2437
- this.scene.add(gltf.scene);
2438
- this.syncOptions();
2439
- this.syncOverlay();
2440
- this.update();
2441
- this.emitEvent({
2442
- type: "databasechunk"
2443
- });
2444
- this.emitEvent({
2445
- type: "geometryend",
2446
- data: gltf.scene
2447
- });
2525
+ await this.loadReferences(model);
2526
+ await loader.load(model, format, params);
2448
2527
  } catch (error) {
2449
2528
  this.emitEvent({
2450
2529
  type: "geometryerror",
2451
- data: error
2530
+ data: error,
2531
+ file: file,
2532
+ model: model
2452
2533
  });
2453
2534
  throw error;
2454
- } finally {
2455
- manager.dispose();
2456
2535
  }
2536
+ this.emitEvent({
2537
+ type: "geometryend",
2538
+ file: file,
2539
+ model: model
2540
+ });
2541
+ return this;
2542
+ }
2543
+ openGltfFile(file, externalFiles, params = {}) {
2544
+ return this.open(file, {
2545
+ ...params,
2546
+ format: "gltf",
2547
+ externalFiles: externalFiles
2548
+ });
2549
+ }
2550
+ loadGltfFile(file, externalFiles, params = {}) {
2551
+ return this.open(file, {
2552
+ ...params,
2553
+ format: "gltf",
2554
+ externalFiles: externalFiles,
2555
+ mode: "append"
2556
+ });
2557
+ }
2558
+ cancel() {
2559
+ this.loaders.forEach((loader => loader.cancel()));
2560
+ this.emitEvent({
2561
+ type: "cancel"
2562
+ });
2457
2563
  return this;
2458
2564
  }
2459
2565
  clear() {
2460
2566
  if (!this.renderer) return this;
2461
2567
  function disposeMaterial(material) {
2462
2568
  const materials = Array.isArray(material) ? material : [ material ];
2463
- materials.forEach((material => {
2464
- material.dispose();
2465
- }));
2569
+ materials.forEach((material => material.dispose()));
2466
2570
  }
2467
2571
  function disposeObject(object) {
2468
2572
  if (object.geometry) object.geometry.dispose();
@@ -2474,10 +2578,12 @@ class Viewer extends EventEmitter2 {
2474
2578
  this.clearSelected();
2475
2579
  this.helpers.traverse(disposeObject);
2476
2580
  this.helpers.clear();
2477
- this.models.forEach((gltf => gltf.scene.traverse(disposeObject)));
2478
- this.models.forEach((gltf => gltf.scene.removeFromParent()));
2581
+ this.models.forEach((model => model.traverse(disposeObject)));
2582
+ this.models.forEach((model => model.removeFromParent()));
2479
2583
  this.models = [];
2480
2584
  this.scene.clear();
2585
+ this.loaders.forEach((loader => loader.dispose()));
2586
+ this.loaders = [];
2481
2587
  this.syncOptions();
2482
2588
  this.syncOverlay();
2483
2589
  this.update(true);
@@ -2740,5 +2846,5 @@ class Viewer extends EventEmitter2 {
2740
2846
  }
2741
2847
  }
2742
2848
 
2743
- export { Viewer, commands, components, draggers };
2849
+ export { GLTFLoadingManager, Viewer, commands, components, draggers, loaders };
2744
2850
  //# sourceMappingURL=viewer-three.module.js.map