- Home /
Project a Vector3 onto a plane, orthographically
How would I go about doing this? I have a Vector3 point, and a Vector3 normal defining the plane's direction. When I google this, I find an awful lot that takes projection into account, and camera stuff. But I don't need this for anything visual. I just need to convert from 3D to 2D.
If I was using Vector3.up, this would be easy; I would just 0 out the Y coordinate. But if I have a normal like (0.8, 0.1, 0.1), I don't know what to do.
Ultimately, I want to project four vectors from 3D space to 2D space so I can perform a line segment intersection test on them in 2D.
Answer by Bunny83 · Nov 12, 2015 at 06:16 PM
You simply project your vector onto the normal and subtract the result from your original vector. That will give you the projected vector on the plane. If you want to project a point to a plane you first need to calculate the relative vector from a point on that plane.
Vector3 planeOrigin;
Vector3 planeNormal;
Vector3 point;
Vector3 v = point - planeOrigin;
Vector3 d = Vector3.Project(v, planeNormal.normalized);
Vector3 projectedPoint = point - d;
Thanks for the reply! As I read your code sample though, it makes me realize that I am missing a step. In order to do the 2D line calculation, I need one of the axes to be 0. It seems to me that the best way to do that would be to add an additional step to rotate the projected point to be oriented with Vector3.up. so for instance, I project my vectors, but then after I project them on the plane, I rotate the entire plane. How would I do that?
EDIT: n/m. It is a bit out of scope of the question, and I found a function that I forgot I had for line segment intersection tests on a plane that does not care about the orientation of the plane. the projection works though.
If you want to do the rotation you need to define an up direction on your plane. Then you can calculate the rotation using Quaternions using your up direction and your plane normal. Using the inverse you rotate your projected vector back into the xy plane. You can also rotate the vector directly and then cast it to Vector2, simply ignoring the z component.
http://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html http://docs.unity3d.com/ScriptReference/Quaternion.Inverse.html
Well, if you want to transform your point into a seperate 2d space you might simply want to use an empty gameobject that is rotated so one axis is aligned with your normal. That way you can use the other two axis as your 2d space. The advantage is at you can simply use InverseTransformPoint to transform a world space point into local space. In local space you can simply "null" the normal axis just like you mentioned in your question.
For example the easiest approach is to use the z axis as normal. Here you can simply use LookRotation.
Transform emptyGO;
Vector3 normal;
Vector3 planeOrigin;
Vector3 point;
emptyGO.position = planeOrigin;
emptyGO.rotation = Quaternion.LookRotation(normal, Vector3.right);
Vector3 localPoint = emptyGO.InverseTransformPoint(point);
localPoint.z = 0; // project to the plane.
Inside the local space of the transform the plane actually isn't rotated. The local coordinates behave like it's not rotated at all. The local coordinates are in the local x-y plane and represent your 2d coordinates. If you need a point back in world space, just transform it back:
Vector3 pos = emptyGO.TransformPoint(localPoint);
That will give you the proper 3d point in the world for the given 2d local point.
Answer by elenzil · Nov 12, 2015 at 06:18 PM
Your Vector3 represents a point in world-space, and you want to project it directly onto a plane ?
so say,
vP = the Vector3 of the point on the plane.
vN = the Vector3 of the normal of the plane.
vQ = the Vector3 of the point you want to project.
create a new vector, vPQ that's the vec from vP to vQ: vPQ = vQ - vP.
now project vPQ onto the normal: dot = vPQ DOT vN. vQN = vN * dot.
vQN is now the projection of your point onto the normal. now we subtract vQN from vQ to pull that vec down onto the plane:
vAnswer = vQ - vQN.