How can I make my airplane animaton smoother?

Hi, I am trying to create an effect where an airplane flies in front of the camera and it loops. My approach to this problem is the code below. However, it is too hard coded. I want to know if there is a better method to get a similar result.

Also: I want to add an effect that when I hover over the aircraft the aircraft stops in mid-air and I can rotate it. It would be helpful knowing how to add that too.
Thank you.

import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { TWEEN } from 'https://unpkg.com/three@0.139.0/examples/jsm/libs/tween.module.min.js';

const scene = new THREE.Scene();
scene.background = new THREE.Color('gainsboro');

const camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(-25, 15, 1 );
camera.lookAt(15, 5, -8);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const axesHelper = new THREE.AxesHelper(20);
scene.add(axesHelper);

const loader = new GLTFLoader();
let airplane;

loader.load('./airplane/plane.glb', function (gltf) {
  airplane = gltf.scene;
  scene.add(airplane);

  const ambientLight = new THREE.AmbientLight('white', 0.5);
  scene.add(ambientLight);

  const light = new THREE.DirectionalLight('white', 0.5);
  light.position.set(1, 1, 1);
  scene.add(light);

  window.addEventListener("resize", () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  });

  const curvePoints = [
      new THREE.Vector3(0, 0, 80),      // Start
      new THREE.Vector3(0, 2, 70),      // Accelerate on runway
      new THREE.Vector3(0, 4, 60),      // Preparing for lift off
      new THREE.Vector3(0, 6, 50),      // Lift off
      new THREE.Vector3(0, 8, 40),      // Initial climb
      new THREE.Vector3(0, 10, 30),     // Continue climb
      new THREE.Vector3(0, 12, 20),     // Nearly leveled off
      new THREE.Vector3(0, 140, 10),     // Level off
      new THREE.Vector3(0, 160, 0),      // Straight flight
      new THREE.Vector3(0, 150, -10),    // Continue straight flight
      new THREE.Vector3(0, 14, -20),    // Begin descent
      new THREE.Vector3(0, 12, -30),    // Continue descent
      new THREE.Vector3(0, 10, -40),    // Halfway through descent
      new THREE.Vector3(0, 8, -50),     // Nearly final approach
      new THREE.Vector3(0, 6, -60),     // Final approach
      new THREE.Vector3(0, 4, -70),     // Preparing for touch down
      new THREE.Vector3(0, 2, -200),     // Touch down
      new THREE.Vector3(0, 0, -200),     // Taxi
      // new THREE.Vector3(0, 0, -40),     // Continue taxi
      new THREE.Vector3(0, 0, 0),       // Nearly at start
      new THREE.Vector3(0, 0, 40),      // Back to start
      new THREE.Vector3(0, 0, 150)       // Ready for next round

  ];


  const trajectory = new THREE.CatmullRomCurve3(curvePoints);
  
  const animationDuration = 5000;

  new TWEEN.Tween()
    .to({}, animationDuration)
    .onUpdate(() => {
      const t = TWEEN.now() / animationDuration;
      const positionOnCurve = trajectory.getPoint(t);
      airplane.position.lerp(positionOnCurve, 0.005);
      
    })
    .repeat(Infinity)
    .start();

  new TWEEN.Tween(airplane.rotation)
    .to({ x: -Math.PI/16, y: Math.PI/32, z: Math.PI/8 }, animationDuration)
    .easing(TWEEN.Easing.Cubic.InOut)
    .repeat(Infinity)
    .yoyo(true)
    .start();

  function animate() {
    requestAnimationFrame(animate);
    TWEEN.update();
    renderer.render(scene, camera);
    light.position.copy(camera.position);
  }

  animate();
});

2024-01-25 22-16-21.mkv (2.6 MB)

Using a curve defined by points is OK, althought I do no see any looping in the video.

However, I asked myself whether it is possible to use a formula-based curve. The right strophoid is a good candidate, so I gave it a try. Here is the result (the looping function starts in line 70):

https://codepen.io/boytchev/full/yLwPGEv

Most likely it is not what you look for, but I decided to share it, as someone might find it useful.

1 Like