4 thoughts on “unproject – How to get the real position on ‘screen(top, left)’ of specific 3d object?

  1. Yeah, camera.matrix needs to be replaced now with camera.matrixWorldInverse.
    Try with this:

    toScreenXY: function ( position, camera, jqdiv ) {
    
        var pos = position.clone();
        projScreenMat = new THREE.Matrix4();
        projScreenMat.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
        projScreenMat.multiplyVector3( pos );
    
        return { x: ( pos.x + 1 ) * jqdiv.width() / 2 + jqdiv.offset().left,
             y: ( - pos.y + 1) * jqdiv.height() / 2 + jqdiv.offset().top };
    
    }
  2. Incase anyone still needs this after upgrading…

    function screenXY(obj){
    
      var vector = obj.clone();
      var windowWidth = window.innerWidth;
      var minWidth = 1280;
    
      if(windowWidth < minWidth) {
        windowWidth = minWidth;
      }
    
      var widthHalf = (windowWidth/2);
      var heightHalf = (window.innerHeight/2);
    
      vector.project(camera);
    
      vector.x = ( vector.x * widthHalf ) + widthHalf;
      vector.y = - ( vector.y * heightHalf ) + heightHalf;
      vector.z = 0;
    
      return vector;
    
    };
  3. Ok, very old issue, but I had a nested object, which didn’t work with the above code.
    My case was: I wanted the real x-and-y (and z) position for a nested object after rendering, so I adapted the above examples.
    Please note:

    1. You now give the whole object as an argument instead of only the object.position in the above examples.
    2. Also this will only work after the renderer has done it’s job and called
    3. It also works for non-nested objects, but it will do a few calculations too many.
    4. It also gives you a screen-Z, which can be used to sort domElements or zSort labels.
      The screen-z relative is between 0 and 1, relative to the front and back clipping planes of the camera/renderer and this works fine for my purposes (sorting).
    5. You can get the renderers current width and height by renderer.domElement.width and renderer.domElement.height.
    scene.updateMatrixWorld(); 
    

    and

    parent.updateMatrixWorld(); 
    
    function nestedObjecttoScreenXYZ(obj,camera,width,height)
    {
    	var vector = new THREE.Vector3();
    	vector.setFromMatrixPosition( obj.matrixWorld );
    	var widthHalf = (width/2);
    	var heightHalf = (height/2);
    	vector.project(camera);
    	vector.x = ( vector.x * widthHalf ) + widthHalf;
    	vector.y = - ( vector.y * heightHalf ) + heightHalf;
    	return vector;
    };

    typical call:

    var screenpos=NestedObjecttoScreenXY(object,camera,renderer.domElement.width,renderer.domElement.height,true);

    Just in case anyone runs into the same problem.

Comments are closed.