diff --git a/packages/viewer-sandbox/src/Sandbox.ts b/packages/viewer-sandbox/src/Sandbox.ts index d448a8f2a9..8f973390ee 100644 --- a/packages/viewer-sandbox/src/Sandbox.ts +++ b/packages/viewer-sandbox/src/Sandbox.ts @@ -14,7 +14,8 @@ import { SpeckleLoader, ObjLoader, UrlHelper, - LoaderEvent + LoaderEvent, + UpdateFlags } from '@speckle/viewer' import { FolderApi, Pane } from 'tweakpane' import { DiffResult } from '@speckle/viewer' @@ -24,7 +25,6 @@ import { SelectionExtension } from '@speckle/viewer' import { FilteringExtension } from '@speckle/viewer' import { MeasurementsExtension } from '@speckle/viewer' import { CameraController } from '@speckle/viewer' -import { UpdateFlags } from '@speckle/viewer' import { AssetType, Assets } from '@speckle/viewer' import Neutral from '../assets/hdri/Neutral.png' import Mild from '../assets/hdri/Mild.png' @@ -297,12 +297,12 @@ export default class Sandbox { // }) // const origin = unionBox.getCenter(new Vector3()) objects.forEach((obj: BatchObject) => { - // obj.transformTRS(position.value, rotation.value, scale.value, origin) - obj.position = new Vector3( - position.value.x, - position.value.y, - position.value.z - ) + obj.transformTRS(position.value) + // obj.position = new Vector3( + // position.value.x, + // position.value.y, + // position.value.z + // ) }) this.viewer.requestRender() }) @@ -487,7 +487,7 @@ export default class Sandbox { this.viewer .getExtension(CameraController) .setCameraView({ azimuth: Math.PI / 12, polar: 0 }, false) - this.viewer.getRenderer().resetPipeline() + this.viewer.requestRender(UpdateFlags.RENDER_RESET) await waitForAnimation(1000) } }) diff --git a/packages/viewer/src/IViewer.ts b/packages/viewer/src/IViewer.ts index 0ba87a72b3..3c0f149e0f 100644 --- a/packages/viewer/src/IViewer.ts +++ b/packages/viewer/src/IViewer.ts @@ -150,7 +150,8 @@ export enum ObjectLayers { export enum UpdateFlags { RENDER = 0b1, SHADOWS = 0b10, - CLIPPING_PLANES = 0b100 + CLIPPING_PLANES = 0b100, + RENDER_RESET = 0b1000 } export interface MaterialOptions { diff --git a/packages/viewer/src/modules/SpeckleRenderer.ts b/packages/viewer/src/modules/SpeckleRenderer.ts index ff7f90fdf5..577585639e 100644 --- a/packages/viewer/src/modules/SpeckleRenderer.ts +++ b/packages/viewer/src/modules/SpeckleRenderer.ts @@ -186,6 +186,9 @@ export default class SpeckleRenderer { public set clippingPlanes(value: Plane[]) { this._clippingPlanes = value.map((value: Plane) => new Plane().copy(value)) this.updateClippingPlanes() + this.renderer.shadowMap.needsUpdate = true + this.needsRender = true + this.resetPipeline() } /**************** @@ -521,7 +524,6 @@ export default class SpeckleRenderer { public resetPipeline() { this._needsRender = true this.pipeline.reset() - // if (force) this.pipeline.reset() } public render(): void { @@ -829,8 +831,6 @@ export default class SpeckleRenderer { }) this.pipeline.updateClippingPlanes(planes) this._shadowcatcher?.updateClippingPlanes(planes) - this.renderer.shadowMap.needsUpdate = true - this.resetPipeline() } public updateShadowCatcher() { @@ -842,7 +842,7 @@ export default class SpeckleRenderer { this.clippingVolume, this._renderer.capabilities.maxTextureSize ) - this.resetPipeline() + this.needsRender = true } } diff --git a/packages/viewer/src/modules/Viewer.ts b/packages/viewer/src/modules/Viewer.ts index b0b24ed860..4333a8ded7 100644 --- a/packages/viewer/src/modules/Viewer.ts +++ b/packages/viewer/src/modules/Viewer.ts @@ -186,7 +186,6 @@ export class Viewer extends EventEmitter implements IViewer { public requestRender(flags: UpdateFlags = UpdateFlags.RENDER) { if (flags & UpdateFlags.RENDER) { this.speckleRenderer.needsRender = true - this.speckleRenderer.resetPipeline() } if (flags & UpdateFlags.SHADOWS) { this.speckleRenderer.shadowMapNeedsUpdate = true @@ -194,6 +193,10 @@ export class Viewer extends EventEmitter implements IViewer { if (flags & UpdateFlags.CLIPPING_PLANES) { this.speckleRenderer.updateClippingPlanes() } + if (flags & UpdateFlags.RENDER_RESET) { + this.speckleRenderer.needsRender = true + this.speckleRenderer.resetPipeline() + } } private frame() { @@ -331,8 +334,7 @@ export class Viewer extends EventEmitter implements IViewer { } Logger.log(this.getRenderer().renderingStats) Logger.log('ASYNC batch build time -> ', performance.now() - t0) - this.requestRender(UpdateFlags.RENDER | UpdateFlags.SHADOWS) - this.speckleRenderer.resetPipeline() + this.requestRender(UpdateFlags.RENDER_RESET | UpdateFlags.SHADOWS) this.emit(ViewerEvent.LoadComplete, loader.resource) } diff --git a/packages/viewer/src/modules/extensions/ExplodeExtension.ts b/packages/viewer/src/modules/extensions/ExplodeExtension.ts index 67f8acd2a0..229bfd97da 100644 --- a/packages/viewer/src/modules/extensions/ExplodeExtension.ts +++ b/packages/viewer/src/modules/extensions/ExplodeExtension.ts @@ -39,6 +39,6 @@ export class ExplodeExtension extends Extension { objects[i].transformTRS(dir, undefined, undefined, undefined) } - this.viewer.requestRender(UpdateFlags.RENDER | UpdateFlags.SHADOWS) + this.viewer.requestRender(UpdateFlags.RENDER_RESET | UpdateFlags.SHADOWS) } } diff --git a/packages/viewer/src/modules/extensions/SectionTool.ts b/packages/viewer/src/modules/extensions/SectionTool.ts index 7e5ea75858..cecf46c34f 100644 --- a/packages/viewer/src/modules/extensions/SectionTool.ts +++ b/packages/viewer/src/modules/extensions/SectionTool.ts @@ -230,53 +230,56 @@ export class SectionTool extends Extension { private _draggingChangeHandler() { if (!this.display.visible) return + this.boxGeometry.computeBoundingBox() this.boxMeshHelper.box.copy(this.boxGeometry.boundingBox || new Box3()) - // Dragging a side / plane - if (this.dragging && this.currentRange) { - this._generateOrUpdatePlanes() - if (this.prevPosition === null) + if (this.dragging) { + // Dragging a side / plane + if (this.currentRange) { + this._generateOrUpdatePlanes() + if (this.prevPosition === null) + this.prevPosition = this.hoverPlane.position.clone() + this.prevPosition.sub(this.hoverPlane.position) + this.prevPosition.negate() + const boxArr = this.boxGeometry.attributes.position.array as number[] + for (let i = 0; i < this.currentRange.length; i++) { + const index = this.currentRange[i] + boxArr[3 * index] += this.prevPosition.x + boxArr[3 * index + 1] += this.prevPosition.y + boxArr[3 * index + 2] += this.prevPosition.z + } + this.prevPosition = this.hoverPlane.position.clone() - this.prevPosition.sub(this.hoverPlane.position) - this.prevPosition.negate() - const boxArr = this.boxGeometry.attributes.position.array as number[] - for (let i = 0; i < this.currentRange.length; i++) { - const index = this.currentRange[i] - boxArr[3 * index] += this.prevPosition.x - boxArr[3 * index + 1] += this.prevPosition.y - boxArr[3 * index + 2] += this.prevPosition.z + this.boxGeometry.attributes.position.needsUpdate = true + this.boxGeometry.computeVertexNormals() + this.boxGeometry.computeBoundingBox() + this.boxGeometry.computeBoundingSphere() } - this.prevPosition = this.hoverPlane.position.clone() - this.boxGeometry.attributes.position.needsUpdate = true - this.boxGeometry.computeVertexNormals() - this.boxGeometry.computeBoundingBox() - this.boxGeometry.computeBoundingSphere() - } - - // Dragging the whole section box - if (this.dragging && !this.currentRange) { - this._generateOrUpdatePlanes() - if (this.prevPosition === null) this.prevPosition = this.sphere.position.clone() - this.prevPosition.sub(this.sphere.position) - this.prevPosition.negate() - const verts = this.boxGeometry.attributes.position.array as number[] - for (let i = 0; i < verts.length; i += 3) { - verts[i] += this.prevPosition.x - verts[i + 1] += this.prevPosition.y - verts[i + 2] += this.prevPosition.z + // Dragging the whole section box. This legacy bit seems to never happen ¯\_(ツ)_/¯ + else { + this._generateOrUpdatePlanes() + if (this.prevPosition === null) this.prevPosition = this.sphere.position.clone() + this.prevPosition.sub(this.sphere.position) + this.prevPosition.negate() + const verts = this.boxGeometry.attributes.position.array as number[] + for (let i = 0; i < verts.length; i += 3) { + verts[i] += this.prevPosition.x + verts[i + 1] += this.prevPosition.y + verts[i + 2] += this.prevPosition.z + } + this.boxGeometry.attributes.position.needsUpdate = true + this.boxGeometry.computeVertexNormals() + this.boxGeometry.computeBoundingBox() + this.boxGeometry.computeBoundingSphere() + + this.prevPosition = this.sphere.position.clone() } - this.boxGeometry.attributes.position.needsUpdate = true - this.boxGeometry.computeVertexNormals() - this.boxGeometry.computeBoundingBox() - this.boxGeometry.computeBoundingSphere() - - this.prevPosition = this.sphere.position.clone() + this.viewer.getRenderer().clippingPlanes = this.planes + this.viewer.getRenderer().clippingVolume = this.getBox() + this.emit(SectionToolEvent.Updated, this.planes) } - this.viewer.getRenderer().clippingPlanes = this.planes - this.viewer.getRenderer().clippingVolume = this.getBox() - this.emit(SectionToolEvent.Updated, this.planes) this.viewer.requestRender() } diff --git a/packages/viewer/src/modules/extensions/measurements/MeasurementsExtension.ts b/packages/viewer/src/modules/extensions/measurements/MeasurementsExtension.ts index b29e1f06d4..63bdb49171 100644 --- a/packages/viewer/src/modules/extensions/measurements/MeasurementsExtension.ts +++ b/packages/viewer/src/modules/extensions/measurements/MeasurementsExtension.ts @@ -66,8 +66,7 @@ export class MeasurementsExtension extends Extension { this._activeMeasurement.update() if (!value) this.cancelMeasurement() } - this.renderer.needsRender = true - this.renderer.resetPipeline() + this.viewer.requestRender() } public get options(): MeasurementOptions { @@ -183,8 +182,7 @@ export class MeasurementsExtension extends Extension { } this._activeMeasurement.update() - this.renderer.needsRender = true - this.renderer.resetPipeline() + this.viewer.requestRender() this._frameLock = true this._sceneHit = true // console.log('Time -> ', performance.now() - start) @@ -309,8 +307,7 @@ export class MeasurementsExtension extends Extension { protected cancelMeasurement() { if (this._activeMeasurement) this.renderer.scene.remove(this._activeMeasurement) this._activeMeasurement = null - this.renderer.needsRender = true - this.renderer.resetPipeline() + this.viewer.requestRender() } protected finishMeasurement() { @@ -332,8 +329,7 @@ export class MeasurementsExtension extends Extension { this.measurements.splice(this.measurements.indexOf(this._selectedMeasurement), 1) this.renderer.scene.remove(this._selectedMeasurement) this._selectedMeasurement = null - this.renderer.needsRender = true - this.renderer.resetPipeline() + this.viewer.requestRender() } else { this.cancelMeasurement() } @@ -357,8 +353,7 @@ export class MeasurementsExtension extends Extension { if (flashCount >= maxFlashCount) { clearInterval(handle) } - this.renderer.needsRender = true - this.renderer.resetPipeline() + this.viewer.requestRender() } }, 100) } @@ -446,8 +441,7 @@ export class MeasurementsExtension extends Extension { if (this._options.visible) this.raycaster.layers.enable(ObjectLayers.MEASUREMENTS) else this.raycaster.layers.disable(ObjectLayers.MEASUREMENTS) - this.renderer.needsRender = true - this.renderer.resetPipeline() + this.viewer.requestRender() } public fromMeasurementData(startPoint: Vector3, endPoint: Vector3) { diff --git a/packages/viewer/src/modules/pipeline/Pipeline.ts b/packages/viewer/src/modules/pipeline/Pipeline.ts index 8d48202647..8ffd182538 100644 --- a/packages/viewer/src/modules/pipeline/Pipeline.ts +++ b/packages/viewer/src/modules/pipeline/Pipeline.ts @@ -62,8 +62,6 @@ export class Pipeline { private _renderer: WebGLRenderer private _batcher: Batcher private _pipelineOptions: PipelineOptions = Object.assign({}, DefaultPipelineOptions) - private _needsProgressive = false - private _resetFrame = false private _composer: EffectComposer private depthPass: DepthPass @@ -89,12 +87,13 @@ export class Pipeline { this.dynamicAoPass.setParams(options.dynamicAoParams) this.staticAoPass.setParams(options.staticAoParams) this.accumulationFrame = 0 - if (options.depthSide) this.depthPass.depthSide = options.depthSide - if (options.accumulationFrames) { + if (options.depthSide !== undefined) this.depthPass.depthSide = options.depthSide + if (options.accumulationFrames !== undefined) { this.applySaoPass.setAccumulationFrames(options.accumulationFrames) this.staticAoPass.setAccumulationFrames(options.accumulationFrames) } - if (options.pipelineOutput) this.pipelineOutput = options.pipelineOutput + if (options.pipelineOutput !== undefined) + this.pipelineOutput = options.pipelineOutput } public get pipelineOptions(): PipelineOptions { @@ -110,7 +109,6 @@ export class Pipeline { this.depthPass.depthSize = DepthSize.FULL this.applySaoPass.setTexture('tDiffuse', this.staticAoPass.outputTexture) this.applySaoPass.setTexture('tDiffuseInterp', this.dynamicAoPass.outputTexture) - this.needsProgressive = true break case PipelineOutputType.DEPTH_RGBA: @@ -119,7 +117,6 @@ export class Pipeline { this.depthPass.depthSize = DepthSize.FULL this.copyOutputPass.setTexture('tDiffuse', this.depthPass.outputTexture) this.copyOutputPass.setOutputType(PipelineOutputType.DEPTH_RGBA) - this.needsProgressive = false break case PipelineOutputType.DEPTH: @@ -128,7 +125,6 @@ export class Pipeline { this.depthPass.depthSize = DepthSize.FULL this.copyOutputPass.setTexture('tDiffuse', this.depthPass.outputTexture) this.copyOutputPass.setOutputType(PipelineOutputType.DEPTH) - this.needsProgressive = false break case PipelineOutputType.COLOR: @@ -141,7 +137,6 @@ export class Pipeline { this.normalsPass.enabled = true this.copyOutputPass.setTexture('tDiffuse', this.normalsPass.outputTexture) this.copyOutputPass.setOutputType(PipelineOutputType.GEOMETRY_NORMALS) - this.needsProgressive = false break case PipelineOutputType.RECONSTRUCTED_NORMALS: @@ -154,7 +149,6 @@ export class Pipeline { this.dynamicAoPass.setOutputType(DynamicAOOutputType.RECONSTRUCTED_NORMALS) this.copyOutputPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) this.copyOutputPass.setOutputType(PipelineOutputType.GEOMETRY_NORMALS) - this.needsProgressive = false break case PipelineOutputType.DYNAMIC_AO: @@ -171,7 +165,6 @@ export class Pipeline { this.copyOutputPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) this.copyOutputPass.setOutputType(PipelineOutputType.COLOR) this.dynamicAoPass.setOutputType(DynamicAOOutputType.AO) - this.needsProgressive = false break case PipelineOutputType.DYNAMIC_AO_BLURED: @@ -189,7 +182,6 @@ export class Pipeline { this.copyOutputPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) this.copyOutputPass.setOutputType(PipelineOutputType.COLOR) this.dynamicAoPass.setOutputType(DynamicAOOutputType.AO_BLURRED) - this.needsProgressive = false break case PipelineOutputType.PROGRESSIVE_AO: @@ -202,7 +194,6 @@ export class Pipeline { this.depthPass.depthSize = DepthSize.FULL this.copyOutputPass.setTexture('tDiffuse', this.staticAoPass.outputTexture) this.copyOutputPass.setOutputType(PipelineOutputType.COLOR) - this.needsProgressive = true break default: break @@ -210,14 +201,6 @@ export class Pipeline { this.setPipeline(pipeline) } - public set needsProgressive(value: boolean) { - this._needsProgressive = value - // if (!value) this._renderType = RenderType.NORMAL - // if (value && this._renderType === RenderType.NORMAL) - // this._renderType = RenderType.ACCUMULATION - this.accumulationFrame = 0 - } - public get needsAccumulation() { return ( this._renderType === RenderType.ACCUMULATION && @@ -375,7 +358,6 @@ export class Pipeline { pipeline.push(this.applySaoPass) pipeline.push(this.overlayPass) - // this.needsProgressive = true return pipeline } @@ -398,7 +380,7 @@ export class Pipeline { } public reset() { - this._resetFrame = true + this.accumulationFrame = 0 this.onStationaryEnd() } @@ -427,20 +409,15 @@ export class Pipeline { let retVal = false this._renderer.clear(true) + this._composer.render() + if (this._renderType === RenderType.NORMAL) { - this._composer.render() - const ret = false || this._resetFrame - if (this._resetFrame) { - this._resetFrame = false - /** This might not be needed */ + if (this.accumulationFrame < this._pipelineOptions.accumulationFrames) this.onStationaryBegin() - } - retVal = ret - } else { - // console.warn('Rendering accumulation frame -> ', this.accumulationFrame) - this._composer.render() + } else if (this._renderType === RenderType.ACCUMULATION) { this.accumulationFrame++ retVal = this.needsAccumulation + if (!retVal) this.onAccumulationComplete() } if (this.onAfterPipelineRender) this.onAfterPipelineRender() @@ -453,11 +430,6 @@ export class Pipeline { } public onStationaryBegin() { - if (!this._needsProgressive) return - if (this._renderType === RenderType.ACCUMULATION) { - this.accumulationFrame = 0 - return - } this._renderType = RenderType.ACCUMULATION this.accumulationFrame = 0 this.depthPass.enabled = true @@ -474,8 +446,6 @@ export class Pipeline { } public onStationaryEnd() { - if (!this._needsProgressive) return - if (this._renderType === RenderType.NORMAL) return this.accumulationFrame = 0 this._renderType = RenderType.NORMAL this.depthPass.depthType = DepthType.PERSPECTIVE_DEPTH @@ -486,4 +456,15 @@ export class Pipeline { this.applySaoPass.setTexture('tDiffuse', this.dynamicAoPass.outputTexture) this.applySaoPass.setRenderType(this._renderType) } + + protected onAccumulationComplete() { + this._renderType = RenderType.NORMAL + this.depthPass.depthType = DepthType.PERSPECTIVE_DEPTH + this.depthPass.depthSize = DepthSize.HALF + this.staticAoPass.enabled = false + this.applySaoPass.enabled = true + this.dynamicAoPass.enabled = true + this.applySaoPass.setTexture('tDiffuse', this.staticAoPass.outputTexture) + this.applySaoPass.setRenderType(this._renderType) + } }