javascript - Three.js 如何在 3D Globe、Three.js 上放置带纬度/经度的标记?

标签 javascript 3d three.js

我在 Three.js 中有一个基本的 3D Globe。我使用导航器获取用户的位置,并在用户当前位置的地球上输入带有标记的位置。我一辈子都无法让它显示正确的位置。 3D Globe 也会旋转。我将如何获得正确的位置并使标记简单地随 Globe 旋转?

示例:http://corexsystems.net/Projects/ThreeJs/EarthAndMoon/

代码:

    var renderer    = new THREE.WebGLRenderer({
        antialias   : true
    });
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    renderer.shadowMapEnabled   = true

    var onRenderFcts= [];
    var scene   = new THREE.Scene();
    var camera  = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 100 );
    camera.position.z = 1;

    var light   = new THREE.AmbientLight( 0x222222 )
    scene.add( light )

    var light   = new THREE.DirectionalLight( 0xffffff, 1 )
    light.position.set(5,5,5)
    scene.add( light )
    light.castShadow    = true
    light.shadowCameraNear  = 0.01
    light.shadowCameraFar   = 15
    light.shadowCameraFov   = 45

    light.shadowCameraLeft  = -1
    light.shadowCameraRight =  1
    light.shadowCameraTop   =  1
    light.shadowCameraBottom= -1
    // light.shadowCameraVisible    = true

    light.shadowBias    = 0.001
    light.shadowDarkness    = 0.2

    light.shadowMapWidth    = 1024
    light.shadowMapHeight   = 1024

    //////////////////////////////////////////////////////////////////////////////////
    //      added starfield                         //
    //////////////////////////////////////////////////////////////////////////////////

    var starSphere  = THREEx.Planets.createStarfield()
    scene.add(starSphere)

    //////////////////////////////////////////////////////////////////////////////////
    //      add an object and make it move                  //
    //////////////////////////////////////////////////////////////////////////////////

    // var datGUI   = new dat.GUI()

    var containerEarth  = new THREE.Object3D()
    containerEarth.rotateZ(-23.4 * Math.PI/180)
    containerEarth.position.z   = 0
    scene.add(containerEarth)
    var moonMesh    = THREEx.Planets.createMoon()
    moonMesh.position.set(0.5,0.5,0.5)
    moonMesh.scale.multiplyScalar(1/5)
    moonMesh.receiveShadow  = true
    moonMesh.castShadow = true
    containerEarth.add(moonMesh)

    var earthMesh   = THREEx.Planets.createEarth()
    earthMesh.receiveShadow = true
    earthMesh.castShadow    = true
    containerEarth.add(earthMesh)
    onRenderFcts.push(function(delta, now){
        earthMesh.rotation.y += 1/32 * delta;       
    })

    var geometry    = new THREE.SphereGeometry(50, 32, 32)
    var material    = THREEx.createAtmosphereMaterial()
    material.uniforms.glowColor.value.set(0x00b3ff)
    material.uniforms.coeficient.value  = 0.8
    material.uniforms.power.value       = 2.0
    var mesh    = new THREE.Mesh(geometry, material );
    mesh.scale.multiplyScalar(1.01);
    containerEarth.add( mesh );
    // new THREEx.addAtmosphereMaterial2DatGui(material, datGUI)

    var geometry    = new THREE.SphereGeometry(0.5, 32, 32)
    var material    = THREEx.createAtmosphereMaterial()
    material.side   = THREE.BackSide
    material.uniforms.glowColor.value.set(0x00b3ff)
    material.uniforms.coeficient.value  = 0.5
    material.uniforms.power.value       = 4.0
    var mesh    = new THREE.Mesh(geometry, material );
    mesh.scale.multiplyScalar(1.15);
    containerEarth.add( mesh );
    // new THREEx.addAtmosphereMaterial2DatGui(material, datGUI)

    var earthCloud  = THREEx.Planets.createEarthCloud()
    earthCloud.receiveShadow    = true
    earthCloud.castShadow   = true
    containerEarth.add(earthCloud)
    onRenderFcts.push(function(delta, now){
        earthCloud.rotation.y += 1/8 * delta;       
    })

    //////////////////////////////////////////////////////////////////////////////////
    //      Camera Controls                         //
    //////////////////////////////////////////////////////////////////////////////////
    var mouse   = {x : 0, y : 0}
    document.addEventListener('mousemove', function(event){
        mouse.x = (event.clientX / window.innerWidth ) - 0.5
        mouse.y = (event.clientY / window.innerHeight) - 0.5
    }, false)
    onRenderFcts.push(function(delta, now){
        camera.position.x += (mouse.x*5 - camera.position.x) * (delta*3)
        camera.position.y += (mouse.y*5 - camera.position.y) * (delta*3)
        camera.lookAt( scene.position )
    })





       var marker2 = new THREE.Object3D();
                var loader = new THREE.OBJLoader( );
                loader.load( 'Pin.obj', function ( object2 ) {                 
                    object2.traverse( function ( child ) {
                        if ( child instanceof THREE.Mesh ) {
                            child.material = new THREE.MeshPhongMaterial( { 
                                color: 0x790811, 
                                specular: 0x050505,
                                shininess: 100
                            } );
                        }
                    } );

                    object2.position.set(0.57,-0.15 ,-0.07); // rotating obj should set (X > 0, 0, 0)
                        object2.receiveShadow   = true
    object2.castShadow  = true
    object2.quaternion.setFromUnitVectors(
                    new THREE.Vector3(8, 1, 3.5), new THREE.Vector3(1, 0, 0));
                    object2.scale.set(0.0003,0.0003,0.0003);


                containerEarth.add( object2 );

                });



    scene.add(marker2);


    var rad = Math.PI / 180;

    marker2.quaternion.setFromEuler(
        new THREE.Euler(0, 105 * rad, 45 * rad, "YZX")); 

  navigator.geolocation.watchPosition(function (pos) {


     var lat2 = 42.3125, lon2 = -86.1131;
        marker2.quaternion.setFromEuler(
            new THREE.Euler(45, lon2 * rad, lat2 * rad, "YZX")); 
        });

    //////////////////////////////////////////////////////////////////////////////////
    //      render the scene                        //
    //////////////////////////////////////////////////////////////////////////////////
    onRenderFcts.push(function(){
        renderer.render( scene, camera );       
    })

    //////////////////////////////////////////////////////////////////////////////////
    //      loop runner                         //
    //////////////////////////////////////////////////////////////////////////////////
    var lastTimeMsec= null
    requestAnimationFrame(function animate(nowMsec){
        // keep looping
        requestAnimationFrame( animate );
        // measure time
        lastTimeMsec    = lastTimeMsec || nowMsec-1000/60
        var deltaMsec   = Math.min(200, nowMsec - lastTimeMsec)
        lastTimeMsec    = nowMsec
        // call each update function
        onRenderFcts.forEach(function(onRenderFct){
            onRenderFct(deltaMsec/1000, nowMsec/1000)
        })
    })

