[3d Globe] how to rotate the globe to target latLng and align earth west to east

Rotating a 3D globe to focus on a particular latitude and longitude.
Ensuring that post-rotation, the globe’s spin axis aligns with the global West-to-East direction, akin to how the real Earth rotates about its axis.

I’ve tried many times on GPT-4 and Sonnet3.5, but there is no ideal solution. The existing code is like this, but it only deals with the case where the initial globe is aligned around longitude, but if the user rolls the globe in any direction, this will not work.

rotateGlobeTo(targetLatLng, onComplete) {
    // Current globe center point in lat/lng
    // const currentLatLng = this.getGlobeCenterLatLng();

    const initialLatLng = this.previousTargetLatLng;
    // Normalize the longitude difference for the shortest path
    const normalizeAngle = (angle) => {
      return ((angle + 180) % 360) - 180;
    };

    const azimuthalAngle = normalizeAngle(targetLatLng.lng - initialLatLng.lng);
    const azimuthalRotation = THREE.MathUtils.degToRad(azimuthalAngle);

    // Calculate polar rotation based on latitudinal change
    const polarAngle = targetLatLng.lat - initialLatLng.lat;
    const polarRotation = THREE.MathUtils.degToRad(polarAngle);

    // Create quaternions for each rotation
    const azimuthalQuaternion = new THREE.Quaternion().setFromAxisAngle(
      new THREE.Vector3(0, 1, 0), // Rotate around Y-axis for longitude
      -azimuthalRotation
    );

    const polarQuaternion = new THREE.Quaternion().setFromAxisAngle(
      new THREE.Vector3(1, 0, 0), // Rotate around X-axis for latitude
      polarRotation
    );

    // Combine rotations: first apply polar rotation, then azimuthal
    const finalRotation = polarQuaternion.multiply(azimuthalQuaternion);

    this.animateRotation(finalRotation, onComplete);
  }

  animateRotation(finalRotation, onComplete) {
    let duration = 800;
    const startTime = Date.now();

    const startRotation = this.earth.quaternion.clone(); // Clone the initial quaternion

    const animate = () => {
      const currentTime = Date.now();
      const fraction = (currentTime - startTime) / duration;

      if (fraction < 1) {
        // Update the quaternion by interpolating between the start and the target
        this.earth.quaternion
          .copy(startRotation)
          .slerp(finalRotation, fraction);
        requestAnimationFrame(animate);
      } else {
        // Make sure we end precisely at the final rotation
        this.earth.quaternion.copy(finalRotation);
        if (typeof onComplete === "function") {
          onComplete(); // Call the completion callback if provided
        }
      }
    };

    animate();
  }

This is the current effect: https://ntc.playgeo.one/
Thanks :slightly_smiling_face:

Here is an example where you can rotate the earth to a chosen lat lon on button click. Maybe its helpful.

Tween to Latitude Longitude

image

3 Likes

This does solve my problem. Many thanks :heart: to you and the project owner!