Convert screen 2D to world 3D coordiate system without using raycaster

I have a PlaneGeometry like a terrain in a game that is always located at y = 0 and I have a camera that can be rotated or zoomed. Is it possible to calculate the x and z of that PlaneGeometry based on the screen mouse x and y?

The raycaster does just that? You can use the raycaster without using a real plane geometry if that’s what you’re looking for, something like:

const worldPosition = new THREE.Vector3;
const plane = new THREE.Plane( new THREE.Vector3( 0.0, 1.0, 0.0 ) );

raycaster.setFromCamera( coords, camera );
raycaster.ray.intersectPlane( plane, worldPosition );

I suppose you mean on?

1 Like

Are you using a height map?

Yes, my english sorry.

How do you calculate coords?

And why 0.0, 1.0, 0.0 for the plane? y is the one actually at 0.

Not sure what is a height map. So I guess I’m not.

@Enzo
Ah, I see. :slight_smile: So, then follow @Fyrestar’s answer.

It just work perfect. I don’t understand it well but I’m ok with that xD.
Thank you.

For someone a bit lost like me, this is the whole snippet I’m using:

function screenToWorld({ x, y, canvasWidth, canvasHeight, camera }) {
    const coords = new THREE.Vector3(
        (x / canvasWidth) * 2 - 1,
        -(y / canvasHeight) * 2 + 1,
        0.5
    )
    const worldPosition = new THREE.Vector3()
    const plane = new THREE.Plane(new THREE.Vector3(0.0, 1.0, 0.0))
    const raycaster = new THREE.Raycaster()
    raycaster.setFromCamera(coords, camera)
    return raycaster.ray.intersectPlane(plane, worldPosition)
}

window.addEventListener('mousemove', event => {
    const { clientX, clientY } = event
    const pos = screenToWorld({
        x: clientX,
        y: clientY,
        canvasWidth: window.innerWidth,
        canvasHeight: window.innerHeight,
        camera
    })
    console.log(pos)
})

You should put all the objects outside your screenToWorld function as you don’t need to create them everytime you call it, like:

const coords = new THREE.Vector3;
const worldPosition = new THREE.Vector3()
const plane = new THREE.Plane(new THREE.Vector3(0.0, 1.0, 0.0))
const raycaster = new THREE.Raycaster()

function screenToWorld({ x, y, canvasWidth, canvasHeight, camera }) {

	coords.set(
		(x / canvasWidth) * 2 - 1,
		-(y / canvasHeight) * 2 + 1,
		0.5
	)
	raycaster.setFromCamera(coords, camera)
	return raycaster.ray.intersectPlane(plane, worldPosition)
}
2 Likes