我用来控制相机的代码通过移动矢量(camera.target)然后设置相机来查看该矢量来工作。在本例中,camera.lookAt(camera.target);。 onDocumentMouseMove 函数计算经度和纬度,这有助于设置camera.target x、y 和z 值。以下是事情如何运作的示例。按任意键都会导致相机旋转到某个对象,但如果您下次通过拖动鼠标移动相机时这样做,相机将自动跳转到按键之前的最后一个位置。这是因为为了让鼠标移动相机,它必须跟踪纬度和经度。所以我遇到的问题是在击键后计算新的经纬度位置。我在想如果目标 x,y,z 值可以根据 lon 和 lat 计算出来,那么按理说 lat 和 lon 可以根据 x,y,z 值反向计算。不幸的是,数学超出了我的能力范围。我已经为此问题添加了赏金。任何帮助将非常感激。 http://codepen.io/anon/pen/GgRXJz
var spriteImg, material, geometry;
var camera, scene, renderer;
var keyboard = new THREEx.KeyboardState();
var fov = 70,
texture_placeholder,
isUserInteracting = false,
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0;
init();
animate();
function init() {
var container;
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xffffff, 1);
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
window.addEventListener( 'resize', onWindowResize, false );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
stats.domElement.style.left = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
material = new THREE.MeshBasicMaterial( { color: 0x0125fd} );
geometry = new THREE.PlaneGeometry(50, 50, 3, 3);
blue1 = new THREE.Mesh(geometry, material);
blue1.position.set(200,100,200);
scene.add(blue1);
blue1.lookAt( camera.position );
blue2 = new THREE.Mesh(geometry, material);
blue2.position.set(-200,-100,-200);
blue2.lookAt( camera.position );
scene.add(blue2);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
isUserInteracting = true;
onPointerDownPointerX = event.clientX;
onPointerDownPointerY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
}
function onDocumentMouseMove( event ) {
if ( isUserInteracting ) {
lon = ( event.clientX - onPointerDownPointerX ) * 0.3 + onPointerDownLon;
lat = ( onPointerDownPointerY - event.clientY ) * 0.3 + onPointerDownLat;
}
}
function onDocumentMouseUp( event ) {
isUserInteracting = false;
}
function animate() {
requestAnimationFrame( animate );
render();
update();
}
function update()
{
stats.update();
}
function render() {
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = THREE.Math.degToRad( 90 - lat );
theta = THREE.Math.degToRad( lon );
camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
camera.target.y = 500 * Math.cos( phi );
camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );
camera.lookAt( camera.target );
renderer.render( scene, camera );
}
最佳答案
要从 x,y,z 坐标计算纬度和经度,您需要反转您的方法。请参阅updated code-pen用于演示。
原文:
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = THREE.Math.degToRad( 90 - lat );
theta = THREE.Math.degToRad( lon );
camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
camera.target.y = 500 * Math.cos( phi );
camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );
逆:
摘自original code-pen的片段,发现于 document.body.onkeydown
update()
内的操作事件监听器method -- 在demo中修改了这个方法,代码如下
//Since you are looking at a given shape on keypress, decided to inverse from that
//shape's position.
camera.lookAt( blue1.position );
//Added the following four lines of code
phi = Math.acos((blue1.position.y)/500);
theta = Math.acos((blue1.position.x)/(500 * Math.sin(phi)))
lon = THREE.Math.radToDeg(theta);
lat = 90-THREE.Math.radToDeg(phi);
代数的更多细节
鉴于我在学校总是为了仅显示解决方案而获得停靠点,以下是我如何从 x、y 和 z 逆/求解纬度和经度
让 x、y 和 z 代表您给定的观点( camera.target.x
或 <object>.position.x
等)。
让phi
= Φ, theta
= θ
求解 θ
- x = 500 * sin (Φ) * cos(θ)
- x/(500 * sin(Φ)) = 500 * sin (Φ) * cos(θ)/(500 * sin(Φ))
- x/(500 * sin(Φ)) = cos(θ)
- arccos(x/(500 * sin(Φ))) = arccos(cos(θ))
- arccos(x/(500 * sin(Φ))) = θ
求解 Φ
- y = 500 * cos(Φ)
- y/500 = 500 * cos(Φ)/500
- y/500 = cos(Φ)
- arccos(y/500) = arccos(cos(Φ))
- arccos(y/500) = Φ
求解 lon
- θ = degToRad(lon)
- radToDeg(θ) = degToRad(degToRad(lon))
- radToDeg(θ) = lon
求解 lat
- Φ = degToRad( 90 - 纬度 );
- radToDeg(Φ) = radToDeg(degToRad( 90 - lat ))
- radToDeg(Φ) = 90 - 纬度
- radToDeg(Φ) - 90 = 90 - lat - 90
- radToDeg(Φ) - 90 = -lat
- -1*(radToDeg(Φ) - 90) = -1*(-lat)
- -radToDeg(Φ + 90 = 纬度
- 90 - radToDeg(Φ) = 纬度
- 90 - radToDeg(Φ) = 纬度
关于javascript - 旋转相机面对物体,而不会弄乱经纬度值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26935288/