最佳答案

您需要将球坐标转换为笛卡尔坐标

如果您没有修改球体的纹理偏移,则以下代码应该可以解决问题:

/**
 * Position an object on a planet.
 * @param {THREE.Object3D} object - the object to place
 * @param {number} lat - latitude of the location
 * @param {number} lon - longitude of the location
 * @param {number} radius - radius of the planet
 */
function placeObjectOnPlanet(object, lat, lon, radius) {
    var latRad = lat * (Math.PI / 180);
    var lonRad = -lon * (Math.PI / 180);
    object.position.set(
        Math.cos(latRad) * Math.cos(lonRad) * radius,
        Math.sin(latRad) * radius,
        Math.cos(latRad) * Math.sin(lonRad) * radius
    );
    object.rotation.set(0.0, -lonRad, latRad - Math.PI * 0.5);
}

请注意,您可以用 THREE.Spherical 做同样的事情.

检查 this fiddle .

如果您希望您的大头针随着行星的旋转而旋转,您需要添加它们作为行星的子元素。或者 将行星和别针添加到同一个 THREE.Object3D:

var object = THREE.Object3D();
object.add(planet);
object.add(pins);
object.rotation.y = 1.0;

关于javascript - Three.js 如何在 3D Globe、Three.js 上放置带纬度/经度的标记?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46017167/

相关文章:

opengl - 如何使用 Assimp 加载 Blender 文件?

c# - Direct X 和 WPF 集成

three.js - 如何使用 WebRTC 流式传输 webGL Canvas ?

three.js - ThreeJs 和 Blender(使用 colladaLoader): first contact

javascript - 传播算子

javascript - 使用 Ajax/Jquery 提交成功后如何隐藏表单

ios - 如何缩放 SCNNodes 以适应边界框

javascript - 从单击的 html 表格行中预填充表单字段,并从 json 文件接收表格数据

javascript - 如何获取当前页面中 Referer 页面的值(该页面中的隐藏字段)?

javascript - 将对象移动到鼠标光标下方