# Animating perspective camera to mimic orbit controls

**URL:** <https://discourse.threejs.org/t/animating-perspective-camera-to-mimic-orbit-controls/18644>\
**Category:** Questions\
**Tags:** orbit-controls, animation\
**Created:** [September 12, 2020, 4:21pm UTC](https://discourse.threejs.org/t/animating-perspective-camera-to-mimic-orbit-controls/18644 "2020-09-12T16:21:13Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![skiler07](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/skiler07/32/13269_2.png) [@skiler07](https://discourse.threejs.org/u/skiler07)\
**Post date:** [September 12, 2020, 4:21pm UTC](https://discourse.threejs.org/t/animating-perspective-camera-to-mimic-orbit-controls/18644/1 "2020-09-12T16:21:13Z")

</div>

I’m trying to animate the camera on click to rotate around an object at 0,0,0. I’ve tried the setup shown below using TWEEN but the camera seems to move instead of rotating around. I also tried using an AnimationClip with position + rotation of the camera but the linear interpolation causes the camera to move linearly from point A to B instead of in a curve. Is there any way to achieve my desired functionality?

```
 function createTween(){
              var qa = new THREE.Quaternion().copy(camera.quaternion);
              var qb = destinationQuaternion;
              var qm = new THREE.Quaternion();
              let r = new TWEEN.Tween({t: 0})
              .to({t: 1}, 5000)
              .onUpdate((tween) => {
                  THREE.Quaternion.slerp(qa, qb, qm, tween.t);
                  camera.quaternion.set(qm.x, qm.y, qm.z, qm.w);
              })
              .easing(TWEEN.Easing.Quartic.InOut)
              .start();
            }
```

---

<div class="post-metadata">

**Author:** ![Mugen87](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/mugen87/32/5645_2.png) [@Mugen87](https://discourse.threejs.org/u/Mugen87)\
**Post date:** [September 13, 2020, 11:27am UTC](https://discourse.threejs.org/t/animating-perspective-camera-to-mimic-orbit-controls/18644/2 "2020-09-13T11:27:08Z")

</div>

> [@skiler07](#):
>
> I’m trying to animate the camera on click to rotate around an object at 0,0,0.

Right now, you animate the `quaternion` property which means you only rotate the camera. To get the same orbiting behavior like `OrbitControls`, you have to translate the camera in 3D space and ensure by calling `lookAt()` to look at the focus point.

The problem is that animation library like Tween.js and GSAP will animate in a linear fashion from vector A to B. E.g. [three.js dev template - module - JSFiddle - Code Playground](https://jsfiddle.net/ng3xcfua/)

If you want to animate the camera around an object by simulating the trajectory of a satellite, you have to animate along a predefined sequence of points (A-B-C-D etc.).

---

<div class="post-metadata">

**Author:** ![skiler07](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/skiler07/32/13269_2.png) [@skiler07](https://discourse.threejs.org/u/skiler07)\
**Post date:** [September 13, 2020, 1:03pm UTC](https://discourse.threejs.org/t/animating-perspective-camera-to-mimic-orbit-controls/18644/3 "2020-09-13T13:03:34Z")

</div>

Thanks for the feedback. I looked around on the web and found a solution to a problem similar to mine. After changing a few bits I got this code to rotate the camera properly.

```
  function cameraRotation(){
  var sphericalStart = new THREE.Spherical();
  var sphericalEnd = new THREE.Spherical();
  var vectorStart = new THREE.Vector3();
  var vectorEnd = new THREE.Vector3();
  var angle = {
    value: 0
  };
  var angleEnd = {
    value: 0
  };
  var normal = new THREE.Vector3();

  function setInitials() {
    sphericalStart.setFromCartesianCoords(positions[0].x, positions[0].y, positions[0].z);
    sphericalEnd.setFromCartesianCoords(positions[1].x, positions[1].y, positions[1].z);
    vectorStart.setFromSpherical(sphericalStart);
    vectorEnd.setFromSpherical(sphericalEnd);
    normal.copy(vectorStart).cross(vectorEnd).normalize();
    angle.value = 0;
    angleEnd.value = vectorStart.angleTo(vectorEnd);
  }
  setInitials();

  var tween = new TWEEN.Tween(angle).to(angleEnd, 5000)
  .onUpdate(
    () => {
      camera.position.copy(vectorStart).applyAxisAngle(normal, angle.value)
      camera.lookAt(0,0,0)
    }
  )

```

It only doesn’t work if the second camera is zoomed, but I will attempt to solve this by creating an animationClip or another tween for zoom.

---

<div class="post-metadata">

**Author:** ![neuged](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/neuged/32/27983_2.png) [@neuged](https://discourse.threejs.org/u/neuged)\
**Post date:** [July 13, 2022, 6:06pm UTC](https://discourse.threejs.org/t/animating-perspective-camera-to-mimic-orbit-controls/18644/4 "2022-07-13T18:06:07Z")

</div>

Thx @skiler07 ! This helped me a lot. This can be simplified a bit though. If anybody needs it:

```javascript
function rotateCamera(from, to) {

  const angle = { value: 0 };
  const angleEnd = { value: 0 };
  const normal = new Vector3();

  normal.copy(from).cross(to).normalize();
  angleEnd.value = from.angleTo(to);

  const tween = new Tween(angle).to(angleEnd, 500).onUpdate(() => {
    camera.position.copy(from).applyAxisAngle(normal, angle.value);
    camera.lookAt(0, 0, 0);
  });
  tween.start();

```

---

<div class="post-metadata">

**Author:** ![Lesley\_Chingwena](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/lesley_chingwena/32/28391_2.png) [@Lesley\_Chingwena](https://discourse.threejs.org/u/Lesley_Chingwena)\
**Post date:** [August 26, 2022, 5:00pm UTC](https://discourse.threejs.org/t/animating-perspective-camera-to-mimic-orbit-controls/18644/5 "2022-08-26T17:00:28Z")

</div>

Thank you so much, this really helped me after days of searching,

Remember to add TWEEN.update(); in your animation update function.
