diff --git a/packages/frontend/src/main/components/viewer/CommentAddOverlay.vue b/packages/frontend/src/main/components/viewer/CommentAddOverlay.vue index f2cc32dfe..5faf3188d 100644 --- a/packages/frontend/src/main/components/viewer/CommentAddOverlay.vue +++ b/packages/frontend/src/main/components/viewer/CommentAddOverlay.vue @@ -509,7 +509,7 @@ export default { updateCommentBubble() { if (!this.location) return if (!this.$refs.commentButton) return - const cam = this.viewer.cameraHandler.camera + const cam = this.viewer.cameraHandler.activeCam.camera cam.updateProjectionMatrix() const projectedLocation = this.location.clone() projectedLocation.project(cam) diff --git a/packages/frontend/src/main/components/viewer/CommentsOverlay.vue b/packages/frontend/src/main/components/viewer/CommentsOverlay.vue index d02597332..22c515c8e 100644 --- a/packages/frontend/src/main/components/viewer/CommentsOverlay.vue +++ b/packages/frontend/src/main/components/viewer/CommentsOverlay.vue @@ -565,7 +565,7 @@ export default { }, updateCommentBubbles() { if (!this.comments) return - const cam = this.viewer.cameraHandler.camera + const cam = this.viewer.cameraHandler.activeCam.camera cam.updateProjectionMatrix() for (const comment of this.localComments) { // get html elements diff --git a/packages/frontend/src/main/components/viewer/ViewerControls.vue b/packages/frontend/src/main/components/viewer/ViewerControls.vue index 75d5c5e3f..aed11ef3c 100644 --- a/packages/frontend/src/main/components/viewer/ViewerControls.vue +++ b/packages/frontend/src/main/components/viewer/ViewerControls.vue @@ -30,8 +30,8 @@ - + eventHub.$emit('resize-viewer'), 300) + setTimeout(() => { + // @Dim: Why are we resizing the viewer here? We generally want to avoid needless resizes + eventHub.$emit('resize-viewer') + }, 300) } // Setup resize events diff --git a/packages/viewer/src/modules/SpeckleRenderer.ts b/packages/viewer/src/modules/SpeckleRenderer.ts index 6bf9a3423..cdbe84cb7 100644 --- a/packages/viewer/src/modules/SpeckleRenderer.ts +++ b/packages/viewer/src/modules/SpeckleRenderer.ts @@ -395,7 +395,6 @@ export default class SpeckleRenderer { if (this._needsRender) { this.batcher.render(this.renderer) this._needsRender = this.pipeline.render() - // this.renderer.render(this.scene, this.viewer.cameraHandler.activeCam.camera) // this._needsRender = true } diff --git a/packages/viewer/src/modules/Viewer.ts b/packages/viewer/src/modules/Viewer.ts index ff5393f68..d88bd1cd2 100644 --- a/packages/viewer/src/modules/Viewer.ts +++ b/packages/viewer/src/modules/Viewer.ts @@ -330,7 +330,7 @@ export class Viewer extends EventEmitter implements IViewer { public toggleCameraProjection() { this.cameraHandler.toggleCameras() - this.speckleRenderer.resetPipeline() + this.speckleRenderer.resetPipeline(true) } public setLightConfiguration(config: SunLightConfiguration): void { diff --git a/packages/viewer/src/modules/context/CameraHanlder.js b/packages/viewer/src/modules/context/CameraHanlder.js index e1b7b935b..5bb0a7720 100644 --- a/packages/viewer/src/modules/context/CameraHanlder.js +++ b/packages/viewer/src/modules/context/CameraHanlder.js @@ -291,13 +291,26 @@ export default class CameraHandler { this.viewer.container.offsetWidth / this.viewer.container.offsetHeight this.camera.updateProjectionMatrix() - const aspect = - this.viewer.container.offsetWidth / this.viewer.container.offsetHeight - const fustrumSize = 50 - this.orthoCamera.left = (-fustrumSize * aspect) / 2 - this.orthoCamera.right = (fustrumSize * aspect) / 2 - this.orthoCamera.top = fustrumSize / 2 - this.orthoCamera.bottom = -fustrumSize / 2 + const lineOfSight = new THREE.Vector3() + this.camera.getWorldDirection(lineOfSight) + const target = new THREE.Vector3() + this.controls.getTarget(target) + const distance = target.clone().sub(this.camera.position) + const depth = distance.dot(lineOfSight) + const dims = { + x: this.viewer.container.offsetWidth, + y: this.viewer.container.offsetHeight + } + const aspect = dims.x / dims.y + const fov = this.camera.fov + const height = depth * 2 * Math.atan((fov * (Math.PI / 180)) / 2) + const width = height * aspect + + this.orthoCamera.zoom = 1 + this.orthoCamera.left = width / -2 + this.orthoCamera.right = width / 2 + this.orthoCamera.top = height / 2 + this.orthoCamera.bottom = height / -2 this.orthoCamera.updateProjectionMatrix() } diff --git a/packages/viewer/src/modules/objects/SpeckleCameraControls.ts b/packages/viewer/src/modules/objects/SpeckleCameraControls.ts index 2a93f4988..d7b60a09c 100644 --- a/packages/viewer/src/modules/objects/SpeckleCameraControls.ts +++ b/packages/viewer/src/modules/objects/SpeckleCameraControls.ts @@ -44,7 +44,9 @@ export class SpeckleCameraControls extends CameraControls { private _didDollyLastFrame = false public _isTrucking = false private _hasRestedLastFrame = false + private _didZoom = false private overrideDollyLerpRatio = 0 + private overrideZoomLerpRatio = 0 static install() { _v3A = new Vector3() _v3B = new Vector3() @@ -101,7 +103,7 @@ export class SpeckleCameraControls extends CameraControls { const zoomScale = Math.pow(0.95, delta * this.dollySpeed) // for both PerspectiveCamera and OrthographicCamera - this.zoomTo(this._zoom * zoomScale) + this.zoomTo(this._zoom * zoomScale, false, 1) this._didDolly = true this.dispatchEvent({ type: 'controlstart' }) if (this.dollyToCursor) { @@ -113,6 +115,30 @@ export class SpeckleCameraControls extends CameraControls { return } + /** + * Zoom in/out camera to given scale. The value overwrites camera zoom. + * Limits set with .minZoom and .maxZoom + * @param zoom + * @param enableTransition + * @category Methods + */ + zoomTo( + zoom: number, + enableTransition = false, + lerpRatio: number = undefined + ): Promise { + this._zoomEnd = MathUtils.clamp(zoom, this.minZoom, this.maxZoom) + this._needsUpdate = true + this.overrideZoomLerpRatio = enableTransition ? 0.05 : lerpRatio + if (!enableTransition) { + this._zoom = this._zoomEnd + } + + const resolveImmediately = + !enableTransition || approxEquals(this._zoom, this._zoomEnd, this.restThreshold) + return this._createOnRestPromise(resolveImmediately) + } + /** * Dolly in/out camera position to given distance. * @param distance Distance of dolly. @@ -282,13 +308,22 @@ export class SpeckleCameraControls extends CameraControls { ) } const zoomDelta = this._zoomEnd - this._zoom - this._zoom += zoomDelta * lerpRatio + this._zoom += + zoomDelta * + (this.overrideZoomLerpRatio + ? this.overrideZoomLerpRatio + : this.overrideZoomLerpRatio) if (this._camera.zoom !== this._zoom) { - if (approxZero(zoomDelta)) this._zoom = this._zoomEnd + if (approxZero(zoomDelta)) { + this._zoom = this._zoomEnd + } this._camera.zoom = this._zoom this._camera.updateProjectionMatrix() this._updateNearPlaneCorners() this._needsUpdate = true + this._didZoom = true + } else { + this._didZoom = false } const updated = this._needsUpdate if (updated && !this._updatedLastTime) { @@ -308,7 +343,8 @@ export class SpeckleCameraControls extends CameraControls { approxZero(deltaOffset.y, this.restThreshold) && approxZero(deltaOffset.z, this.restThreshold) && !this._hasRested && - !this._isTrucking + !this._isTrucking && + !this._didZoom ) { this._hasRested = true this.dispatchEvent({ type: 'rest' }) @@ -327,7 +363,8 @@ export class SpeckleCameraControls extends CameraControls { approxZero(deltaOffset.x, this.restThreshold) && approxZero(deltaOffset.y, this.restThreshold) && approxZero(deltaOffset.z, this.restThreshold) && - !this._isTrucking + !this._isTrucking && + !this._didZoom ) { this.dispatchEvent({ type: 'rest' }) this._didDollyLastFrame = false