Alternative FirstPersonController

by felixp

HTML

<script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
<script src="https://unpkg.com/@loaders.gl/[email protected]/dist/dist.min.js"></script>

CSS

body {
  margin: 0;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

JavaScript

-=/*
* https://deck.gl/docs/api-reference/core/first-person-view
*/
const {DeckGL, Controller, FirstPersonView, PointCloudLayer, COORDINATE_SYSTEM, LinearInterpolator} = deck;
const {PLYLoader} = loaders;

import { Vector3, _SphericalCoordinates as SphericalCoordinates, clamp } from 'https://esm.sh/@math.gl/[email protected]';
 
// Modified FirstPersonController implementation

class FirstPersonController extends Controller {
  ControllerState = FirstPersonState;

  transition = {
    transitionDuration: 300,
    transitionInterpolator: new LinearInterpolator(['position', 'pitch', 'bearing'])
  };
}

function mod(value, divisor) {
  const modulus = value % divisor;
  return modulus < 0 ? divisor + modulus : modulus;
}

// Apply any constraints (mathematical or defined by _viewportProps) to map state
function applyConstraints(props) {
  // Ensure pitch and zoom are within specified range
  const { pitch, maxPitch, minPitch, longitude, bearing } = props;
  props.pitch = clamp(pitch, minPitch, maxPitch);

  // Normalize degrees
  if (longitude !== null && (longitude < -180 || longitude > 180)) {
    props.longitude = mod(longitude + 180, 360) - 180;
  }
  if (bearing < -180 || bearing > 180) {
    props.bearing = mod(bearing + 180, 360) - 180;
  }

  return props;
}

const MOVEMENT_SPEED = 25;
const PAN_SPEED = 500;

// Adapted from FirstPersonState used in deck.gl FirstPersonController
class FirstPersonState {
  getViewportProps() {
    return this._viewportProps;
  }

  getState() {
    return this._state;
  }

  constructor(options) {
    const {
      /* Viewport arguments */
      width, // Width of viewport
      height, // Height of viewport

      // Position and orientation
      position = [0, 0, 0], // typically in meters from anchor point

      bearing = 0, // Rotation around y axis
      pitch = 0, // Rotation around x axis

      // Geospatial anchor
      longitude = null,
      latitude = null,

      maxPitch = 90,
      minPitch = -90,

      // Model...