From a52bb75414c79113d7603220ff19911670ebd1d0 Mon Sep 17 00:00:00 2001 From: Alexandru Popovici Date: Fri, 16 Jun 2023 15:55:27 +0300 Subject: [PATCH] Fixed the issues in #1611. There is still an issue left, where zooming in in orthographic mode, then switching to perspective does not yield the correct camera distance, especially when the controls target is off model (#1616) --- packages/viewer-sandbox/src/main.ts | 5 ++-- packages/viewer/src/IViewer.ts | 10 +++++-- .../viewer/src/modules/SpeckleRenderer.ts | 19 +++++++++++--- packages/viewer/src/modules/Viewer.ts | 15 ++++++++--- .../src/modules/context/CameraHanlder.js | 26 +++++++++---------- .../modules/objects/SpeckleCameraControls.ts | 5 ++++ 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/packages/viewer-sandbox/src/main.ts b/packages/viewer-sandbox/src/main.ts index 08c66aab3..576fcf059 100644 --- a/packages/viewer-sandbox/src/main.ts +++ b/packages/viewer-sandbox/src/main.ts @@ -109,7 +109,7 @@ const getStream = () => { // prettier-ignore // 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8?c=%5B-7.66134,10.82932,6.41935,-0.07739,-13.88552,1.8697,0,1%5D' // Revit sample house (good for bim-like stuff with many display meshes) - // 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8' + 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8' // 'https://latest.speckle.dev/streams/c1faab5c62/commits/6c6e43e5f3' // 'https://latest.speckle.dev/streams/58b5648c4d/commits/60371ecb2d' // 'Super' heavy revit shit @@ -270,10 +270,11 @@ const getStream = () => { // 'https://latest.speckle.dev/streams/c1faab5c62/objects/d3466547df9df86397eb4dff7ac9713f' // 'https://latest.speckle.dev/streams/c1faab5c62/commits/140c443886' // 'https://latest.speckle.dev/streams/e258b0e8db/commits/108971810d' + // 'https://latest.speckle.dev/streams/e258b0e8db/objects/3fcd63d80cf791c3f554a795846e62f6' // 'https://latest.speckle.dev/streams/55cc1cbf0a/objects/d7ae178fb6a7b1f599a177486e14f9a6' // 'https://latest.speckle.dev/streams/e258b0e8db/objects/3fcd63d80cf791c3f554a795846e62f6' // 'https://latest.speckle.dev/streams/92b620fb17/commits/6adbcfa8dc' - 'https://latest.speckle.dev/streams/92b620fb17/commits/6adbcfa8dc' + // 'https://latest.speckle.dev/streams/92b620fb17/commits/6adbcfa8dc' ) } diff --git a/packages/viewer/src/IViewer.ts b/packages/viewer/src/IViewer.ts index 7ed4be38b..84e4c48e3 100644 --- a/packages/viewer/src/IViewer.ts +++ b/packages/viewer/src/IViewer.ts @@ -164,12 +164,18 @@ export interface IViewer { transition?: boolean ) - loadObject(url: string, token?: string, enableCaching?: boolean): Promise + loadObject( + url: string, + token?: string, + enableCaching?: boolean, + zoomToObject?: boolean + ): Promise loadObjectAsync( url: string, token?: string, enableCaching?: boolean, - priority?: number + priority?: number, + zoomToObject?: boolean ): Promise cancelLoad(url: string, unload?: boolean): Promise unloadObject(url: string): Promise diff --git a/packages/viewer/src/modules/SpeckleRenderer.ts b/packages/viewer/src/modules/SpeckleRenderer.ts index 5bc63b596..9bf316ebb 100644 --- a/packages/viewer/src/modules/SpeckleRenderer.ts +++ b/packages/viewer/src/modules/SpeckleRenderer.ts @@ -520,7 +520,11 @@ export default class SpeckleRenderer { this._needsRender = true } - public async addRenderTreeAsync(subtreeId: string, priority = 1) { + public async addRenderTreeAsync( + subtreeId: string, + priority = 1, + zoomToObject = true + ) { this.cancel[subtreeId] = false const subtreeGroup = new Group() subtreeGroup.name = subtreeId @@ -537,11 +541,9 @@ export default class SpeckleRenderer { if (!batch) continue this.addBatch(batch, subtreeGroup) - this.zoom() + if (zoomToObject) this.zoom() if (batch.geometryType === GeometryType.MESH) { this.updateDirectLights() - /** Updating the shadowcatcher after each batch is a bit too much. Stalls a lot */ - // this.updateShadowCatcher() } this._needsRender = true if (this.cancel[subtreeId]) { @@ -1176,6 +1178,7 @@ export default class SpeckleRenderer { view.view.target['z'], transition ) + this.viewer.cameraHandler.enableRotations() } /** @@ -1191,12 +1194,14 @@ export default class SpeckleRenderer { switch (side) { case 'front': + this.zoomExtents() this.viewer.cameraHandler.controls.rotateTo(0, DEG90, transition) if (this.viewer.cameraHandler.activeCam.name === 'ortho') this.viewer.cameraHandler.disableRotations() break case 'back': + this.zoomExtents() this.viewer.cameraHandler.controls.rotateTo(DEG180, DEG90, transition) if (this.viewer.cameraHandler.activeCam.name === 'ortho') this.viewer.cameraHandler.disableRotations() @@ -1204,6 +1209,7 @@ export default class SpeckleRenderer { case 'up': case 'top': + this.zoomExtents() this.viewer.cameraHandler.controls.rotateTo(0, 0, transition) if (this.viewer.cameraHandler.activeCam.name === 'ortho') this.viewer.cameraHandler.disableRotations() @@ -1211,18 +1217,21 @@ export default class SpeckleRenderer { case 'down': case 'bottom': + this.zoomExtents() this.viewer.cameraHandler.controls.rotateTo(0, DEG180, transition) if (this.viewer.cameraHandler.activeCam.name === 'ortho') this.viewer.cameraHandler.disableRotations() break case 'right': + this.zoomExtents() this.viewer.cameraHandler.controls.rotateTo(DEG90, DEG90, transition) if (this.viewer.cameraHandler.activeCam.name === 'ortho') this.viewer.cameraHandler.disableRotations() break case 'left': + this.zoomExtents() this.viewer.cameraHandler.controls.rotateTo(-DEG90, DEG90, transition) if (this.viewer.cameraHandler.activeCam.name === 'ortho') this.viewer.cameraHandler.disableRotations() @@ -1261,10 +1270,12 @@ export default class SpeckleRenderer { view.target.z, transition ) + this.viewer.cameraHandler.enableRotations() } private setViewPolar(view: PolarView, transition = true) { this.viewer.cameraHandler.controls.rotate(view.azimuth, view.polar, transition) + this.viewer.cameraHandler.enableRotations() } public screenToNDC( diff --git a/packages/viewer/src/modules/Viewer.ts b/packages/viewer/src/modules/Viewer.ts index 4839676d7..63bb64e3d 100644 --- a/packages/viewer/src/modules/Viewer.ts +++ b/packages/viewer/src/modules/Viewer.ts @@ -467,7 +467,12 @@ export class Viewer extends EventEmitter implements IViewer { await loader.load() } - public async loadObject(url: string, token: string = null, enableCaching = true) { + public async loadObject( + url: string, + token: string = null, + enableCaching = true, + zoomToObject = true + ) { if (++this.inProgressOperations === 1) (this as EventEmitter).emit(ViewerEvent.Busy, true) await this.downloadObject(url, token, enableCaching) @@ -480,7 +485,8 @@ export class Viewer extends EventEmitter implements IViewer { await this.speckleRenderer.addRenderTree(url) Logger.log('SYNC batch build time -> ', performance.now() - t0) - this.zoom() + if (zoomToObject) this.zoom() + this.speckleRenderer.resetPipeline(true) this.emit(ViewerEvent.LoadComplete, url) this.loaders[url].dispose() @@ -493,7 +499,8 @@ export class Viewer extends EventEmitter implements IViewer { url: string, token: string = null, enableCaching = true, - priority = 1 + priority = 1, + zoomToObject = true ) { if (++this.inProgressOperations === 1) (this as EventEmitter).emit(ViewerEvent.Busy, true) @@ -505,7 +512,7 @@ export class Viewer extends EventEmitter implements IViewer { if (treeBuilt) { t0 = performance.now() - await this.speckleRenderer.addRenderTreeAsync(url, priority) + await this.speckleRenderer.addRenderTreeAsync(url, priority, zoomToObject) Logger.log('ASYNC batch build time -> ', performance.now() - t0) this.speckleRenderer.resetPipeline(true) this.emit(ViewerEvent.LoadComplete, url) diff --git a/packages/viewer/src/modules/context/CameraHanlder.js b/packages/viewer/src/modules/context/CameraHanlder.js index 5bb0a7720..d29575fe4 100644 --- a/packages/viewer/src/modules/context/CameraHanlder.js +++ b/packages/viewer/src/modules/context/CameraHanlder.js @@ -118,10 +118,9 @@ export default class CameraHandler { const lineOfSight = new THREE.Vector3() this.camera.getWorldDirection(lineOfSight) - const target = new THREE.Vector3() - this.controls.getTarget(target) + const target = new THREE.Vector3().copy(this.viewer.World.worldOrigin) const distance = target.clone().sub(this.camera.position) - const depth = distance.dot(lineOfSight) + const depth = distance.length() const dims = { x: this.viewer.container.offsetWidth, y: this.viewer.container.offsetHeight @@ -141,21 +140,22 @@ export default class CameraHandler { this.orthoCamera.updateProjectionMatrix() this.orthoCamera.position.copy(this.camera.position) this.orthoCamera.quaternion.copy(this.camera.quaternion) + this.orthoCamera.updateProjectionMatrix() this.controls.camera = this.orthoCamera // fit the camera inside, so we don't have clipping plane issues. // WIP implementation - const camPos = this.orthoCamera.position - const box = new THREE.Box3().setFromObject(this.viewer.speckleRenderer.allObjects) - const sphere = new THREE.Sphere() - box.getBoundingSphere(sphere) + // const camPos = this.orthoCamera.position + // const box = new THREE.Box3().setFromObject(this.viewer.speckleRenderer.allObjects) + // const sphere = new THREE.Sphere() + // box.getBoundingSphere(sphere) - let dist = sphere.distanceToPoint(camPos) - if (dist < 0) { - dist *= -1 - this.controls.setPosition(camPos.x + dist, camPos.y + dist, camPos.z + dist) - } + // let dist = sphere.distanceToPoint(camPos) + // if (dist < 0) { + // dist *= -1 + // this.controls.setPosition(camPos.x + dist, camPos.y + dist, camPos.z + dist) + // } this.viewer.emit('projection-change', 'ortho') } @@ -165,7 +165,7 @@ export default class CameraHandler { this.camera.position.copy(this.orthoCamera.position) this.camera.quaternion.copy(this.orthoCamera.quaternion) this.camera.updateProjectionMatrix() - this.controls.distance = this.previousDistance + // this.controls.distance = this.previousDistance this.controls.camera = this.camera this.controls.zoomTo(1) this.enableRotations() diff --git a/packages/viewer/src/modules/objects/SpeckleCameraControls.ts b/packages/viewer/src/modules/objects/SpeckleCameraControls.ts index 2c8eeb43a..df1e1990d 100644 --- a/packages/viewer/src/modules/objects/SpeckleCameraControls.ts +++ b/packages/viewer/src/modules/objects/SpeckleCameraControls.ts @@ -47,6 +47,7 @@ export class SpeckleCameraControls extends CameraControls { private _didZoom = false private overrideDollyLerpRatio = 0 private overrideZoomLerpRatio = 0 + static install() { _v3A = new Vector3() _v3B = new Vector3() @@ -101,6 +102,10 @@ export class SpeckleCameraControls extends CameraControls { protected _zoomInternal = (delta: number, x: number, y: number): void => { const zoomScale = Math.pow(0.95, delta * this.dollySpeed) + /** We need to move the camera as well when zooming in orthographic mode */ + const dollyScale = Math.pow(0.95, -delta * this.dollySpeed) + const distance = this._sphericalEnd.radius * dollyScale + this.dollyTo(distance, true, 0.9) // for both PerspectiveCamera and OrthographicCamera this.zoomTo(this._zoom * zoomScale, false, 1)