Getting camera perpendicular plane

Hi everyone!

I am trying to get the following value: for any vector in 3D space (the blue one), I need to project it on the green plane so I can compute the angle alpha on this green plane between the projected vector (purple) and the z axis of the camera.
So far, my best attempt was by first trying to get the green plane, whichever the camera position is in 3D space, assuming that the green plane normal is pointing to +y :

var greenPlane= new THREE.Vector3( 0, 1, 0 );
greenPlane.applyQuaternion( camera.quaternion );

Then get my purple vector by the following:

purpleVector = blueVector.projectOnPlane(greenPlane)

But the values get by tracing the purple vector are incorrect. My final purpose is to detect if the purple vector is pointing towards left or right of the screen, so I can correctly place a label at its extremity.


Thanks for any possible hint!

If you project a vector on a plane, the vector lies on that plane. Or in other words: It is coplanar to the given plane. It looks like this:


Unfortunately, i don’t know a generic way in order to calculate your desired outcome.

Hi Mugen,

Yes and this is what I’m achieving with

purpleVector = blueVector.projectOnPlane(greenPlane)

My concern is how to get the vector representing the green plane. The 2 first line of codes don’t give me this.

Um, if you transform the original vector into eye space, couldn’t you just calculate the angle alpha like this:

const zAxis = new THREE.Vector( 0, 0, - 1 ); // default view direction
purpleVector.applyMatrix4( viewMatrix ); // assuming purpleVector is in world space
const angle = Math.acos( purpleVector ) ); // calculate angle in radians

I am not familiar with applyMatrix4 function (very few tutos about how to use it).
Does this apply a transformation to the blue vector so we get its coordinates in the camera/view coordinates? And I am confused, you mention purple, but for me I can’t get the purple unless I am figuring out what is the green plane.

But if I can project the blue vector directly to the camera plane, then I can use cos to see if it’s positive or negative yes. I am only concerned about left or right with respect to the view (screen).

Ah, now i see. But if you perform all calculations in eye space, the plane normal should be var greenPlane= new THREE.Vector3( 0, 1, 0 );.

Yes Michael. And this is my first line of code actually!
So maybe this second one is wrong and I should use ApplyMatrix4 instead?

greenPlane.applyQuaternion( camera.quaternion );

I would try this (camera.matrixWorldInverse is the view matrix):

// ensure matrix is up to date
// transform original vector into eye space, assuming blue vector is in world space
blueVector.applyMatrix4( camera.matrixWorldInverse ); 

After that, project the vector on the plane.

You mean the camera plane then, not the green one? (because the green hasn’t been transformed yet)

I thought the green one. In eye space, it has always a normal vector of ( 0, 1, 0 ).

The green one has only be declared var greenPlane= new THREE.Vector3( 0, 1, 0 ). If I move the camera it doesn’t go along. If I want it to actually be the green plane I have to apply a transformation in respect to the camera position, and this was (supposedly) achieved by greenPlane.applyQuaternion( camera.quaternion );

But following your previous idea, projecting the blue directly to the view should work.

blueVector.applyMatrix4( camera.matrixWorldInverse );
const zAxis = new THREE.Vector( 0, 0, - 1 );
blueVectorProject= blueVector.projectOnPlane(zAxis );
// then I compute the cos value between blueVectorProject and view x axis

Maybe you can provide a fiddle with the code. That makes it easier to verify the solution.

I have to try yes, not familiar with it. Good opportunity to start!

BTW, do you know a good source where we can learn about all these Vector and Matrix manipulations for the 3D world. I didn’t know what matrixWorldInverse was representing for instance.

Thanks Michael (I should all put you name on the credits of our projects :grin:)

1 Like

This book is one of my favorites:

Ordered. Thanks!