Vector Math problem

I have a vector math problem that is beyond me, I don’t really know how to begin solving it, but i’m certain it’d be no problem for someone out there.

Imagine a plane floating in 3D space, and its at a random orientation. I need to get the vector in that plane which is pointing closest to the world down direction. And it needs to be done in an efficient way ( ie using classic vector maths, not using iteration ).

I can solve the problem in english:

Convert the world down vector into the plane’s local coordinates. Then flatten that vector so that it’s within the plane. Convert vector back into world coordinates.

Hopefully that makes sense to you, and perhaps you know how to do this mathematically? Or perhaps you even know how you’d do this in code?

Many thanks.

If I understand you correctly, you wish to find the projection of world down onto an arbitrary plane?

You can do that using Vector3.Project:

projectionOnNormal = Vector3.Project(worldNormal, planeNormal);
projectionOnPlane = projectionOnNormal + worldNormal;

I based this on a quick sketch made on paper, so I’m not 100% certain it works, but you can try and check that for yourself.

The following code is a fairly short and efficient way to do what you describe in your English description of the solution:-

var planeUp: Vector3;
var planeRight: Vector3;
var planeForward: Vector3;

Vector3.OrthoNormalize(planeUp, planeRight, planeForward);	

vat mat: Matrix4x4;
mat.SetRow(0, planeRight);
mat.SetRow(1, planeUp);
mat.SetRow(2, planeForward);

var planeNearDown = mat.MultiplyPoint3x4(-Vector3.up);
planeNearDown.y = 0;
var worldNearDown = mat.inverse.MultiplyPoint3x4(planeNearDown);

I’m guessing that the orientation of your plane is determined by a vector normal to the face. The OrthoNormalize call just generates two other vectors at right angles to the normal to define a coordinate space for the plane. The first matrix multiplication transforms the world down vector to the plane’s space. The Y coordinate of the transformed point is then set to zero (ie, the vector is forced to be within the plane). The inverse matrix multiplication finally gets the vector back into world space.

So i used your code to fix the mistake in mine:

projectionOnNormal = Vector3.Project(worldNormal, planeNormal);
projectionOnPlane = worldNormal - projectionOnNormal;

It gives the same output as your matrix code now, but with far less code :P.

hey people -

I’m trying to solve a similar problem here.
I have 2 transforms (A, B) and I want to find the ‘horizontal’ direction from A to B.

So, using the examples in this thread I got it to work perfectly if A rotation stays at (0,0,0).
Any rotation, even on Y will mess up the direction from A to B.

What could be the problem here?
Oddly - if I try to draw pW it will always be zero, I can only get a visual result if I use p.

This is what I’m using which is just a C# versions of what andeee posted - tomvds’s solution also has the same problems if the transform is rotated

void OnDrawGizmos()
{
        Matrix4x4 mat = new Matrix4x4();
        mat.SetRow(0, transform.right);
        mat.SetRow(1, transform.up);
        mat.SetRow(2, transform.forward);
        Vector3 p = mat.MultiplyPoint3x4(t.position);
        p.y =0;
        Vector3 pW = mat.inverse.MultiplyPoint3x4(p);
        Gizmos.DrawLine(transform.position, transform.position + pW);
}

Have you tried Vector3.Angle?

Bryan

hey bryan -
from what I understand that will return the angle between two vectors? I’m not sure how that would help in my case, could you explain a bit more?

Still having trouble with this… and seems to be with the rotations… both Transforms can move around freely and I’ll be able to get the direction vector projected into the first transforms local space - but rotate it and it’s all off!

Am I greatly misunderstanding the problem, or are you wanting

var horizontalDifference : Vector3;

horizontalDifference = A.position - B.position;
horizontalDifference.y = 0;

If you need that in a transform’s local space for some reason there’s always Transform.TransformDirection and Transform.InverseTransformDirection. One of them will translate an input vector into a transform’s local space.

Yes, that’s almost correct… transforming the direction to the target into object space, zero the Y…

It works perfect, as do the other solutions posted here that use Vector3.Project() and even using the Matrix alternative… works great until you rotate it! :slight_smile:

If you try one of the examples you see the vector is indeed projected onto a plane defined by a transforms up vector… then try rotating it!

I do not understand why this is happening? I do admit i’m not that well versed in this sort of math!

If you send the y-zeroed vector through transformations, it’s going to be strangely oriented, as you’ve sent it through transformations.

Why do you rotate the vector after you calculate it / what vector are you expecting and what vector are you getting?

You explained you wanted the direction between two Vectors, the angle will show the angle in degrees between two Vectors. Alternatively, if you don’t care about pitch you could use Vector2.Angle by leaving out one:

var angle=Vector2.Angle(Vector2(a.transform.position.x,a.transform.position.z),Vector2(b.transform.position.x,b.transform.position.z));

At least in theory, math is not my strong suit either. If you want distance, use Vector3.Distance…

Bryan

Well, I’m not sure what I had missed on previous attempts but I got what I was after.
For a Transform transform, this will get the projected direction vector to target on transform’s local space XZ plane.

 Vector3 target = transform.InverseTransformDirection(transform.position - t.position);
        target.y = 0;
        target.Normalize();
        target = transform.TransformDirection(target);

For a real world example, imagine a camera system where you can set constraints whilst within certain zones…

Well, one of these camera zones may restrict camera movement to its local XZ (or an abitrary plane for that matter)… in this case, I needed to get the local, projected direction vector to the target so that the camera knew which way it was allowed to move in world space.

Thanks for the input everyone! :slight_smile: