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)