I am currently building an application in three.js alongside some jQuery. I am currently raycasting and placing a helper at the location of where the raycast hits. More or less I am trying to achieve this.
I have managed to achieve this, however upon moving the coordinates of my objects and moving the camera to the new location, my raycast, or the helper at least, is off. It seems to be off by around sort of 30 pixels but depends as you change the camera angle as you can see from here
Here is the code for the helper and the onMouseMove event for raycasting.
// RAYCAST HELPER
var geometry = new THREE.CylinderGeometry( 0, 5, 15, 3 ); // radius at top, radius at bottom, height, segments
//geometry.applyMatrix( new THREE.Matrix4().makeTranslation( -50, 0, 0 ) );
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI / 2 ) );
helper = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial({ color: 0xEB1515, ambient: 0xEB1515, wireframe: false }) );
scene.add( helper );
rays = true;
function onMouseMove( event ) {
//console.log("Mouse moved");
$( document ).ready(function() {
if ( rays == true ) {
cX = event.clientX - $( "#info" ).width()
cY = event.clientY - $( "#topbar" ).height()
mouseVector.x = 2 * ( cX / canvaswidth ) - 1;
mouseVector.y = 1 - 2 * ( cY / canvasheight );
mouseVector.z = 1;
var raycaster = projector.pickingRay( mouseVector.clone(), camera );
for (var i = 0; i < buildingsroofs.length; i++) {
var intersects = raycaster.intersectObject( buildingsroofs[i]);
// Toggle rotation bool for meshes that we clicked
if ( intersects.length > 0 ) {
console.log("Intersection");
helper.position.set( 0, 0, 0 );
helper.lookAt( intersects[ 0 ].face.normal );
helper.position.copy(intersects[0].point);
}
}
} //End of overarching if loop
})
} //End of onMouse function
Interestingly, I have got it to work here but these objects have the wrong coordinates from what i'm after. You can also see I am adjusting for the height of the top div and the side div, so that does not appear to be the issue as I originally imagined.
As everything else is correct, your mouseVector
x
and y
values (i.e. clientX
and clientY
) are most likely off as compared with your WebGL canvas (for instance, you may be getting these from some element other than the canvas.
Easiest way to check for this is to place the mouse in the top left corner of your canvas (should be (0, 0)
and log out the mouse position on click to see whether your values are off. Apply same for the bottom right corner, checking against your canvas width and height. I solved a similar problem this way. In my case, (cx, cy)
were (-10, -10)
and this was enough for a substantial error in raycasting.
Oddly enough the issue seemed to resolve itself upon changing the perspective camera near parameter from 0.1 to 1
camera = new THREE.PerspectiveCamera(45, canvaswidth / canvasheight , 0.1, 10000 );
To:
camera = new THREE.PerspectiveCamera(45, canvaswidth / canvasheight , 1, 10000 );
I am still not 100% sure why this fixed the issue, but it appears to have worked.
Edit: Changing FOV from 45 to 60 removed the minor distortion in the raycasting that was still occuring after changing the near camera parameter.
Use event.OffsetX and event.OffsetY if you are using ClientX and ClientY.
Had many difficulties with this, and still not sure I understand why this works, but this calculation of x and y works for me.
let canvas = document.querySelector('canvas');
let x = (event.offsetX / canvas.clientWidth) * 2 - 1;
let y = -(event.offsetY / canvas.clientHeight) * 2 + 1;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With