As Maximus Minimus notes in the comments, when we have a mesh without normal vectors (say just raw vertex positions from a procedural generator or 3D scanned point cloud), we can determine a normal vector for each triangle of the mesh using the cross product of two of the triangle's edges, ensuring the vector is perpendicular to the triangle surface.
The magnitude of such a vector will be equal to twice the area of the triangle, which we can exploit when averaging the normals around each vertex to make vertex normals. The area weighting means that dividing a big triangle into many small skinny triangles won't unfairly skew the resulting normal.
These vertex normals can then be used to apply lighting and shading when rendering the surface, or match an object's orientation to its underlying surface, or compute a ricochet off the surface, etc.
We can use a simplified version of this cross product between a triangle's edges to check whether it's a front face or a back face during rendering.
After transforming the vertices to normalized device coordinates, we can compute just the z component of the cross product and check its sign to determine whether the triangle is facing toward the camera, or away. In many shaders this will be used to cull triangles from the back sides of objects, roughly halving the fragment shading/blending costs for them.
Generating a Coordinate Basis
Often in games we want an object to face in a particular direction — like pointing a camera at a target or aiming a character's head/eyes/weapon with IK, or spawning a projectile oriented along its flight direction.
But one direction vector along isn't quite enough information to fully specify an orientation — it uses up two degrees of rotational freedom, but we still have one degree of freedom left: spinning the object around that direction vector.
So to get an unambiguous orientation, we need to extend this direction into a basis. One common way to do this uses the cross product. In a left-handed coordinate system, that might look like:
desiredRight = normalize(cross(worldUp, desiredForward))
desiredUp = cross(desiredForward, desiredRight)
(This has a singularity when you want to look exactly up or down, so those edge cases need to be handled separately — usually still with a cross product)
You can use the trio of right/up/forward vectors formed this way as the columns of a rotation matrix, or convert them to a quaternion.
Applying a Torque
When a force is applied to a physics object at an offset from its center of mass, it should impart some angular momentum to the object, making it rotate.
We can calculate the amount and direction of spin using torque:
torque = cross(offsetFromCenter, force)
This acts as the angular equivalent of force, and can be integrated into angular momentum/angular velocity by the physics engine similar to how regular linear force gets integrated into linear momentum/linear velocity.
Matrix Determinants and Inverses
A handy shortcut to computing the determinant of a 3x3 matrix is the scalar triple product. If vectors
c are the rows of your matrix, then:
determinant = dot(cross(a, b), c)
You can find a fuller mathematical treatment of this elsewhere, but suffice it to say that this can be handy when computing matrix inverses, like if we want to undo the transformation of an object to convert a point from world coordinates into the object's local coordinates — such as to position a bullet decal on an object at the position of a projectile collision.
This one is a bit more esoteric, but as Eric Lengyel explains in a number of GDC talks, the cross product can be thought of as being a special case of a more general "wedge product". Wedges (and their complementary anti-wedges) turn out to be powerful tools for working with constructs of different dimensions, like finding intersections between lines and planes etc., in a really elegant way.