My current camera control code involves moving a vector (camera.target) and then setting the camera to look at that vector using camera.lookAt( camera.target ). The onDocumentMouseMove function calculates longitude and latitude values which are used to adjust the camera.target's x, y, and z coordinates. However, I am facing an issue where after a key press event causes the camera to rotate towards an object, dragging the mouse subsequently results in the camera jumping back to its position before the key press. This is because the mouse movement relies on tracking lat and lon values, which need to be recalculated after the key press. I have attempted to reverse calculate the lat and long from the x, y, z values but my lack of mathematical expertise has proved to be a hindrance. Therefore, I have added a bounty for this problem and any assistance would be greatly appreciated. View the example here.
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 );
}