UNPKG

@inweb/viewer-three

Version:

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

140 lines (114 loc) 4.8 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, LoaderUtils } from "three"; import { Loader, 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 extends Loader { public viewer: Viewer; public gltfLoader: DynamicGltfLoader; public requestId = 0; constructor(viewer: Viewer) { super(); this.viewer = viewer; } override dispose() { if (this.gltfLoader) this.gltfLoader.clear(); } override 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) ); } override 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); const modelImpl = new DynamicModelImpl(scene); modelImpl.id = model.file.id; modelImpl.gltfLoader = this.gltfLoader; this.gltfLoader.addEventListener("databasechunk", (data) => { this.viewer.scene.add(scene); this.viewer.models.push(modelImpl); this.viewer.syncOptions(); this.viewer.syncOverlay(); this.viewer.emitEvent({ type: "databasechunk", data: scene, file: model.file, model }); this.viewer.update(true); }); this.gltfLoader.addEventListener("geometryerror", (data) => { this.viewer.emitEvent({ type: "geometryerror", data, file: model.file, model }); }); this.gltfLoader.addEventListener("update", () => { this.viewer.update(); }); const loadController = { loadJson: async () => { const progress = (progress: number) => { this.viewer.emitEvent({ type: "geometryprogress", data: progress, file: model.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 ); }, resolveURL: (uri) => { const path = `${model.httpClient.serverUrl}${model.path}/`; const url = LoaderUtils.resolveURL(uri, path); return Promise.resolve(url); }, }; const structure = new GltfStructure(modelImpl.id, loadController); await this.gltfLoader.loadStructure(structure); await this.gltfLoader.loadNodes(); return this; } override cancel() { if (this.gltfLoader) this.gltfLoader.abortLoading(); } }