我在 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/