Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raycaster displaces object intersections when pitching camera in three.js

I created a raycaster that allows me to pick an object from the scene with my mouse like such:

this.raycaster = new THREE.Raycaster()

// then in onMouseDown event
this.raycaster.setFromCamera(this.mouse, this.camera)
let intersects = this.raycaster.intersectObjects(this.scene.children)

It works as expected when I translate the camera and when I yaw the camera, however, once I pitch the camera, the raycaster intersects the object away from where the object is rendered on screen. If I look above the object, the raycaster intersects the object above where it is rendered. If I look below the object, the raycaster intersects the object below where it is rendered.

this.yaw = new THREE.Object3D()
this.pitch = new THREE.Object3D()
this.camera = new THREE.PerspectiveCamera(70, this.width / this.height, 0.01, 50)

this.yaw.add(this.pitch.add(this.camera))
this.scene = new THREE.Scene().add(this.yaw)

// then in onMouseMove event
if (this.state === this.STATE.PAN) {
    this.yaw.translateX(-this.mouseDelta.x)
    this.yaw.translateZ(-this.mouseDelta.y)
}
if (this.state === this.STATE.ROTATE) {
    this.yaw.rotation.y -= this.mouseDelta.x
    this.pitch.rotation.x -= this.mouseDelta.y
}

I tried disabling all transformations except the pitch and the problem still persists. I think the problem may be with the raycaster and not the objects themselves, as it wouldn't make sense for the objects to render in one location but be intersected in another.

What am I doing wrong? Is the raycaster maybe not casting from the camera's origin after rotating?

like image 340
Gibran Garcia Avatar asked Nov 07 '22 19:11

Gibran Garcia


1 Answers

The raycaster was detecting an intersection when I clicked above the object while pointing the camera above the object because the mouse.y coordinates were not normalized correctly.

// Incorrect
this.mouse.y = (e.clientY / window.innerHeight) * 2 - 1
// Correct
this.mouse.y = -(e.clientY / window.innerHeight) * 2 + 1

By excluding the negation, my mouse.y position was effectively mirrored within the scene. So if I clicked the top most point of the scene, the raycaster would be mirrored to detect intersections at the bottom most point of the scene.

This wasn't an issue when there was no pitching because I was testing on box geometry placed level to the camera. Thus any mirroring done onto the raycaster would still detect a collision since the geometry was symmetric.

like image 163
Gibran Garcia Avatar answered Nov 15 '22 11:11

Gibran Garcia