Christian Marques
Christian Marques

Reputation: 109

How to avoid camera jumps during/after Tween/animation?

I'm having some trouble while creating a camera Tween in THREE.js, specifically at the end and beginning of the animation, there always seems to be a camera 'jump', meaning that the camera flickers once the animation starts and once the animation ends. For reference, what I'm doing is :

  1. Camera is overlooking a scenario from above.

  2. When user clicks on an element of the scenario, the camera zooms on it (by a TWEEN) and when it's close enough, the OrbitControls target change to the centroid of the selected element, and autorotate starts, so the user sees the element rotating in the center of the screen.

  3. When user clicks again, the camera zooms out to its initial position (by a TWEEN) and goes back to the original controls.

I'm experiencing 'jumps/flickers' at the beginning and end of each TWEEN.

This is my tween function :

      var origpos = new THREE.Vector3().copy(camera.position); // original position
      var origrot = new THREE.Euler().copy(camera.rotation); // original rotation

      camera.position.set(x, y+500, z+variation);
      camera.lookAt(new THREE.Vector3(x,y,z));
      var dstrot = new THREE.Euler().copy(camera.rotation)

      // reset original position and rotation
      camera.position.set(origpos.x, origpos.y, origpos.z);
      camera.rotation.set(origrot.x, origrot.y, origrot.z);

     options = {duration: 3000};

      //
      // Tweening
      //

      // position
      new TWEEN.Tween(camera.position).to({
        x: x,
        y: y+500,
        z: z
      }, options.duration).easing(TWEEN.Easing.Cubic.Out).onUpdate(function () {
            camera.lookAt(new THREE.Vector3(x,y,z));
        }).onComplete(function () {
            controls.autoRotate = true;
            controls.autoRotateSpeed = 5.0;
            controls.target = new THREE.Vector3(x, y, z);
        }).start(); 

      // rotation (using slerp)
      (function () {
        var qa = camera.quaternion; // src quaternion
        var qb = new THREE.Quaternion().setFromEuler(dstrot); // dst quaternion
        var qm = new THREE.Quaternion();

        var o = {t: 0};
        new TWEEN.Tween(o).to({t: 1}, options.duration).onUpdate(function () {
          THREE.Quaternion.slerp(qa, qb, qm, o.t);
          camera.quaternion.set(qm.x, qm.y, qm.z, qm.w);
        }).start();
      }).call(this);

Upvotes: 0

Views: 1122

Answers (1)

Christian Marques
Christian Marques

Reputation: 109

OK, it seems that the issue was in itself with the method I was using to rotate the camera, using quaternions and SLERP.

I found that the best way (easier and without flicker/jump) would be to interpolate the parameters of camera.rotation instead of interpolating the quaternions.

So, a Tween of camera.rotation.the_axis_where_you_want_to_rotate works perfectly, and done concurrently with a Tween on the position, achieves the effect I was looking for.

Upvotes: 0

Related Questions