Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...

    Unified orbit/ortho camera controls with quaternion rotation and exponential damping.

    Combines the damping, pan, and zoom math of three.js OrbitControls with the gimbal-lock-free quaternion rotation of a virtual-trackball ArcballControls, and works with both PerspectiveCamera and OrthographicCamera. Pointer gestures accumulate into per-frame delta buffers (rotation/pan/zoom/roll) that are applied fractionally and decayed each update, giving the smooth "weighted" feel; Shift+scroll view-axis roll feeds the same damped buffers, while auto-rotation is applied directly in the same update step.

    This same class backs both the manager's orbit (3D) and ortho (2D) modes, each with its own instance — ControlsManager disposes and reconstructs a fresh instance on every orbit↔ortho switch, which is why the manager persists its stored distance/zoom limits across that recreation. reinitialize re-derives the internal distance and orientation from the live camera after external camera edits, and saveState/reset snapshot and restore the full pose.

    ControlsManager which owns and switches between control modes

    Hierarchy

    • EventDispatcher<{ change: {}; start: {}; end: {} }>
      • LuxarOrbitControls
    Index
    enabled: boolean = true
    target: Vector3
    enableDamping: boolean
    dampingFactor: number
    rotateSpeed: number
    panSpeed: number
    zoomSpeed: number
    enableRotate: boolean
    enablePan: boolean
    enableZoom: boolean
    autoRotate: boolean
    autoRotateSpeed: number
    autoRotateAxis: AutoRotateAxis

    Camera-frame axis or fixed scene axis the turntable revolves around; see AutoRotateAxis. Also the default axis of applyOrbitRotation, so programmatic turntables (recording) follow the same choice as the interactive one.

    autoDolly: boolean

    Auto-dolly: oscillate the orbit distance on a sine while enabled — the turntable's radial sibling. Gated on enableZoom rather than enableRotate, so it also runs in ortho mode (where it modulates camera.zoom; see math/auto-dolly.ts).

    Switching it OFF leaves the camera exactly where it is, mid-swing or not, and freezes the phase there. That is deliberate, and it is what the turntable does: disabling auto-rotation does not rewind the scene to the angle it started from, so disabling the dolly must not rewind the distance either (measured: rotation jumps 0.000° on disable, and a snap-back would have teleported the camera by up to 95% of the viewing distance in a single frame at max amplitude). Re-enabling resumes from the frozen phase, so nothing jumps in either direction and a completed cycle still returns to wherever the user left it.

    _autoDollyAmplitude: number
    autoDollyPeriod: number

    Seconds per full dolly oscillation.

    screenSpacePanning: boolean
    minDistance: number
    maxDistance: number
    minZoom: number
    maxZoom: number
    mouseButtons: { LEFT: MOUSE | null; MIDDLE: MOUSE | null; RIGHT: MOUSE | null }
    camera: LuxarCamera
    domElement: HTMLElement
    orientation: Quaternion = ...
    distance: number = 1
    rotationDelta: Quaternion = ...
    panDelta: Vector3 = ...
    zoomDelta: number = 0
    rollDelta: number = 0
    dollyPhase: number = 0

    Auto-dolly oscillation phase (radians, wrapped to [0, 2π)). NOT a damping accumulator: the dolly is applied to the distance directly, and this is only the clock it reads. Phase 0 is the baseline distance moving inward, so enabling the feature starts with an approach.

    pointers: PointerEvent[] = []
    pointerPositions: Map<number, Vector2> = ...
    state: ControlAction = 'none'
    rotateStart: Vector2 = ...
    panStart: Vector2 = ...
    dollyStart: Vector2 = ...
    trackballRadius: number
    lastPosition: Vector3 = ...
    lastQuaternion: Quaternion = ...
    target0: Vector3 = ...
    position0: Vector3 = ...
    orientation0: Quaternion = ...
    zoom0: number = 1
    boundOnPointerDown: (e: PointerEvent) => void
    boundOnPointerMove: (e: PointerEvent) => void
    boundOnPointerUp: (e: PointerEvent) => void
    boundOnWheel: (e: WheelEvent) => void
    boundOnContextMenu: (e: Event) => void
    viewAxisRotationHandler: ((e: WheelEvent) => void) | null = null
    keyPanSpeed: number = 7
    keyboardDisposer: (() => void) | null = null
    • get autoDollyAmplitude(): number

      Peak dolly swing as a fraction of distance (0.15 = ±15%). While the dolly is running, assigning re-derives the position at the current phase while preserving the baseline. While it is switched off, assigning does not move the camera because the frozen position is the user's framing (see autoDolly).

      Returns number

    • set autoDollyAmplitude(amplitude: number): void

      Parameters

      • amplitude: number

      Returns void

    • Update controls. Call every frame.

      Parameters

      • OptionaldeltaTime: number

        Optional time since last frame (seconds). Used for frame-rate independent auto-rotation.

      Returns boolean

      true if the view changed — camera position, orientation, or orthographic zoom (useful for render-on-demand).

    • Apply an orbit rotation by the given angle (radians).

      Parameters

      • angle: number

        Rotation angle in radians (positive = counter-clockwise when looking along the axis).

      • Optionalaxis: Vector3

        World-space axis to rotate around. Defaults to the axis autoRotateAxis names (screen-up unless changed) — the SAME axis interactive auto-rotation uses, so a recorded turntable cannot rotate unlike the preview it was set up from.

        This is the same quaternion math that auto-rotation uses — call it from turntable recording or any other code that needs to orbit the camera programmatically.

      Returns void

    • Move the auto-dolly to an absolute oscillation phase (radians) and apply the resulting distance change.

      The programmatic counterpart of the per-frame dolly, for the same reason applyOrbitRotation exists: offline capture drives the camera from a FRAME INDEX, not from wall-clock time (its frames wait on LOD settling, so deltaTime there is meaningless), and both paths must agree on what the oscillation is. Passing an absolute phase rather than an increment lets a recording close its loop exactly — phase 2π lands on the same distance as phase 0, with no accumulated error.

      Uses the configured autoDollyAmplitude, so a recording breathes as deeply as the preview. Does nothing while enableZoom is false.

      Parameters

      • phase: number

        Absolute oscillation phase in radians.

      Returns void

    • Re-derive orientation and distance from the current camera position and target. Call after changing the target externally to keep the orbit state consistent.

      Returns void

    • Enable Shift+scroll view-axis rotation (roll around the viewing axis). Uses capture phase to intercept before other wheel handlers (zoom, FOV). Works in both orbit and ortho modes.

      Parameters

      • speed: number = 0.0005

      Returns void

    • Extract orientation and distance from current camera state. minDistance (scene diagonal × minDistanceFactor once scale limits are known) supplies the scale-relative degenerate-distance floor — see camera-application.ts.

      Returns void

    • Enable keyboard controls (arrow keys for panning). Call with the element that should receive key events (typically window or canvas).

      Parameters

      • element: HTMLElement | Window

      Returns void