Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orbit Around Cursor #3796

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d012877
Updated the fly controller to use the z up basis
AlexandruPopovici Nov 21, 2024
e3a20bd
Fixed very important compiler error
AlexandruPopovici Nov 21, 2024
83063b0
Removed the annoying delay when first holding down WASD keys before m…
AlexandruPopovici Nov 21, 2024
59ae40d
Updated LegacyViewer to use the hybrid camera controls
AlexandruPopovici Nov 22, 2024
0b0cb8b
Merge branch 'main' into alex/advanced-camera-controls
AlexandruPopovici Nov 22, 2024
d1da6a7
Added big baker
AlexandruPopovici Nov 26, 2024
86d9d92
Merge branch 'main' into alex/advanced-camera-controls
AlexandruPopovici Nov 27, 2024
0ad6c44
Trying to figure out the essence of this
AlexandruPopovici Dec 11, 2024
d3d6d52
Partly works
AlexandruPopovici Dec 11, 2024
dabeefc
Pivotal coordinates now work
AlexandruPopovici Dec 18, 2024
fbab733
Smoothened out the math abit
AlexandruPopovici Dec 19, 2024
339cc79
Merged and removed debug spheres
AlexandruPopovici Dec 19, 2024
8fab92e
Fixed sandbox error
AlexandruPopovici Dec 19, 2024
28fff50
Enabled the pivot sphere
AlexandruPopovici Dec 20, 2024
688bb53
chore(viewer-lib): Merged with main
AlexandruPopovici Jan 9, 2025
8d6c043
Merge branch 'main' into alex/advanced-camera-controls
AlexandruPopovici Jan 9, 2025
3ded61f
feat(viewer-lib): Fixed some issues with orbiting around cursor
AlexandruPopovici Jan 9, 2025
a4dbf46
feat(viewer-lib): Updates to WEB-2313, orbiting around mouse cursor
AlexandruPopovici Jan 10, 2025
fc1cf44
feat(viewer-lib): Mouse orbiting now takes clipping planes into consi…
AlexandruPopovici Jan 10, 2025
8720874
chore(viewer-lib): Fixed sandbox build error
AlexandruPopovici Jan 10, 2025
b40e99e
fix(viewer-lib): Handled WEB-2449 and WEB-2450
AlexandruPopovici Jan 13, 2025
5de1bc5
fix(viewer-lib): Fixed the issue with focusing and other camera anima…
AlexandruPopovici Jan 13, 2025
cf0c1e8
Merge branch 'main' into alex/advanced-camera-controls
AlexandruPopovici Jan 14, 2025
572ae38
feat(viewer-lib): Updates on mouse orbiting:
AlexandruPopovici Jan 14, 2025
decb3d5
Merge branch 'main' into alex/advanced-camera-controls
AlexandruPopovici Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions packages/viewer-sandbox/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
SelectionEvent,
ViewerEvent,
Viewer,
CameraController,
ViewModes,
SelectionExtension
SelectionExtension,
CameraController
} from '@speckle/viewer'

