From 9e7c80bb4fabe5da0d19f3098d77e30bf7816627 Mon Sep 17 00:00:00 2001 From: AlexandruPopovici Date: Wed, 27 Jul 2022 15:09:46 +0300 Subject: [PATCH] #828. Added controlled update and render loops which propagate throught the viewer library --- .../viewer/src/modules/SpeckleRenderer.ts | 10 ++++ packages/viewer/src/modules/Viewer.ts | 47 +++++++++---------- packages/viewer/src/modules/batching/Batch.ts | 4 +- .../viewer/src/modules/batching/Batcher.ts | 14 +++++- .../viewer/src/modules/batching/LineBatch.ts | 11 ++++- .../viewer/src/modules/batching/MeshBatch.ts | 11 ++++- .../viewer/src/modules/batching/PointBatch.ts | 11 ++++- .../viewer/src/modules/materials/Materials.ts | 33 +++++-------- .../modules/materials/SpeckleLineMaterial.ts | 6 +-- 9 files changed, 93 insertions(+), 54 deletions(-) diff --git a/packages/viewer/src/modules/SpeckleRenderer.ts b/packages/viewer/src/modules/SpeckleRenderer.ts index d82b987d2..a6ce73974 100644 --- a/packages/viewer/src/modules/SpeckleRenderer.ts +++ b/packages/viewer/src/modules/SpeckleRenderer.ts @@ -2,6 +2,7 @@ import { ACESFilmicToneMapping, Box3, Box3Helper, + Camera, CameraHelper, Color, DirectionalLight, @@ -105,6 +106,15 @@ export default class SpeckleRenderer { this.input.on('object-doubleclicked', this.onObjectDoubleClick.bind(this)) } + public update(deltaTime: number) { + this.batcher.update(deltaTime) + } + + public render(camera: Camera) { + this.batcher.render(this.renderer) + this.renderer.render(this.scene, camera) + } + public addRenderTree() { this.batcher.makeBatches(GeometryType.MESH, SpeckleType.Mesh, SpeckleType.Brep) this.batcher.makeBatches( diff --git a/packages/viewer/src/modules/Viewer.ts b/packages/viewer/src/modules/Viewer.ts index 700388da2..3b8406267 100644 --- a/packages/viewer/src/modules/Viewer.ts +++ b/packages/viewer/src/modules/Viewer.ts @@ -23,7 +23,7 @@ export class Viewer extends EventEmitter implements IViewer { private container: HTMLElement private stats: Optional private loaders: { [id: string]: ViewerObjectLoader } = {} - public needsRender: boolean + private _needsRender: boolean private inProgressOperations: number public sectionBox: SectionBox @@ -33,6 +33,14 @@ export class Viewer extends EventEmitter implements IViewer { public static Assets: Assets + public get needsRender(): boolean { + return this._needsRender + } + + public set needsRender(value: boolean) { + this._needsRender = value || this._needsRender + } + private _worldOrigin: Vector3 = new Vector3() public get worldSize() { World.worldBox.getCenter(this._worldOrigin) @@ -83,7 +91,7 @@ export class Viewer extends EventEmitter implements IViewer { this.interactions = new InteractionHandler(this) - this.animate() + this.frame() this.onWindowResize() // this.interactions.zoomExtents() this.needsRender = true @@ -125,32 +133,23 @@ export class Viewer extends EventEmitter implements IViewer { this.needsRender = true } - private animate() { + private frame() { + this.update() + this.render() + } + + private update() { const delta = this.clock.getDelta() - - const hasControlsUpdated = this.cameraHandler.controls.update(delta) - - requestAnimationFrame(this.animate.bind(this)) - - // you can skip this condition to render though - if (hasControlsUpdated || this.needsRender) { - // this.needsRender = false - if (this.stats) this.stats.begin() - this.render() - - const infoDrawsEl = document.getElementById('info-draws') - if (this.stats && infoDrawsEl) { - infoDrawsEl.textContent = '' + this.speckleRenderer.renderer.info.render.calls - } - if (this.stats) this.stats.end() - } + this.needsRender = this.cameraHandler.controls.update(delta) + this.speckleRenderer.update(delta) + this.stats.update() + requestAnimationFrame(this.frame.bind(this)) } private render() { - this.speckleRenderer.renderer.render( - this.speckleRenderer.scene, - this.cameraHandler.activeCam.camera - ) + if (this.needsRender) { + this.speckleRenderer.render(this.cameraHandler.activeCam.camera) + } } public toggleSectionBox() { diff --git a/packages/viewer/src/modules/batching/Batch.ts b/packages/viewer/src/modules/batching/Batch.ts index 391170087..5e55e8143 100644 --- a/packages/viewer/src/modules/batching/Batch.ts +++ b/packages/viewer/src/modules/batching/Batch.ts @@ -1,4 +1,4 @@ -import { Material, Object3D } from 'three' +import { Material, Object3D, WebGLRenderer } from 'three' import { MaterialOptions } from '../materials/Materials' import { NodeRenderView } from '../tree/NodeRenderView' @@ -23,6 +23,8 @@ export interface Batch { resetDrawRanges() buildBatch() getRenderView(index: number): NodeRenderView + onUpdate(deltaTime: number) + onRender(renderer: WebGLRenderer) purge() } diff --git a/packages/viewer/src/modules/batching/Batcher.ts b/packages/viewer/src/modules/batching/Batcher.ts index f2f84fac3..167438635 100644 --- a/packages/viewer/src/modules/batching/Batcher.ts +++ b/packages/viewer/src/modules/batching/Batcher.ts @@ -9,7 +9,7 @@ import { NodeRenderView } from '../tree/NodeRenderView' import { Batch, BatchUpdateRange, GeometryType } from './Batch' import PointBatch from './PointBatch' import { FilterMaterialType } from '../FilteringManager' -import { Material } from 'three' +import { Material, WebGLRenderer } from 'three' import { FilterMaterial } from '../FilteringManager' export default class Batcher { @@ -77,6 +77,18 @@ export default class Batcher { } } + public update(deltaTime: number) { + for (const batchId in this.batches) { + this.batches[batchId].onUpdate(deltaTime) + } + } + + public render(renderer: WebGLRenderer) { + for (const batchId in this.batches) { + this.batches[batchId].onRender(renderer) + } + } + public purgeBatches() { for (const k in this.batches) { this.batches[k].purge() diff --git a/packages/viewer/src/modules/batching/LineBatch.ts b/packages/viewer/src/modules/batching/LineBatch.ts index 021cc39ee..c797df68a 100644 --- a/packages/viewer/src/modules/batching/LineBatch.ts +++ b/packages/viewer/src/modules/batching/LineBatch.ts @@ -6,7 +6,8 @@ import { InterleavedBufferAttribute, Line, Object3D, - Vector4 + Vector4, + WebGLRenderer } from 'three' import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2' import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry' @@ -42,6 +43,14 @@ export default class LineBatch implements Batch { this.batchMaterial = material } + public onUpdate(deltaTime: number) { + deltaTime + } + + public onRender(renderer: WebGLRenderer) { + renderer.getDrawingBufferSize(this.batchMaterial.resolution) + } + public setVisibleRange(...ranges: BatchUpdateRange[]) { const data = this.colorBuffer.array as number[] for (let k = 0; k < data.length; k += 4) { diff --git a/packages/viewer/src/modules/batching/MeshBatch.ts b/packages/viewer/src/modules/batching/MeshBatch.ts index cded0fc4c..824c117b1 100644 --- a/packages/viewer/src/modules/batching/MeshBatch.ts +++ b/packages/viewer/src/modules/batching/MeshBatch.ts @@ -7,7 +7,8 @@ import { Mesh, Object3D, Uint16BufferAttribute, - Uint32BufferAttribute + Uint32BufferAttribute, + WebGLRenderer } from 'three' import { Geometry } from '../converter/Geometry' import SpeckleStandardColoredMaterial from '../materials/SpeckleStandardColoredMaterial' @@ -40,6 +41,14 @@ export default class MeshBatch implements Batch { this.batchMaterial = material } + public onUpdate(deltaTime: number) { + deltaTime + } + + public onRender(renderer: WebGLRenderer) { + renderer + } + public setVisibleRange(...ranges: BatchUpdateRange[]) { if (ranges.length === 1 && ranges[0] === HideAllBatchUpdateRange) { this.geometry.setDrawRange(0, 0) diff --git a/packages/viewer/src/modules/batching/PointBatch.ts b/packages/viewer/src/modules/batching/PointBatch.ts index 7a0175071..38745d4dc 100644 --- a/packages/viewer/src/modules/batching/PointBatch.ts +++ b/packages/viewer/src/modules/batching/PointBatch.ts @@ -3,7 +3,8 @@ import { Float32BufferAttribute, Material, Object3D, - Points + Points, + WebGLRenderer } from 'three' import { NodeRenderView } from '../tree/NodeRenderView' import { World } from '../World' @@ -33,6 +34,14 @@ export default class PointBatch implements Batch { this.batchMaterial = material } + public onUpdate(deltaTime: number) { + deltaTime + } + + public onRender(renderer: WebGLRenderer) { + renderer + } + public setVisibleRange(...ranges: BatchUpdateRange[]) { if (ranges.length === 1 && ranges[0] === HideAllBatchUpdateRange) { this.geometry.setDrawRange(0, 0) diff --git a/packages/viewer/src/modules/materials/Materials.ts b/packages/viewer/src/modules/materials/Materials.ts index 6cc6cc9eb..0c2923d0f 100644 --- a/packages/viewer/src/modules/materials/Materials.ts +++ b/packages/viewer/src/modules/materials/Materials.ts @@ -88,17 +88,14 @@ export default class Materials { worldUnits: false, vertexColors: false, alphaToCoverage: false, - resolution: new Vector2(1281, 1306) + resolution: new Vector2() // clippingPlanes: this.viewer.sectionBox.planes }) ;(this.lineHighlightMaterial).color = new Color(0xff0000) ;(this.lineHighlightMaterial).linewidth = 1 ;(this.lineHighlightMaterial).worldUnits = false ;(this.lineHighlightMaterial).pixelThreshold = 0.5 - ;(this.lineHighlightMaterial).resolution = new Vector2( - 1281, - 1306 - ) + ;(this.lineHighlightMaterial).resolution = new Vector2() this.lineGhostMaterial = new SpeckleLineMaterial({ color: 0x00ff00, @@ -106,17 +103,14 @@ export default class Materials { worldUnits: false, vertexColors: false, alphaToCoverage: false, - resolution: new Vector2(1281, 1306) + resolution: new Vector2() // clippingPlanes: this.viewer.sectionBox.planes }) ;(this.lineHighlightMaterial).color = new Color(0x00ff00) ;(this.lineHighlightMaterial).linewidth = 1 ;(this.lineHighlightMaterial).worldUnits = false ;(this.lineHighlightMaterial).pixelThreshold = 0.5 - ;(this.lineHighlightMaterial).resolution = new Vector2( - 1281, - 1306 - ) + ;(this.lineHighlightMaterial).resolution = new Vector2() this.lineColoredMaterial = new SpeckleLineMaterial({ color: 0xffffff, @@ -124,17 +118,14 @@ export default class Materials { worldUnits: false, vertexColors: false, alphaToCoverage: false, - resolution: new Vector2(1281, 1306) + resolution: new Vector2() // clippingPlanes: this.viewer.sectionBox.planes }) ;(this.lineHighlightMaterial).color = new Color(0xffffff) ;(this.lineHighlightMaterial).linewidth = 1 ;(this.lineHighlightMaterial).worldUnits = false ;(this.lineHighlightMaterial).pixelThreshold = 0.5 - ;(this.lineHighlightMaterial).resolution = new Vector2( - 1281, - 1306 - ) + ;(this.lineHighlightMaterial).resolution = new Vector2() this.pointCloudHighlightMaterial = new SpecklePointMaterial({ color: 0xff0000, @@ -229,14 +220,14 @@ export default class Materials { worldUnits: false, vertexColors: false, alphaToCoverage: false, - resolution: new Vector2(1281, 1306) + resolution: new Vector2() // clippingPlanes: this.viewer.sectionBox.planes }) ;(this.materialMap[hash]).color = new Color(0xff00ff) ;(this.materialMap[hash]).linewidth = 1 ;(this.materialMap[hash]).worldUnits = false ;(this.materialMap[hash]).pixelThreshold = 0.5 - ;(this.materialMap[hash]).resolution = new Vector2(1281, 1306) + ;(this.materialMap[hash]).resolution = new Vector2() this.materialMap[NodeRenderView.NullPointMaterialHash] = new SpecklePointMaterial({ color: 0x7f7f7f, @@ -281,14 +272,14 @@ export default class Materials { worldUnits: materialData.lineWeight > 0 ? true : false, vertexColors: true, alphaToCoverage: false, - resolution: new Vector2(1281, 1306) + resolution: new Vector2() }) mat.color = new Color(materialData.color) mat.linewidth = materialData.lineWeight > 0 ? materialData.lineWeight : 1 mat.worldUnits = materialData.lineWeight > 0 ? true : false mat.vertexColors = true mat.pixelThreshold = 0.5 - mat.resolution = new Vector2(1281, 1306) + mat.resolution = new Vector2() return mat } @@ -397,14 +388,14 @@ export default class Materials { worldUnits: false, vertexColors: true, alphaToCoverage: false, - resolution: new Vector2(1281, 1306) + resolution: new Vector2() }) mat.color = color mat.linewidth = 1 mat.worldUnits = false mat.vertexColors = true mat.pixelThreshold = 0.5 - mat.resolution = new Vector2(1281, 1306) + mat.resolution = new Vector2() return mat } case GeometryType.POINT: diff --git a/packages/viewer/src/modules/materials/SpeckleLineMaterial.ts b/packages/viewer/src/modules/materials/SpeckleLineMaterial.ts index 54a58b2a1..847342a36 100644 --- a/packages/viewer/src/modules/materials/SpeckleLineMaterial.ts +++ b/packages/viewer/src/modules/materials/SpeckleLineMaterial.ts @@ -3,7 +3,7 @@ /* eslint-disable camelcase */ import { speckleLineVert } from './shaders/speckle-line-vert' import { speckleLineFrag } from './shaders/speckle-line-frag' -import { UniformsUtils, ShaderLib, Vector3, Vector2 } from 'three' +import { UniformsUtils, ShaderLib, Vector3 } from 'three' import { Matrix4 } from 'three' import { Geometry } from '../converter/Geometry' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js' @@ -13,7 +13,7 @@ class SpeckleLineMaterial extends LineMaterial { private static readonly vecBuff0: Vector3 = new Vector3() private static readonly vecBuff1: Vector3 = new Vector3() private static readonly vecBuff2: Vector3 = new Vector3() - private static readonly vecBuff3: Vector2 = new Vector2() + public set pixelThreshold(value: number) { this.userData.pixelThreshold.value = value this.needsUpdate = true @@ -100,8 +100,6 @@ class SpeckleLineMaterial extends LineMaterial { ) this.userData.uViewer_low.value.copy(SpeckleLineMaterial.vecBuff1) this.userData.uViewer_high.value.copy(SpeckleLineMaterial.vecBuff2) - _this.getDrawingBufferSize(SpeckleLineMaterial.vecBuff3) - this.resolution.copy(SpeckleLineMaterial.vecBuff3) this.needsUpdate = true } }