This post is part of my Game Math Series.

### Cross Product of What?

No, you didn’t hear me wrong. I did say cross product of **2D vectors**. So the cross product of two 3D vectors is a 3D vector, which is the **rotation axis** of rotating the first vector to match the second vector with the **smallest rotation angle possible** (less than 180 degrees).

However, the “cross product” of two 2D vectors is not a 2D vector; instead, it is a scalar. How does this work? The cross product is basically treating the 2D vectors like 3D vectors with their z-component equal to zero, and the result is the z-component of the resulting 3D vector. Here’s what the implementation in C++ looks like:

// not the most efficient implementation float cross(const Vec2 &a, const Vec2 &b) { Vec3 v1(a.x, a.y, 0.0f); Vec3 v2(b.x, b.y, 0.0f); return cross(v1, v2).z; }

Since the z-components of the 3D vectors built from 2D ones are zeros, the x-component and y-component of the 3D cross product are zeros. Thus, we can further optimize the implementation:

float cross(const Vec2 &a, const Vec2 &b) { // just calculate the z-component return a.x * b.y - a.y * b.x; }

### What’s So Special About It?

We’ve see what the cross product of 2D vectors does, but what does it mean geometrically? As I said before, the cross product of two 3D vectors gives you a rotation axis to rotate first vector to the second. We’re just extending the 2D space into 3D and perform the cross product, where the two vectors lie on the X-Y plane. The resulting 3D vector is just a rotation axis. However, since the two vectors are on the X-Y plane, this rotation axis would cause rotation only on the X-Y plane, so the axis is always parallel to the Z-axis.

If we reduce our dimension from 3D back to 2D, the rotation represented by such rotation axis is a rotation that is either clockwise (CW) or counter-clockwise (CCW). In other words, The **sign** of the cross product of 2D vectors tells you whether the second vector is on the **left** or **right** side of the first vector (the direction of the first vector being **front**).

This is useful, because sometimes we just need to decide whether something is on your left or right in 2D. I used cross products of 2D vectors in Astrobunny (my first DigiPen freshmen game project), to decide whether the mouse cursor is on the left or right of the ship and determine which direction to steer.

Pingback: Studio 2: Making a Vector library | Caleb's Blog

This is actually just an exterior product (http://en.wikipedia.org/wiki/Exterior_algebra).

The idea is that like terms when they are squared i.e they become ‘scalars’. These go into the scalar product, or dot product, or inner product. ( these are all different names for the same thing).

(a*e1 + b*e2) * (c*e1 + d*e2) = ac*e1^2 + ad*e1e2 + bc*e2e1 + bd*e2^2

now since e1^2 = 1 and e2^2 = 1 :

= (ac + bd) + ad*e1e2 + bc*e2e1

the exterior product is also defined to be skew symmetric, which means e1e2 = -e2e1, this means:

= (ac + bd) + (ad – bc)e1e2

the (ad – bc) is exactly what you get when take the determinant of a matrix, and when you multiply complex numbers. In fact the multiplication formula for complex numbers is almost the same except e2^2 = i^2 = -1. So you will get (ac – bd) instead. if you let e1^2 = 0 and e2^2 = 0 you will get your familiar cross product since the scalar part of the product vanishes.

This same tricks works in any dimension. With 3 dimensions you will get a cross product, with 4 dimensions you will get a 6 dimension vector as a result.

Thanks for the info. I never thought about it this way.

Nevertheless, I’d still prefer viewing them as cross products of 3D vectors with the z component set to zero, since it’s simpler to picture in mind. ðŸ™‚

Of course you can use any mental mapping you want ðŸ™‚ Another way you can use this is derive the quaternion algebra, and also you could check what happens if you let i^2 = j^2 = k^2 = 1, rather then -1 as hamilton defined it.

You lost me. Can you elaborate on that? I don’t think we need to go that far to utilize cross products in 2D. Sounds like an overkill to me.

You’re right, I’m kind of going on a tangent here ^^. I mean that quaternions are generated by this same idea:

Lets say you have a 3d vector whose components you denote with e0, e1, e2 and the rule that that when you square components they become negative scalars, like e0^2 = e1^2 = e2^2 = -1.

now when you multiply (a*e1 + b*e2 + c*e3)(e*e1 + b*e2 + c*e3) you end up with the quaternion product, along with the rules that:

e1e2 = -e2e1 = e3

e2e3 = -e3e2 = e1

e3e1 = -e1e3 = e2

Again, if you agree that e^1 = e^2 = e^3 = 0 you will get a cross product, if you let e^1 = e^2 = e^3 = 1 you will get the cross product + dot product, if you let e^1 = e^2 = e^3 you will get the quaternion product, which also lets you “divide” vectors.

Correction: denote the components with e0,e1,e2 and e^1 = e^2 = e^3 = -1 for the quaternion product.

I should learn not to type so fast >.>

Just citing another use of the 2D cross product, which is to determine the facing of a given set of vertices, say, a triangle or a quad (usually the former in simpler cases) on screen space (not 3D – you would expect much more to be involved really…)

As it turns out, given three vertices/points p1 thru p3, you can use the 2D cross product to do simple determining of render culling (that is, do you render this triangle if the plane it resides on has normal pointing -away- from you i.e. you should not ever be able to see it? Hint: no). This, however, is implementation dependent – you can either choose clockwise culling or counterclockwise culling, but you have to be consistent about it. This choice is usually affected by the API you use for graphics.

On a more complicated note, what I just said is mostly derived from the implicit plane equation Ax +By + Cz – D = 0, but it will be a bit much to talk about in the context of a reply.

Are you saying that you can use the “2D cross product” to determine if three vertices are listed in clockwise or counterclockwise order? I guess the sign of imaginary part of (c-b)/(b-a) has the answer, so in that sense it’s true.

However, there is a more informative way to determine the orientation: Compute the determinant of

(x1 y1 1)

(x2 y2 1)

(x3 y3 1)

The result is half the area of the triangle, with the sign indicating the orientation.