import './style.css'
Expand All @@ -20,6 +20,7 @@ import {
import { SectionTool } from '@speckle/viewer'
import { SectionOutlines } from '@speckle/viewer'
import { ViewModesKeys } from './Extensions/ViewModesKeys'
// import { JSONSpeckleStream } from './JSONSpeckleStream'
import { BoxSelection } from './Extensions/BoxSelection'

const createViewer = async (containerName: string, _stream: string) => {
Expand Down Expand Up @@ -111,7 +112,7 @@ const getStream = () => {
// prettier-ignore
// 'https://app.speckle.systems/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://app.speckle.systems/streams/da9e320dad/commits/5388ef24b8'
'https://app.speckle.systems/streams/da9e320dad/commits/5388ef24b8'
// 'https://latest.speckle.systems/streams/c1faab5c62/commits/ab1a1ab2b6'
// 'https://app.speckle.systems/streams/da9e320dad/commits/5388ef24b8'
// 'https://latest.speckle.systems/streams/58b5648c4d/commits/60371ecb2d'
Expand Down Expand Up @@ -456,10 +457,12 @@ const getStream = () => {
// Perfectly flat
// 'https://app.speckle.systems/projects/344f803f81/models/5582ab673e'

// big baker
// 'https://latest.speckle.systems/projects/126cd4b7bb/models/032d09f716'
// 'https://speckle.xyz/streams/27e89d0ad6/commits/5ed4b74252'

//Gingerbread
'https://latest.speckle.systems/projects/387050bffe/models/48f7eb26fb'
// 'https://latest.speckle.systems/projects/387050bffe/models/48f7eb26fb'
// DUI3 Mesh Colors
// 'https://app.speckle.systems/projects/93200a735d/models/cbacd3eaeb@344a397239'

Expand Down
2 changes: 1 addition & 1 deletion packages/viewer/src/modules/Viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export class Viewer extends EventEmitter implements IViewer {
}

private update() {
const delta = this.clock.getDelta()
const delta = this.clock.getDelta() * 1000 // turn to miliseconds
const extensions = Object.values(this.extensions)
extensions.forEach((ext: Extension) => {
ext.onEarlyUpdate(delta)
Expand Down
9 changes: 5 additions & 4 deletions packages/viewer/src/modules/extensions/CameraController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ export const DefaultOrbitControlsOptions: Required<CameraControllerOptions> = {
touchAction: 'none',
infiniteZoom: true,
zoomToCursor: true,
orbitAroundCursor: true,
showOrbitPoint: true,
lookSpeed: 1,
moveSpeed: 1,
damperDecay: 30,
Expand Down Expand Up @@ -194,8 +196,7 @@ export class CameraController extends Extension implements SpeckleCamera {
this.perspectiveCamera,
this.viewer.getContainer(),
this.viewer.World,
this.viewer.getRenderer().scene,
this.viewer.getRenderer().intersections,
this.viewer.getRenderer(),
this._options
)
orbitControls.enabled = true
Expand Down Expand Up @@ -295,8 +296,8 @@ export class CameraController extends Extension implements SpeckleCamera {
this.emit(CameraEvent.Dynamic)
}

public onEarlyUpdate() {
const changed = this._activeControls.update()
public onEarlyUpdate(_delta?: number) {
const changed = this._activeControls.update(_delta)
if (changed !== this._lastCameraChanged) {
this.emit(changed ? CameraEvent.Dynamic : CameraEvent.Stationary)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class HybridCameraController extends CameraController {
public constructor(viewer: IViewer) {
super(viewer)
document.addEventListener('keydown', this.onKeyDown.bind(this))
document.addEventListener('keyup', this.onKeyUp.bind(this))
}

protected onKeyDown(event: KeyboardEvent) {
Expand Down
36 changes: 21 additions & 15 deletions packages/viewer/src/modules/extensions/controls/FlyControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ class FlyControls extends SpeckleControls {
}

public set enabled(value: boolean) {
if (value) this.connect()
else this.disconnect()
this._enabled = value
}

Expand Down Expand Up @@ -109,6 +107,8 @@ class FlyControls extends SpeckleControls {
this.container = container
this.world = world
this._options = Object.assign({}, options)

this.connect()
}

public isStationary(): boolean {
Expand All @@ -123,9 +123,12 @@ class FlyControls extends SpeckleControls {
const now = performance.now()
delta = delta !== undefined ? delta : now - this._lastTick
this._lastTick = now
const deltaSeconds = delta / 1000

if (!this._enabled) return false

const deltaSeconds = delta / 1000
const scaledWalkingSpeed = this.world.getRelativeOffset(0.2) * walkingSpeed

if (this.keyMap.forward)
this.velocity.z = -scaledWalkingSpeed * this._options.moveSpeed * deltaSeconds
if (this.keyMap.back)
Expand All @@ -145,9 +148,14 @@ class FlyControls extends SpeckleControls {
if (!this.keyMap.down && !this.keyMap.up) this.velocity.y = 0

if (this.isStationary()) return false

this.moveBy(this.velocity)

this.updatePositionRotation(delta)

return true
}

protected updatePositionRotation(delta: number) {
const diagonal = this.world.worldBox.min.distanceTo(this.world.worldBox.max)
const minMaxRange = diagonal < 1 ? diagonal : 1
this.position.x = this.positionXDamper.update(
Expand Down Expand Up @@ -175,12 +183,10 @@ class FlyControls extends SpeckleControls {

this.rotate(this.euler)
this._targetCamera.position.copy(this.position)

return true
}

public jumpToGoal(): void {
this.update(SETTLING_TIME)
this.updatePositionRotation(SETTLING_TIME)
}

public fitToSphere(sphere: Sphere): void {
Expand All @@ -192,14 +198,14 @@ class FlyControls extends SpeckleControls {
this.goalPosition.copy(pos)
}

/** The input position and target will be in a basis with (0,1,0) as up */
/** The input position and target will be in a basis with (0,0,1) as up */
public fromPositionAndTarget(position: Vector3, target: Vector3): void {
const cPos = this.getPosition()
const cTarget = this.getTarget()
if (cPos.equals(position) && cTarget.equals(target)) return

const tPosition = new Vector3().copy(position).applyMatrix4(this._basisTransform)
const tTarget = new Vector3().copy(target).applyMatrix4(this._basisTransform)
const tPosition = new Vector3().copy(position)
const tTarget = new Vector3().copy(target)
const matrix = new Matrix4()
.lookAt(tPosition, tTarget, this._up)
.premultiply(this._basisTransformInv)
Expand All @@ -208,7 +214,7 @@ class FlyControls extends SpeckleControls {
this.goalPosition.copy(tPosition)
}

/** The returned vector needs to be in a basis with (0,1,0) as up */
/** The returned vector needs to be in a basis with (0,0,1) as up */
public getTarget(): Vector3 {
const target = new Vector3().copy(this.goalPosition)
const matrix = new Matrix4().makeRotationFromEuler(this.goalEuler)
Expand All @@ -217,12 +223,12 @@ class FlyControls extends SpeckleControls {
.applyMatrix4(this._basisTransform)
.normalize()
target.addScaledVector(forward, -this.world.getRelativeOffset(0.2))
return target.applyMatrix4(this._basisTransformInv)
return target
}

/** The returned vector needs to be in a basis with (0,1,0) as up */
/** The returned vector needs to be in a basis with (0,0,1) as up */
public getPosition(): Vector3 {
return new Vector3().copy(this.goalPosition).applyMatrix4(this._basisTransformInv)
return new Vector3().copy(this.goalPosition)
}

/**
Expand Down Expand Up @@ -292,7 +298,7 @@ class FlyControls extends SpeckleControls {

// event listeners
protected onMouseMove = (event: PointerEvent) => {
if (event.buttons !== 1) return
if (event.buttons !== 1 || !this._enabled) return

const movementX = event.movementX || 0
const movementY = event.movementY || 0
Expand Down
53 changes: 53 additions & 0 deletions packages/viewer/src/modules/extensions/controls/PivotalControls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// import { PerspectiveCamera, OrthographicCamera, Sphere, Vector3 } from 'three'
// import { SpeckleControls } from './SpeckleControls.js'

// export interface PivotalControlsOptions {}

// export class PivotalControls extends SpeckleControls {
// private _enabled: boolean = false
// private _options: Required<PivotalControlsOptions> = {}

// get options(): Partial<PivotalControlsOptions> {
// return this._options
// }
// set options(value: Partial<PivotalControlsOptions>) {
// Object.assign(this._options, value)
// }

// get enabled(): boolean {
// return this._enabled
// }
// set enabled(value: boolean) {
// this._enabled = value
// }

// set targetCamera(target: PerspectiveCamera | OrthographicCamera) {
// throw new Error('Method not implemented.')
// }

// isStationary(): boolean {
// throw new Error('Method not implemented.')
// }

// update(delta?: number): boolean {
// throw new Error('Method not implemented.')
// }
// jumpToGoal(): void {
// throw new Error('Method not implemented.')
// }
// fitToSphere(sphere: Sphere): void {
// throw new Error('Method not implemented.')
// }
// dispose(): void {
// throw new Error('Method not implemented.')
// }
// fromPositionAndTarget(position: Vector3, target: Vector3): void {
// throw new Error('Method not implemented.')
// }
// getTarget(): Vector3 {
// throw new Error('Method not implemented.')
// }
// getPosition(): Vector3 {
// throw new Error('Method not implemented.')
// }
// }
Loading
Loading