3D model set the pitch and roll

Use the MapTiler 3D JS module to rotate a 3D model, setting the pitch and roll propertie. Thanks to the 3D JS module we can add 3D models to the map and configure it as we want, rotating it, animating it, scaling it, etc.

NPM module setup


npm install --save @maptiler/sdk @maptiler/3d
import { Map, MapStyle, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
import { Layer3D, AltitudeReference } from '@maptiler/3d';

config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';

const center = [2.3416, 48.9548];

const map = new Map({
  container: document.getElementById('map'),
  hash: true,
  style: MapStyle.SATELLITE,
  zoom: 10,
  center: center,
  pitch: 65,
  maxPitch: 85,
  terrainControl: true,
  terrain: true,
  maptilerLogo: true,
});

(async () => {
  await map.onReadyAsync();

  const layer3D = new Layer3D("custom-3D-layer");
  map.addLayer(layer3D);

  const LNGLAT_OFFSET = 0.25;
  const PLANE_BASE_ALT = 6200;

  // Adding a point light
  layer3D.addPointLight("point-light", {
    intensity: 20,
    color: "#ffffff",
    lngLat: center.map(num => num + 0.0001),
    altitude: 2000,
    altitudeReference: AltitudeReference.GROUND,
  });

  // Adding a mesh of a plane. 
  const originalPlaneID = "biplaneOne";
  const biplaneOne = await layer3D.addMeshFromURL(
    originalPlaneID,
    "https://docs-media.maptiler.com/docs/models/low_poly_biplane.glb",
    {
      lngLat: center,
      heading: 0,
      scale: 300,
      altitude: PLANE_BASE_ALT,
      altitudeReference: AltitudeReference.GROUND,
      transform: {
        rotation: {
          y: Math.PI / 2,
        },
      }
    }
  );

  layer3D.cloneMesh("biplaneOne", "biplaneTwo");
  const biplaneTwo = layer3D.getItem3D("biplaneTwo");

  let progress = 0;
  let speed = 0.001;

  const startLngLat = maptilersdk.LngLat.convert(center.map(num => num - LNGLAT_OFFSET));
  const endLngLat = maptilersdk.LngLat.convert(center.map(num => num + LNGLAT_OFFSET));

  function updateBiPlaneOne() {
    const position = lerpLngLat(startLngLat, endLngLat, progress);
    const nextPosition = lerpLngLat(startLngLat, endLngLat, progress + 0.01);

    const currentAltitude = 2000 * Math.sin(progress * 8) + PLANE_BASE_ALT;
    const nextAltitude = 2000 * Math.sin(progress * 8 + 0.1) + PLANE_BASE_ALT;

    const pitchInRadians = getPitch(currentAltitude, nextAltitude, position.distanceTo(nextPosition));
    const pitch = radiansToDegrees(pitchInRadians);
    biplaneOne.setPitch(pitch);
    biplaneOne.setAltitude(currentAltitude);

    biplaneOne.setLngLat(position);

    biplaneOne.setHeading(radiansToDegrees(getHeading(startLngLat, endLngLat)));
    biplaneOne.setRoll(radiansToDegrees(50 * progress));
  }

  function updateBiPlaneTwo() {
    const position = orbitCenter(center, progress, 0.05);
    const nextPosition = orbitCenter(center, progress + 0.01, 0.05);

    biplaneTwo.setLngLat(position);
    biplaneTwo.setHeading(getHeading(position, nextPosition) * 180 / Math.PI);
    biplaneTwo.setRoll(45);

    const currentAltitude = 2000 * Math.sin(progress * Math.PI * 2) + PLANE_BASE_ALT;
    const nextAltitude = 2000 * Math.sin(progress * Math.PI * 2 + 0.1) + PLANE_BASE_ALT;
    const pitchInRadians = getPitch(currentAltitude, nextAltitude, position.distanceTo(nextPosition));
    const pitch = pitchInRadians * 180 / Math.PI;
    biplaneTwo.setPitch(pitch);
    biplaneTwo.setAltitude(currentAltitude);
  }

  function loop() {
    requestAnimationFrame(loop);

    updateBiPlaneOne();
    updateBiPlaneTwo();

    progress += 0.001;
    if (progress > 1) {
      progress = 0;
    }
  }

  loop();

})()

function orbitCenter(center, progress, radius) {
  return new maptilersdk.LngLat(
    center[0] + radius * Math.cos(progress * 2 * Math.PI),
    center[1] + radius * Math.sin(progress * 2 * Math.PI),
  );
}

function lerpLngLat(startLngLat, endLngLat, progress) {
  return new maptilersdk.LngLat(
    startLngLat.lng + (endLngLat.lng - startLngLat.lng) * progress,
    startLngLat.lat + (endLngLat.lat - startLngLat.lat) * progress,
  );
}

function getPitch(startAltitude, endAltitude, distance) {
  return Math.asin((endAltitude - startAltitude) / distance);
}

function getHeading(startLngLat, endLngLat) {
  return Math.atan2(endLngLat.lng - startLngLat.lng, endLngLat.lat - startLngLat.lat);
}

function radiansToDegrees(radians) {
  return radians * 180 / Math.PI;
}

Low-Poly Biplane by ElectrikGoat0395 is licensed under Creative Commons Attribution ↩

Add a airplane 3D model

Add a plane 3D model

Examples

Add and position flying 3D airplane models on maps.

Add events on 3D models

3D model events

Examples

Listen for mouse events on 3D models in maps.

3D model set the roll

3D model roll

Examples

Rotate 3D models by setting the roll property.

3D model set the pitch or tilt

3D model pitch

Examples

Rotate 3D models by setting the pitch tilt property.

Was this helpful?