Three.js earth and camera turning problems

安稳与你 提交于 2019-12-12 02:15:58

问题


Like this site http://www.gsmlondon.ac.uk/global-oil-map/

I would like to click on this marker, let this marker turn to the center of the screen. Now know the mark latitude and longitude, how to turn after the click? I do not understand.


回答1:


Interesting question, I tried Matrix to get right orientation, but the result is a little bit strange. I choose another way using spherical coordinates system, and it works now.

we need to get two points coordinates, one is the point on the sphere surface which is closest to the camera we note it as P(the line from camera to center of sphere intersect with the sphere). another point is where we click on the sphere surface, we note it as Q .

we use raycaster to get P and Q Cartesian Coordinates. and convert the Cartesian Coordinates to Spherical Coordinates(always described like (r,θ,φ)).

then, we calculate the angular displacement from Q to P. and make the displacement as an addition to sphere rotation.

Here is my snippet:

    //get the point coordinates which a line from camera to sphere center intersect with the sphere 
    var vector = new THREE.Vector3().copy(sphere.position);
    vector = vector.unproject(camera);
    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
    var intersects = raycaster.intersectObjects([sphere],true);
    var intersected_point = new THREE.Vector3().copy(intersects[0].point);

    //calculate the intersected point spherical coordinates
    var radius = sphere.children[0].geometry.parameters.radius;
    var heading = Math.atan2(intersects[0].point.x,intersects[0].point.z);
    var pitch = Math.asin(-(intersects[0].point.y)/radius);

    document.addEventListener("click",OnDocumentClick,false);

    function OnDocumentClick(event)
    {
        //get the point coordinates which you click on the sphere surface
        var vector = new THREE.Vector3(( event.clientX / window.innerWidth ) * 2 - 1, -( event.clientY / window.innerHeight ) * 2 + 1, 0.5);
        vector = vector.unproject(camera);
        var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
        var intersects = raycaster.intersectObjects([sphere],true);
        if(intersects.length > 0)
        {
            //get click point spherical coordinates
            var heading1 = Math.atan2(intersects[0].point.x,intersects[0].point.z);
            var pitch1 = Math.asin(-(intersects[0].point.y)/radius);
            //calculate displacement of click point to intersected point
            var delta_heading = heading - heading1;
            var delta_pitch = pitch - pitch1;
            var target_pitch = parseFloat(sphere.rotation.x) +delta_pitch;
            var target_heading = parseFloat(sphere.rotation.y) + delta_heading;

            //using an animation to rotate the sphere
            anime({
                targets:sphere.rotation,
                x:target_pitch,
                y:target_heading,
                elasticity: 0
            });
        }
    }

At the end, I use an animation lib to make the rotation smooth.

Here is my demo:rotate the earth.

I made a little progress, the previous version has a little bit off. when I turn up and down the earth, I got a bad result. I think the code sphere.rotation.x += delta_pitch make sphere rotate on object axises. but what we need is making the sphere rotate on the world space axises. we know world axises coordinates are always x_axis = (1,0,0) ; y_axis = (0,1,0) ; z_axis = (0,0,1); then, I convert the world coordinates to object coordinates, Sphere matrix interpret sphere rotate from indentity rotation to current rotation. and the inverse matrix interpret the backword. so we can apply the inverse matrix to basic axises to get object space coordinates. make sphere rotate on new axises. I just make a little change in OnDcoumentClick function:

            var heading1 = Math.atan2(intersects[0].point.x,intersects[0].point.z);
            var pitch1 = Math.asin(-(intersects[0].point.y)/radius);
            //get the sphere inverse matrix;
            var sphere_matrix = new THREE.Matrix4().copy(sphere.matrix);
            var inverse_sphere_matrix = new THREE.Matrix4();
            inverse_sphere_matrix.getInverse(sphere_matrix);
            //convert world space x and y axises to sphere object space coordinates.
            var x_axis = new THREE.Vector3(1,0,0);
            var y_axis = new THREE.Vector3(0,1,0);
            x_axis.applyMatrix4(inverse_sphere_matrix);
            y_axis.applyMatrix4(inverse_sphere_matrix);

            //calculate displacement of click point to intersected point
            var delta_heading = heading - heading1;
            var delta_pitch = pitch - pitch1;
            //make sphere rotate around whith world x and y axises.
            sphere.rotateOnAxis(x_axis,delta_pitch);
            sphere.rotateOnAxis(y_axis,delta_heading);

Here is my new demo: rotate earth new version.



来源:https://stackoverflow.com/questions/42663593/three-js-earth-and-camera-turning-problems

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!