[SOLVED] Rotate Camera to face point on sphere

Evening/Morning y’all

thus far
example: https://codepen.io/magicspon/pen/jYJNBq?editors=0010

I’ve setup a click handler that responds to any of the points on the sphere being clicked.
I need to rotate the sphere so that the point clicked is facing the camera

I’m sure there is some beautifully simple way of achieving this… currently a little lost in google and maths, any pointers muchly appreciated.

thanks

You can move your camera instead of rotating the sphere:

  const item = intersects[0]
  
  var point = item.point;
  var camDistance = this.camera.position.length();
  this.camera.position.copy(point).normalize().multiplyScalar(camDistance);
  this.controls.update();

1 Like

Amazing, you absolute legend. Thank you a million times.

You’re welcome ))

I’d say that about many people from three.js community, but never about myself :smiley:

Any thoughts on animating the change…

I was thinking I could use the FLIP approach… i.e make the change, save, invert, and play…

I think I’ve got a lot to learn about three.js… this is my first dive into 3d… waaaa!

// get the current camera position
const { x, y, z } = this.camera.position
const start = new THREE.Vector3(x, y, z)

// move camera to the target
const point = item.point
const camDistance = this.camera.position.length()
this.camera.position
	.copy(point)
	.normalize()
	.multiplyScalar(camDistance)

// save the camera position
const { x: a, y: b, z: c } = this.camera.position

// invert back to original position
this.camera.position
	.copy(start)
	.normalize()
	.multiplyScalar(camDistance)

// animate from start to end
TweenMax.to(this.camera.position, 1, { x: a, y: b, z: c })

I’d use .onUpdate() instead of .onComplete() to control the camera:

// animate from start to end
TweenMax.to(this.camera.position, 1, { x: a, y: b, z: c, onUpdate: () => {
    this.controls.update()
} })
1 Like

He strikes again! You beauty. Thanks

Hi, I know this thread is pretty old, but it did help me quite a bit. So I thought to just reply in here!
I’ve used every piece of code in this thread to try and fix my kind of similar goal.
I would like to move the camera, which is looking face down on the sphere (planet), toward its center (at 0, 0, 0) from a given point (longitude and latitude) around the sphere to another point on the surface of the sphere (also longitude and latitude) while maintaining a fixed distance from it.
Unfortunately, the code suggested in here does only work up to a point.I think I’ve almost nailed it.

This is what I have now:

calcPosFromLatLonRad(latitude: number, longitude: number, radius: number): Vector3 {
  
      const phi   = (90 - latitude) * (Math.PI / 180);
      const theta = (longitude + 180) * (Math.PI / 180);
  
      const x = -(radius * Math.sin(phi)*Math.cos(theta));
      const z = (radius * Math.sin(phi)*Math.sin(theta));
      const y = (radius * Math.cos(phi));
    
      return new Vector3(x, y, z);
  }

this.startPositionVector = this.camera.position.clone();
this.endPositionVector = calcPosFromLatLonRad(latitude, longitude, this.globeRadius + this.cameraDistance);

gsap.fromTo(this.camera.position,
      {
        x: this.startPositionVector.x,
        y: this.startPositionVector.y,
        z: this.startPositionVector.z,
      },
      {
        duration: 1,
        x: this.endPositionVector.x,
        y: this.endPositionVector.y,
        z: this.endPositionVector.z,
        onUpdate: () => {
          this.camera.position.normalize().multiplyScalar(this.globeRadius + this.cameraDistance);
          this.camera.lookAt(new Vector3(0, 0, 0));
        }
      }
    );

I know Tween is now gsap and there may be some alterations to how their code works, but I suspect my code is missing something.
The animation runs smoothly and ends at the intended target. But it does not start out on the position of the camera I orbit it to. The camera always starts out on a completely different position and then moves around the globe toward its destination.
Could there be some conflict with the orbit controls maybe? Or maybe the calculation of the position is incorrect.
When I add this.orbitControls.update() in the onUpdate callback the animation doesn’t even occur anymore. It just goes straight to the end position.
If the code looks fine I can try to set up a fiddle or codepen sample.

Never mind. I tried to replicate the code that I was looking for in a clean component and now it is working. For anyone who might be running into the same problems, here is mine:

const cameraDistance = this.camera.position.distanceTo(this.center) - this.radius;
    const rotateStartPositionVector = this.camera.position.clone();
    const rotateEndPositionVector = this.calculatePositionVectorFromLatLonRad(lat, lon, this.radius + cameraDistance);
    
    gsap.fromTo(this.camera.position,
      {
        x: rotateStartPositionVector.x,
        y: rotateStartPositionVector.y,
        z: rotateStartPositionVector.z,
      },
      {
        duration: 0.5,
        x: rotateEndPositionVector.x,
        y: rotateEndPositionVector.y,
        z: rotateEndPositionVector.z,
        onUpdate: () => {
          this.camera.position.normalize().multiplyScalar(this.radius + cameraDistance);
          this.camera.lookAt(new Vector3(0, 0, 0));
        }
      }
    );