0
votes

Trying to reposition a camera on a three.js globe I have a list of countries that when clicked on return the country's lat and lon. I've checked these and am pretty sure thats what is being passed to the code below. So I click on the country and the camera moves to the new position, but it is inside the surface of the globe. Its under the correct country so I have to zoom out. This is the code I am using the radius of the globe is held in the var globeRadius (just in case that wasn't really obvious).

console.log(cameraTarget[0].lat,cameraTarget[0].lon)

  var phi = cameraTarget[0].lat * Math.PI / 180;
  var theta = (cameraTarget[0].lon + 90) * Math.PI / 180;
  posX = globeRadius * Math.cos(phi) * Math.sin(theta);
  posY = globeRadius * Math.sin(phi);
  posZ = globeRadius * Math.cos(phi) * Math.cos(theta);
  camera.position.set(posX,posY,posZ);

  camera.lookAt(new THREE.Vector3(0,0,0));

I'm 'm guessing I have to incorporate the cameras height above the globe in some way. These are my initial camera settings

var FOV = 45;
  var NEAR = 2;
  var FAR = 4000;

  // setup a camera that points to the center
  var camera = new THREE.PerspectiveCamera(FOV,width/height,NEAR,FAR);
  camera.position.set(posX,posY,posZ);
  camera.lookAt(new THREE.Vector3(0,0,0));

Do I need to add the width/height to the globalradius first for example. If anyone could tell me a nice transition method that would be helpful also, thanks

2

2 Answers

0
votes

This seems to work, but I'd appreciate anyone telling me its not correct

posX = (globeRadius+1200) * Math.cos(phi) * Math.sin(theta);
posY = (globeRadius+1200) * Math.sin(phi);
posZ = (globeRadius+1200) * Math.cos(phi) * Math.cos(theta);

But id somebody could hel me with a nice transition that would be great

0
votes

Here is an idea for basic smooth rotation+zoom transition. Having function for parameters setup:

let perf: Performance = window.performance;
// init other necessary variables

var initTransition = function (longitude, latitude, animationTime, radius) {   
    beginTime = perf.now();
    animTime = animationTime * 1000;

    beginPhi = Config.Phi;
    beginThetta = Config.Thetta;
    beginZoomRadius = Config.ZoomRadius;

    targetPhi = latitude * Math.PI / 180;
    targetThetta = (longitude + 90) * Math.PI / 180;
    targetZoomRadius = radius; 

    needsTransitionAnim = true;
 }

perform something like that in your update loop:

update() {
/* stuff */

computeCurrentCameraPos();
setCameraPosFromConfig();
}

where computeCurrentCameraPos is:

var computeCurrentCameraPos  = function() {
if (needsTransitionAnim) {
    t = (perf.now() - beginTime) / speedTime;
    if (t > 1) {
        t = 1;
        needsTransitionAnim = false;
    }

    Config.Phi = blendFunc (beginPhi, targetPhi, t);
    Config.Thetta = blendFunc (beginThetta, targetThetta, t);
    Config.ZoomRadius = blendFunc (beginZoomRadius, targetZoomRadius, t);
    }
}

and setCameraPosFromConfig is self-explanatory. blendFunc(a, b, t) might be whatever interpolation function (here we got t in [0,1] and expect value in [a,b]).

Keep in mind, that considering orientation the closest way from A to 2*M_PI - A lays through 0 if A < M_PI/2, so this example needs to be slightly modified.