Raycaster is detecting the intersection at an offset

I am getting this output:

I am adding a small red sphere at the point of intersection.
You can see that it is getting offset by some distance, I have already applied the solution mentioned in this thread.
Solution in a thread

Here is my code:

//
// Raycaster
//

let raycaster = new THREE.Raycaster();

const mouse = new THREE.Vector2()

window.addEventListener('mousemove', (event) => {
  var canvasBounds = renderer.domElement.getBoundingClientRect();

  mouse.x = ((event.clientX - canvasBounds.left) / (canvasBounds.right - canvasBounds.left)) * 2 - 1;
  mouse.y = - ((event.clientY - canvasBounds.top) / (canvasBounds.bottom - canvasBounds.top)) * 2 + 1;
})

let testBox = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), new THREE.MeshBasicMaterial);
testBox.position.set(-5, 5, 10);
testBox.name = 'Test Box'
scene.add(testBox)

// 
// GAME LOOP ==========================================================================
// 
const clock = new THREE.Clock();
let animate = () => {
...
...
raycaster.setFromCamera(mouse, camera)
    let boxIntersect = raycaster.intersectObject(testBox);
    console.log(boxIntersect);
    if(boxIntersect.length > 0){
      let sphereTest = new THREE.Mesh(new THREE.SphereGeometry(0.02, 32, 32), new THREE.MeshBasicMaterial({color:'red'}));
      sphereTest.position.set(boxIntersect[0].point.x, boxIntersect[0].point.y, boxIntersect[0].point.z);
      scene.add(sphereTest)
    }
...
}

What’s drawing the trail on the cursor?

Not sure whats wrong in yr app… can you post the renderer setup? Are you setting devicePixelRatio? That might interact with the coordinate calculation…

@manthrax

The cursor trail is from a chrome extension: CursorTrace link

I am not setting the pixel ratio. Here is my renderer setup, along with camera:

// 
// RENDERER ============================================================================
//

const renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true });
renderer.setSize(sizes.width, sizes.height);

renderer.outputColorSpace = THREE.LinearSRGBColorSpace;
renderer.gammaOutput = true;
renderer.gammaFactor = 3;
renderer.toneMapping = THREE['LinearToneMapping'];
renderer.toneMappingExposure = 1.13;

renderer.render(scene, camera);

// 
// CAMERA =============================================================================
// 
let camera;
let perspectiveCamera = new THREE.PerspectiveCamera(
  55,
  sizes.width / sizes.height,
  0.1,
  300
);
perspectiveCamera.position.set(-8, 8, 25);
camera = perspectiveCamera

Why dont you use canvasBounds.width for this?


const mouse = new THREE.Vector2()

window.addEventListener('mousemove', (event) => {
  var canvasBounds = renderer.domElement.getBoundingClientRect();

  mouse.x = ((event.clientX - canvasBounds.left) / (canvasBounds.width)) * 2 - 1;
  mouse.y = - ((event.clientY - canvasBounds.top) / (canvasBounds.height)) * 2 + 1;
})

Updated, still same result.

Where does “sizes” come from?
Does your app have a resize handler?
Can you paste that?

Yes, I am handling resize.


const sizes = { width: window.innerWidth, height: window.innerHeight };


window.addEventListener("resize", () => {
  sizes.width = window.innerWidth;
  sizes.height = window.innerHeight;

  camera.aspect = sizes.width / sizes.height;
  camera.updateProjectionMatrix();

  renderer.setSize(sizes.width, sizes.height);
  renderer.render(scene, camera);
});

OK and one last thing to check before I just ask to see it running somewhere because otherwise I’m out of ideas…

Is your browser zoom set to 100% ?

Yes, the browser is set to 100% zoom.

I have deployed it here for you to check out. Apologies for it not being optimized as of now.
Netlify Deployed link

1 Like

There are a couple calls to .lookAt in the main loop. These are changing the camera transform, but not updating the cameras matrices. normally this isn’t a big deal since the renderer.render call updates them… but you happen to be doing your raycast after those .lookAts, but before renderer.render so the camera matrix the raycaster is using is stale.

Try this right before your setFromCamera:

camera.updateMatrix():
camera.updateMatrixWorld();
raycaster.setFromCamera(mouse, camera)

Or… move the raycasting down after renderer.render

2 Likes

Here’s how I checked it:

(abused a conditional breakpoint to inject the updateMatrix+updateMatrixWorld before the call)

2 Likes

Damn, didn’t know that.
Thank you so much. Works like a charm now.

1 Like

you’re welcome! raycasting is often very fiddly to get right.
Throwing some:
.updateMatrix()
.updateMatrixWorld()
and scene.updateMatrixWorld( true )
before key operations can be a good sanity check when things are acting weird.

1 Like