7

I have a 3D object with the position(x,y,z). How can I calculate the screen position(x,y) of that object?

I have search for it and one solution is that I have to find out the projection matrix then multiply 3D position point by this matrix to project it onto some 2D viewing surface (computer screen). But I have no idea how to find this matrix in Three.js.

I try a convert function like this but it give incorrect result

function Point3DToScreen2D(point3D){
            var screenX = 0;
            var screenY = 0;
            var inputX = point3D.x - camera.position.x;
            var inputY = point3D.y - camera.position.y;
            var inputZ = point3D.z - camera.position.z;
            var aspectRatio = renderer.domElement.width / renderer.domElement.height;
            screenX = inputX / (-inputZ * Math.tan(camera.fov/2));
            screenY = (inputY * aspectRatio) / (-inputZ * Math.tan(camera.fov / 2));
            screenX = screenX * renderer.domElement.width;
            screenY = renderer.domElement.height * (1-screenY);
            return {x: screenX, y: screenY};
        }

Thank in advance.

gman
  • 100,619
  • 31
  • 269
  • 393
user1533481
  • 456
  • 3
  • 8
  • 16

3 Answers3

12

For me this function works (Three.js version 69):

function createVector(x, y, z, camera, width, height) {
        var p = new THREE.Vector3(x, y, z);
        var vector = p.project(camera);

        vector.x = (vector.x + 1) / 2 * width;
        vector.y = -(vector.y - 1) / 2 * height;

        return vector;
    }
Julia Savinkova
  • 573
  • 8
  • 18
5

I make it done by this code at last:

Note: div parameter = canvas dom element.

function toScreenXY( position, camera, div ) {
            var pos = position.clone();
            projScreenMat = new THREE.Matrix4();
            projScreenMat.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
            projScreenMat.multiplyVector3( pos );

            var offset = findOffset(div);

            return { x: ( pos.x + 1 ) * div.width / 2 + offset.left,
                 y: ( - pos.y + 1) * div.height / 2 + offset.top };

        }
function findOffset(element) { 
          var pos = new Object();
          pos.left = pos.top = 0;        
          if (element.offsetParent)  
          { 
            do  
            { 
              pos.left += element.offsetLeft; 
              pos.top += element.offsetTop; 
            } while (element = element.offsetParent); 
          } 
          return pos;
        } 
user1533481
  • 456
  • 3
  • 8
  • 16
  • I appreciate the attempt as this is a problem that does not seem to have any documented solution, but I was not able to get this to provide accurate coordinates. – BishopZ Jul 20 '12 at 19:30
  • Could you give more detail about your case? – user1533481 Jul 24 '12 at 07:32
  • Thank you and here is my write-up: http://stackoverflow.com/questions/11586527/converting-world-coordinates-to-screen-coordinates-in-three-js-using-projection – BishopZ Jul 24 '12 at 13:53
  • I believe your inaccurate coordinates problem come from incorrect div (3rd parameter) input. Anyway, seem that you found your answer. Congratulation! – user1533481 Jul 25 '12 at 03:09
-1

Check out the source at the demo: http://stemkoski.github.com/Three.js/Mouse-Over.html

The object that I believe you are interested in is THREE.Projector(); you can use this, for example, for automating calculations that create rays from the location of mouse cursor on the screen and project it into the scene.

Stemkoski
  • 8,936
  • 3
  • 47
  • 61
  • Thank for replying, Lee. Assume that I had a Ray that its origin is the object's position, and its direction is to the screen. Then which object the ray will intersect to return to me the (x,y) of the object on the screen? Thanks. – user1533481 Jul 19 '12 at 08:44