cameraSetup.js

import {
  localStorageSetMatrix4,
  localStorageSetVector3,
} from '@ud-viz/utils_browser';
import { C3DTILES_LAYER_EVENTS, Layer, PlanarView } from 'itowns';
import { Vector3 } from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

import { Visualizer } from '.';

/**
 * Sets up default camera settings for an iTowns view.
 *
 * @param {PlanarView} itownsView - iTowns view
 * @param {OrbitControls} orbitControls - Orbit controls for the camera.
 * @param {Array<Layer>} layers - layers in the scene.
 * @param {object} [camOptions] - camera options.
 * @param {object} [camOptions.default] - Default camera options.
 * @param {object} [camOptions.default.position] - Default camera position coordinates.
 */
export function setUpCameraDefaults(
  itownsView,
  orbitControls,
  layers,
  camOptions
) {
  const camera3D = itownsView.camera.camera3D;

  // Try to set camera position from local storage
  if (
    !localStorageSetMatrix4(
      camera3D.matrixWorld,
      Visualizer.CAMERA_LOCAL_STORAGE_KEY
    )
  ) {
    // If not in local storage, use default position from options
    if (camOptions && camOptions.default)
      camera3D.position.set(
        camOptions.default.position.x,
        camOptions.default.position.y,
        camOptions.default.position.z
      );
  } else {
    // If found in local storage, decompose the matrix to set position, rotation, and scale
    camera3D.matrixWorld.decompose(
      camera3D.position,
      camera3D.quaternion,
      camera3D.scale
    );
    camera3D.updateProjectionMatrix();
  }

  // Try to set orbit controls target from local storage
  if (
    !localStorageSetVector3(
      orbitControls.target,
      Visualizer.TARGET_LOCAL_STORAGE_KEY
    )
  ) {
    // If not in local storage, set up a listener to set target when tile content is loaded
    const listener = (layer) => {
      const bb = layer.tileContent.boundingVolume.box;
      const center = bb.getCenter(new Vector3());
      const target = layer.tileContent.position.clone().add(center.clone());
      orbitControls.target.copy(target);
      orbitControls.update();
      itownsView.notifyChange(camera3D);

      // Remove the listener from all layers once target is set
      layers.forEach((layer) =>
        layer.removeEventListener(
          C3DTILES_LAYER_EVENTS.ON_TILE_CONTENT_LOADED,
          listener
        )
      );
    };

    // Add the listener to all layers
    layers.forEach((layer) => {
      layer.addEventListener(
        C3DTILES_LAYER_EVENTS.ON_TILE_CONTENT_LOADED,
        listener
      );
    });
  }
}