Search code examples
three.jsaframe

In A-Frame/THREE.js, is there a method like the Camera.ScreenToWorldPoint() from Unity?


I know a method from Unity whichs is very useful to convert a screen position to a world position : https://docs.unity3d.com/ScriptReference/Camera.ScreenToWorldPoint.html

I've been looking for something similar in A-Frame/THREE.js, but I didn't find anything.

Is there an easy way to convert a screen position to a world position in a plane which is positioned a given distance from the camera ?


Solution

  • This is typically done using Raycaster. An equivalent function using three.js would be written like this:

    function screenToWorldPoint(screenSpaceCoord, target = new THREE.Vector3()) {
    
      // convert the screen-space coordinates to normalized device coordinates 
      // (x and y ranging from -1 to 1):
    
      const ndc = new THREE.Vector2()
      ndc.x = 2 * screenSpaceCoord.x / screenWidth - 1;
      ndc.y = 2 * screenSpaceCoord.y / screenHeight - 1;
    
      // `Raycaster` can be used to convert this into a ray:
    
      const raycaster = new THREE.Raycaster();
      raycaster.setFromCamera(ndc, camera);
    
      // finally, apply the distance:
    
      return raycaster.ray.at(screenSpaceCoord.z, target);
    }
    

    Note that coordinates in browsers are usually measured from the top/left corner with y pointing downwards. In that case, the NDC calculation should be:

    ndc.y = 1 - 2 * screenSpaceCoord.y / screenHeight;
    

    Another note: instead of using a set distance in screenSpaceCoord.z you could also let three.js compute an intersection with any Object in your scene. For that you can use raycaster.intersectObject() and get a precise depth for the point of intersection with that object. See the documentation and various examples linked here: https://threejs.org/docs/#api/core/Raycaster