3D Math Quick Reference

I am writing this quick reference because I always need to know this stuff off the cuff for someone and sometimes I forget it when my brain is tired. Some of these are very simple but I just try to put each one down as I think of it so that those that are newer may be able to use this too.

  • Points are represented as Vectors in 3-Space (Vector 3)
  • Directions here are known elsewhere as unit vectors, we will use them synonymously.
  • Rotations can be Quaternions or unit vectors but will always be designated.
  • The default coordinate system will be left handed unless stated otherwise.
  • There are some Unity specific things in here, but in general these techniques should work no matter what engine you are working with.

What's the distance between two points?

Given two vectors, V1 and V2 it's the magnitude (norm) of V2 - V1. In Unity, that's the magnitude property on Vector3. For quickly comparing the magnitude of two vectors you can use the sqrMagnitude property to compare.

Octave code:

octave-3.4.0:47> V1 = [0 2]; V2 = [3 2];
octave-3.4.0:49> V3 = V2 - V1
V3 =
   3   0
octave-3.4.0:50> norm(V3)
ans =  3
octave-3.4.0:51> V3/norm(V3)
ans =
   1   0

Most engines including Unity have properties or functions that get you that last calculation which would be the direction of V3. In Unity it's the normalized property on Vector3 (or Vector2).

Unity code:

Vector2 V1 = new Vector2(0,2);
Vector2 V2 = new Vector2(3,2);
Vector2 V3 = V2 - V1;
Debug.Log (V3);
Debug.Log (V3.normalized);

What is the direction expressed as a unit vector between two points?

It seems like there should be a Function "DirectionTo(Vector3 other)" on Vector3, but there is not so this is really easy…

Octave code:

octave-3.4.0:60> startPoint = [11 11 11]; targetPoint = [33 33 33];
octave-3.4.0:61> directionToTarget = (targetPoint - startPoint)/norm(targetPoint - startPoint)
directionToTarget =
   0.57735   0.57735   0.57735
octave-3.4.0:62> distanceFromStartToTarget = norm(targetPoint - startPoint)
distanceFromStartToTarget =  38.105
octave-3.4.0:63> startPoint + (directionToTarget * distanceFromStartToTarget)
ans =

   33   33   33

You don't need all that of course (just the first two lines), but just playing around with it helps you see how it all works.

I have a Quaternion but just want a Vector3. How do I get that?

Just multiply the quaternion times the world forward vector. This will return the quaternion's axis of rotation which is essentially what you want.

Quaternion q1 = Quaternion.AngleAxis(45f, Vector3.right);
Vector3 direction = q1 * Vector3.forward;

Yields (0.0, -0.7, 0.7). Similarly, to find the axis representing the "X" axis of rotation for the quaternion in question us Vector3.right instead of forward. This is also useful for quickly finding a perpendicular axis to an unknown rotation. In our previous example after rotating 45 degrees about X, multiplying by Vector3.right gives us (1.0, 0.0, 0.0) still and by Vector3.up gives us (0.0, 0.7, 0.7)

How do you project points onto a plane?

If I have two known points or I know a point and a direction. If I have a line between my two known points or a Ray that is in a known direction from a known point I can find where it enters a plane either between the points or in an arbitrary distance in the direction. Think of firing bullets through a pane of glass at an arbitrary angle at a target on the other side and you need to know how to place the bullet holes.

This problem has tons of uses one of them I have seen recently is you have a point A somewhere inside of a concave enclosure and a camera somewhere outside of the enclosure. I want to find the distance and the coordinates where the line between the camera and the object cross the opening of the enclosure (if they are not clipped by the enclosure). Luckily for Unity folks, most of these calculations are handled for you in the Plane structure but it's nice to see this work so here is a snippet in Octave of a simple example.

Octave code:

octave-3.4.0:24> rayOrigin = [0 0 0]
rayOrigin =
   0   0   0
octave-3.4.0:25> rayDirection = [1 1 0]/norm([1 1 0])
rayDirection =
   0.70711   0.70711   0.00000
octave-3.4.0:26> planeNormal = [0 1 0]
planeNormal =
   0   1   0
octave-3.4.0:27> ratioA = dot(rayDirection, planeNormal)
ratioA =  0.70711
octave-3.4.0:28> ratioB = (-1 * dot(rayOrigin,planeNormal)) - (-1)
ratioB =  1
octave-3.4.0:30> ratioB/ratioA
ans =  1.4142

And of course after you have found the distance the coordinates will follow (approximately) by simply multiplying the direction vector by the distance. This usually works pretty well but if someone knows a more accurate way to calculate this please contact me.

Octave code:

octave-3.4.0:42> 1.4142 * rayDirection 
ans =

   0.99999   0.99999   0.00000

How to project a vector onto a flat surface?

This is a pretty common problem and most engines will give this to you. Projection is described more rigorously here. Unity has a Vector3.Project method that does this for you. Here is an example:
For simplification and demonstration my camera is at the origin looking along the positive X axis in direction n, e.g. [1 0 0]. A point is defined by a vector V and is 10 units along the X axis and 10 units up the Y axis with no Z component, e.g. [10 10 0]. I want to draw a line on the ground from the camera to directly under the point in the sky as if the line to V were to cast a shadow on the ground under it if the light were perfectly overhead. This is easy to work out if the problem is framed this way but if n and V are more arbitrary here is how this is done
Octave code:

octave-3.4.0:2> n = [1 0 0]; V = [10 10 0];
#The dot in the numerator has the effect of squaring the magnitude of n
octave-3.4.0:3> n*(dot(V,n)/dot(n,n))
ans =
   10    0    0

Unity code:

Vector3 n = new Vector3(1,0,0);
Vector3 v = new Vector3(10,10,0);

(10.0, 0.0, 0.0)

I found later a great mathematical description for this if you are interested in learning more about why this works.

Unless otherwise stated, the content of this page is licensed under GNU Free Documentation License.