From eec93469b34cfdcd5abf70534ce18c6372ab3ced Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Fri, 30 May 2025 15:14:32 +0100 Subject: [PATCH] trying to add a separate geometry conversion progress as well as data loading progress (#4710) * Adding more progress to loading and rendering of a model * have separate values for loading totals * Allow callback to be null * Fix loading test * Prettier * Revert sandbox changes --- packages/viewer-sandbox/src/Sandbox.ts | 24 ++++++++++++++--- packages/viewer-sandbox/src/main.ts | 4 +-- packages/viewer/src/modules/loaders/Loader.ts | 6 ++++- .../modules/loaders/Speckle/SpeckleLoader.ts | 27 ++++++++++++++----- .../viewer/src/modules/tree/RenderTree.ts | 11 +++++--- 5 files changed, 56 insertions(+), 16 deletions(-) diff --git a/packages/viewer-sandbox/src/Sandbox.ts b/packages/viewer-sandbox/src/Sandbox.ts index 39ad8dbca..584c6dea5 100644 --- a/packages/viewer-sandbox/src/Sandbox.ts +++ b/packages/viewer-sandbox/src/Sandbox.ts @@ -1325,17 +1325,35 @@ export default class Sandbox { true, undefined ) - let progress = 0 + let dataProgress = 0 + let renderedCount = 0 + let traversedCount = 0 /** Too spammy */ loader.on(LoaderEvent.LoadProgress, (arg: { progress: number; id: string }) => { const p = Math.floor(arg.progress * 100) - if (p > progress) { + if (p > dataProgress) { if (colorImage) colorImage.style.clipPath = `inset(${(1 - arg.progress) * 100}% 0 0 0)` - progress = p + dataProgress = p console.log(`Loading ${p}%`) } }) + loader.on(LoaderEvent.Traversed, (arg: { count: number }) => { + if (arg.count > traversedCount) { + traversedCount = arg.count + if (traversedCount % 777 === 0) { + console.log(`Traversed Data ${traversedCount}`) + } + } + }) + loader.on(LoaderEvent.Converted, (arg: { count: number }) => { + if (arg.count > renderedCount) { + renderedCount = arg.count + if (renderedCount % 777 === 0) { + console.log(`Rendering Data ${renderedCount}`) + } + } + }) loader.on(LoaderEvent.LoadCancelled, (resource: string) => { console.warn(`Resource ${resource} loading was canceled`) }) diff --git a/packages/viewer-sandbox/src/main.ts b/packages/viewer-sandbox/src/main.ts index 977d53225..8d0c17f3d 100644 --- a/packages/viewer-sandbox/src/main.ts +++ b/packages/viewer-sandbox/src/main.ts @@ -117,10 +117,10 @@ const getStream = () => { // 'https://latest.speckle.systems/streams/58b5648c4d/commits/60371ecb2d' //bad commit! not all items uploaded to server - // 'https://app.speckle.systems/projects/8e4347e65d/models/39bea37d69' + //'https://app.speckle.systems/projects/8e4347e65d/models/39bea37d69' // 'Super' heavy revit shit - // 'https://app.speckle.systems/streams/e6f9156405/commits/0694d53bb5' + //'https://app.speckle.systems/streams/e6f9156405/commits/0694d53bb5' // IFC building (good for a tree based structure) // 'https://latest.speckle.systems/streams/92b620fb17/commits/2ebd336223' // IFC story, a subtree of the above diff --git a/packages/viewer/src/modules/loaders/Loader.ts b/packages/viewer/src/modules/loaders/Loader.ts index ac338e580..db0a83d09 100644 --- a/packages/viewer/src/modules/loaders/Loader.ts +++ b/packages/viewer/src/modules/loaders/Loader.ts @@ -3,11 +3,15 @@ import EventEmitter from '../EventEmitter.js' export enum LoaderEvent { LoadProgress = 'load-progress', LoadCancelled = 'load-cancelled', - LoadWarning = 'load-warning' + LoadWarning = 'load-warning', + Converted = 'converted', + Traversed = 'traversed' } export interface LoaderEventPayload { [LoaderEvent.LoadProgress]: { progress: number; id: string } + [LoaderEvent.Converted]: { count: number } + [LoaderEvent.Traversed]: { count: number } [LoaderEvent.LoadCancelled]: string [LoaderEvent.LoadWarning]: { message: string } } diff --git a/packages/viewer/src/modules/loaders/Speckle/SpeckleLoader.ts b/packages/viewer/src/modules/loaders/Speckle/SpeckleLoader.ts index 381c98da4..7cc054666 100644 --- a/packages/viewer/src/modules/loaders/Speckle/SpeckleLoader.ts +++ b/packages/viewer/src/modules/loaders/Speckle/SpeckleLoader.ts @@ -86,9 +86,9 @@ export class SpeckleLoader extends Loader { public async load(): Promise { const start = performance.now() let first = true - let current = 0 + let dataloading = 0 const total = await this.loader.getTotalObjectCount() - let viewerLoads = 0 + let traversals = 0 let firstObjectPromise = null Logger.warn('Downloading object ', this.resource) @@ -103,14 +103,17 @@ export class SpeckleLoader extends Loader { this.resource, obj as SpeckleObject, async () => { - viewerLoads++ + traversals++ + this.emit(LoaderEvent.Traversed, { + count: traversals + }) } ) first = false } - current++ + dataloading++ this.emit(LoaderEvent.LoadProgress, { - progress: current / (total + 1), + progress: dataloading / (total + 1), id: this.resource }) } @@ -125,7 +128,7 @@ export class SpeckleLoader extends Loader { } seconds. Node count: ${this.tree.nodeCount}` ) - if (viewerLoads === 0) { + if (traversals === 0) { Logger.warn(`Viewer: no 3d objects found in object ${this.resource}`) this.emit(LoaderEvent.LoadWarning, { message: `No displayable objects found in object ${this.resource}.` @@ -144,7 +147,17 @@ export class SpeckleLoader extends Loader { const renderTree = this.tree.getRenderTree(this.resource) if (!renderTree) return Promise.resolve(false) - const p = renderTree.buildRenderTree(geometryConverter) + let converted = 0 + const p = renderTree.buildRenderTree(geometryConverter, () => { + converted++ + this.emit(LoaderEvent.Converted, { + count: converted + }) + }) + + Logger.warn( + `Finished rendering object . Node count: ${this.tree.nodeCount} Total: ${total}` + ) void p.then(() => { Logger.log('ASYNC Tree build time -> ', performance.now() - t0) diff --git a/packages/viewer/src/modules/tree/RenderTree.ts b/packages/viewer/src/modules/tree/RenderTree.ts index e70a9e1e4..fb2f93591 100644 --- a/packages/viewer/src/modules/tree/RenderTree.ts +++ b/packages/viewer/src/modules/tree/RenderTree.ts @@ -29,10 +29,13 @@ export class RenderTree { this.root = subtreeRoot } - public buildRenderTree(geometryConverter: GeometryConverter): Promise { + public buildRenderTree( + geometryConverter: GeometryConverter, + callback?: () => void + ): Promise { const p = this.tree.walkAsync((node: TreeNode): boolean => { let start = performance.now() - const rendeNode = this.buildRenderNode(node, geometryConverter) + const rendeNode = this.buildRenderNode(node, geometryConverter, callback) node.model.renderView = rendeNode ? new NodeRenderView(rendeNode) : null this.buildNodeTime += performance.now() - start start = performance.now() @@ -71,11 +74,13 @@ export class RenderTree { private buildRenderNode( node: TreeNode, - geometryConverter: GeometryConverter + geometryConverter: GeometryConverter, + callback?: () => void ): NodeRenderData | null { let ret: NodeRenderData | null = null let start = performance.now() const geometryData = geometryConverter.convertNodeToGeometryData(node.model) + if (callback) callback() this.convertTime += performance.now() - start if (geometryData) { start = performance.now()