1

I use function like this in three.js 69

  function Point3DToScreen2D(point3D,camera){
    var p = point3D.clone();
    var vector = p.project(camera);

    vector.x = (vector.x + 1) / 2 * window.innerWidth;
    vector.y = -(vector.y - 1) / 2 * window.innerHeight;

    return vector;

  }

It works fine when i keep the scene still. But when i rotate the scene it made a mistake and return wrong position in the screen.It occurs when i rotate how about 180 degrees.It shoudn't have a position in screen but it showed.

I set a position var tmpV=Point3DToScreen2D(new THREE.Vector3(-67,1033,-2500),camera); in update and show it with css3d.And when i rotate like 180 degrees but less than 360 , the point shows in the screen again.Obviously it's a wrong position that can be telled from the scene and i haven't rotate 360 degrees.

I know little about the Matrix,So i don't know how the project works.

Here is the source of project in three.js:

project: function () {

        var matrix;

        return function ( camera ) {

            if ( matrix === undefined ) matrix = new THREE.Matrix4();

            matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
            return this.applyProjection( matrix );

        };

    }()

Is the matrix.getInverse( camera.matrixWorld ) redundant? I tried to delete it and it didn't work. Can anyone help me?Thanks.

aboutqx
  • 362
  • 2
  • 17
  • Duplicate: http://stackoverflow.com/questions/27409074/three-js-converting-3d-position-to-2d-screen-position-r69 – WestLangley Apr 24 '15 at 02:17
  • What is the code you are using to "rotate the scene"? – WestLangley Apr 24 '15 at 02:20
  • @WestLangley I mean there is a mistake here.I use normal rotate controll like http://threejs.org/examples/webgl_panorama_equirectangular.html – aboutqx Apr 24 '15 at 02:59
  • @WestLangley I think that is because `project` return 2 directions project.If i can have a ray cast I may get right answer,But i don't know how to intersect the screen. – aboutqx Apr 24 '15 at 03:54
  • Are you saying that `p.project( camera )` projects a point that is _behind_ the camera onto the screen? – WestLangley Apr 24 '15 at 05:10
  • Well,actually i don't know what `project` do,I guess that because of the result – aboutqx Apr 24 '15 at 05:15
  • 1
    `project()` projects the point from world space into normalized-device-coordinate (NDC) space. You are going to have to [study some math](http://stackoverflow.com/questions/11966779/learning-webgl-and-three-js/11970687#11970687). If a point is behind the camera, it can be projected into NDC space, too. Maybe that is what you are seeing. – WestLangley Apr 24 '15 at 05:22
  • yeah,master,can you give a solution ?By comparing the point's z with camera?Any better way? – aboutqx Apr 24 '15 at 05:25
  • What is the question you want the answer to? – WestLangley Apr 24 '15 at 05:34
  • I just want to avoid the other point i get.That can't represent the object's position in the scene.For me that's a wrong position. – aboutqx Apr 24 '15 at 05:36
  • Then do not call `Point3DToScreen2D()` if the point is behind the camera. – WestLangley Apr 24 '15 at 05:41
  • As i place the function that shows the point in `update`,if we can't see the object the `Point3DToScreen2D` will return a `x,y` that's out of the screen and need no more dealing with. But with above i have to judge if the object is out of screen. – aboutqx Apr 24 '15 at 05:44
  • @WestLangley the **behind** is a little bit difficult to detect for me,do you have demo?Also, you can give an answer so that i can accept it. – aboutqx Apr 24 '15 at 06:59

4 Answers4

3

You are projecting a 3D point from world space to screen space using a pattern like this one:

var vector = new THREE.Vector3();
var canvas = renderer.domElement;

vector.set( 1, 2, 3 );

// map to normalized device coordinate (NDC) space
vector.project( camera );

// map to 2D screen space
vector.x = Math.round( (   vector.x + 1 ) * canvas.width  / 2 ),
vector.y = Math.round( ( - vector.y + 1 ) * canvas.height / 2 );
vector.z = 0;

However, using this approach, points behind the camera are projected to screen space, too.

You said you want to filter out points that are behind the camera. To do that, you can use this pattern first:

var matrix = new THREE.Matrix4(); // create once and reuse

...

// get the matrix that maps from world space to camera space
matrix.getInverse( camera.matrixWorld );

// transform your point from world space to camera space
p.applyMatrix( matrix );

Since the camera is located at the origin in camera space, and since the camera is always looking down the negative-z axis in camera space, points behind the camera will have a z-coordinate greater than zero.

// check if point is behind the camera
if ( p.z > 0 ) ...

three.js r.71

WestLangley
  • 92,014
  • 9
  • 230
  • 236
  • Well,Maybe i should tell more clearly.What i'm trying to do is showing the point with css3d and the point will move like that it's in the scene.So i should figure out when the point is out of camera view without changing the point's position.I will create a fiddle and you can edit it.Thank for your help. – aboutqx Apr 25 '15 at 02:36
  • I've try `if( camera.target.z-(-2500)<0)`,-2500 is the `z` of point,but it shows a bug .The point disappears before the 3d point out of the camera view. – aboutqx Apr 25 '15 at 03:24
  • I corrected my answer... Sorry, I can only answer questions about three.js. I cannot debug your code for you. I hope you understand. – WestLangley Apr 25 '15 at 03:34
  • this works fine:http://jsfiddle.net/aboutqx/0sgh361q/18/ ,using `Frustum` to determine if the point is inside the camera's view – aboutqx Apr 25 '15 at 05:00
0

Like the example above but you can check vector.z to determine if it's in front.

var vector = new THREE.Vector3();
var canvas = renderer.domElement;

vector.set( 1, 2, 3 );

// map to normalized device coordinate (NDC) space
vector.project( camera );

// map to 2D screen space
vector.x = Math.round( (   vector.x + 1 ) * canvas.width  / 2 ),
vector.y = Math.round( ( - vector.y + 1 ) * canvas.height / 2 );

//behind the camera if z isn't in 0..1 [frustrum range]
if(vector.z > 1){
   vector = null;
}
Cam
  • 1
  • This is not true. The mapping is not continuous. Points beyond the far plane also map to z-values greater than 1. – WestLangley May 06 '15 at 14:12
0

To delve a little deeper into this answer:

// behind the camera if z isn't in 0..1 [frustrum range]
if(vector.z > 1){
   vector = null;
}

This is not true. The mapping is not continuous. Points beyond the far plane also map to z-values greater than 1

What exactly does the z-value of a projected vector stand for? X and Y are in normalised clipspace [-1,1] , what about z?

Would this be true?

projectVector.project(camera);

var inFrontOfCamera = projectVector.z < 1;
René
  • 71
  • 7
0

Since the camera is located at the origin in camera space, and since the camera is always looking down the negative-z axis in camera space, points behind the camera will have a z-coordinate greater than 1.

//check if point is behind the camera
if ( p.z > 1 ) ...

NOTICE: If this condition is satisfied, then the projected coordinates need to be centrosymmetric

{x: 0.233, y: -0.566, z: 1.388}
// after transform
{x: -0.233, y: 0.566, z: 1.388}
owlcity
  • 1
  • 1