UNPKG

@inweb/viewer-three

Version:

JavaScript library for rendering CAD and BIM files in a browser using Three.js

142 lines (115 loc) 4.91 kB
/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a // license agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// import { Group } from "three"; import { ILoader, LoadParams } from "@inweb/viewer-core"; import { Viewer } from "../Viewer"; import { DynamicModelImpl } from "./DynamicGltfLoader/DynamicModelImpl"; import { DynamicGltfLoader } from "./DynamicGltfLoader/DynamicGltfLoader.js"; import { GltfStructure } from "./DynamicGltfLoader/GltfStructure.js"; export class GLTFCloudDynamicLoader implements ILoader { public viewer: Viewer; public gltfLoader: DynamicGltfLoader; public requestId = 0; constructor(viewer: Viewer) { this.viewer = viewer; } dispose() { if (this.gltfLoader) this.gltfLoader.clear(); } isSupport(file: any): boolean { return ( typeof file === "object" && typeof file.database === "string" && typeof file.downloadResource === "function" && typeof file.downloadResourceRange === "function" && /.gltf$/i.test(file.database) ); } async load(model: any, format?: string, params?: LoadParams): Promise<this> { const scene = new Group(); this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer); this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit; this.gltfLoader.setVisibleEdges(this.viewer.options.edgeModel); // this.gltfLoader.setMaxConcurrentChunks(this.viewer.options.maxConcurrentChunks); this.gltfLoader.addEventListener("databasechunk", (data) => { const modelImpl = new DynamicModelImpl(scene); modelImpl.loader = this; modelImpl.viewer = this.viewer; modelImpl.gltfLoader = this.gltfLoader; modelImpl.modelId = model.id; this.viewer.scene.add(scene); this.viewer.models.push(modelImpl); this.viewer.syncOptions(); this.viewer.syncOverlay(); this.viewer.update(); this.viewer.emitEvent({ type: "databasechunk", data: scene, file: model.file, model }); }); this.gltfLoader.addEventListener("geometryprogress", (data) => { const progress = data.loaded / data.total; this.viewer.emitEvent({ type: "geometryprogress", data: progress, file: model.file, model }); }); this.gltfLoader.addEventListener("geometryerror", (data) => { this.viewer.emitEvent({ type: "geometryerror", data, file: model.file, model }); }); this.gltfLoader.addEventListener("update", (data) => { this.viewer.update(); }); const loadController = { loadJson: async () => { const progress = (progress: number) => { this.viewer.emitEvent({ type: "geometryprogress", data: progress, file: model }); }; const arrayBuffer = await model.downloadResource( model.database, progress, this.gltfLoader.getAbortController().signal ); const text = new TextDecoder().decode(arrayBuffer); const json = JSON.parse(text); return json; }, loadBinaryData: (requests) => { const ranges = requests.map((request) => ({ begin: request.offset, end: request.offset + request.length - 1, requestId: this.requestId++, })); return model.downloadResourceRange( model.geometry[0], undefined, ranges, undefined, this.gltfLoader.getAbortController().signal ); }, baseUrl: () => Promise.resolve(`${model.httpClient.serverUrl}${model.path}/`), }; const structure = new GltfStructure(model.id, loadController); await this.gltfLoader.loadStructure(structure); await this.gltfLoader.loadNodes(); return this; } cancel() { if (this.gltfLoader) this.gltfLoader.abortLoading(); } }