Reputation: 163
I have a sphere and I need to convert mouse click to latitude and longitude
Everything works fine as long as the sphere having no rotation, but if it have any rotation - I get wrong results
Here is my code:
var mouse = new THREE.Vector2();
mouse.x = (event.pageX / window.innerWidth) * 2 - 1;
mouse.y = -(event.pageY / window.innerHeight) * 2 + 1;
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObject( EarthSphere );
if (intersects.length!=1) return;
var pointOnSphere = new THREE.Vector3();
pointOnSphere.x = intersects[0].point.x;
pointOnSphere.y = intersects[0].point.y;
pointOnSphere.z = intersects[0].point.z;
var EarthRadius = 20;
var lat = 90 - (Math.acos(pointOnSphere.y / EarthRadius)) * 180 / Math.PI;
var lon = ((90 + (Math.atan2(pointOnSphere.x , pointOnSphere.z)) * 180 / Math.PI) % 360) - 180;
I am gussing that I need to manipulate somehow the pointOnSphere based on EarthSphere, any ideas?
EDITED
earth.updateMatrixWorld(true); pointOnSphere = earth.localToWorld( pointOnSphere.clone() );
I thought something like the following would work:
EarthSphere.updateMatrixWorld(true);
pointOnSphere = EarthSphere.localToWorld( pointOnSphere.clone() );
But it does not work ..
Upvotes: 2
Views: 1193
Reputation: 17596
I think, you have to use .worldToLocal()
rather than .localToWorld()
. Thus you'll get a point in local coordinates of your sphere.
The documetation says about .worldToLocal()
:
Updates the vector from world space to local space.
Which means that the vector, passed into this function, will be updated. No creation of a new THREE.Vector3()
.
Both of those functions just update an existing vector which you pass to them.
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects;
var pointOfIntersection = new THREE.Vector3();
var localPoint = new THREE.Vector3();
var spherical = new THREE.Spherical();
var lat, lon;
window.addEventListener("mousedown", sphereClick, false);
function sphereClick(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
intersects = raycaster.intersectObjects([sphere]);
if (intersects.length == 0) return;
pointOfIntersection = intersects[0].point;
sphere.worldToLocal(localPoint.copy(pointOfIntersection)); // that's how it works with translation from the world coordinate system to the local one
createPoint(localPoint);
}
function createPoint(position) {
var point = new THREE.Mesh(new THREE.SphereGeometry(0.0625, 16, 12), new THREE.MeshBasicMaterial({
color: 0x777777 + Math.random() * 0x777777
}));
point.position.copy(position);
sphere.add(point);
var color = point.material.color.getHexString();
// three.js already has useful object to get polar coordinates from the given vector - 'position', which is in local coordinates already
spherical.setFromVector3(position);
lat = THREE.Math.radToDeg(Math.PI / 2 - spherical.phi);
lon = THREE.Math.radToDeg(spherical.theta);
pointList.innerHTML += "<span style='color:#" + color + "'>lat: " + lat + "; lon: " + lon + "</span><br>";
}
jsfiddle example r87.
Upvotes: 2