Articles
Current series: 3D Math (Return to list of 3D Math articles)
Welcome to the second part of 3D Math Basics articles. Here I will try to explain two very important vector operations  the cross and dot product.
Cross product
Cross product is very important in 3D graphics. With it, we can calculate the normal of polygon. For those, who doesn't know what is the normal, it is a directional vector, which is perpendicular
to the plane (there is a right angle between normal and plane), in which polygon lies, so it is also perpendicular to this polygon. It is used for thousands of things, for example lighting calculations
or backface culling. And for those, who doesn't understand what is the plane, it's just a flat area in some 3D space. It can be defined by 3 points, which are not collinear  they don't lie
on the same line. Look at the picture:
So this is the plane (with yellow color):
It goes on forever, so actually this is just part of a plane. I hope you got the idea of what is the plane. When we have 3 (or more) points there, they form a triangle (or polygon). But in order to
set backface culling and achieve nice lighting effects, we need to define a normal vector. How to do it? We need to take cross product. It's always taken from two directional vectors and resulting
vector will be normal. This normal is perpendicular both to first and second directional vector. Look at this:
We've got two directions  green is P2  P1 and red is P3  P2. Now, here is how is the cross product calculated:




CVector3 vecCross(CVector3 vVector1, CVector3 vVector2)
{
CVector3 vCross; // Here we will store it // Get the X value
vCross.x = ((vVector1.y * vVector2.z)  (vVector1.z * vVector2.y)); // X value vCross.y = ((vVector1.z * vVector2.x)  (vVector1.x * vVector2.z)); // Y value vCross.z = ((vVector1.x * vVector2.y)  (vVector1.y * vVector2.x)); // Z value
return vCross;
}





Green vector is (0, 0, 1) and red is (1, 0, 0). If we put these vectors as parameters, the resulting vector is (0, 1, 0)  vector pointing straight up! And it is perpendicular to both vectors: Look:
I hope you now got it. But there is one problem. What if the resulting vector was (0, 1, 0)? It would be perpendicular too. How to know which direction will be vector pointing? Well, I heard something about
righthand rule, but I didn't get the idea of it. But I found out that it depends on whether vectors are in clockwise or anticlockwise order. The best way to explain it is an example:
Edit on 21.01.2012: I was a n00b back then, and I'm not much of a pro right now, but I should be less n00b . Righthand rule is very easy and I didn't even try to
understand it back then. Take your right hand, have thumb, index finger and middle finger be perpendicular, your thumb finger points as vVector1, your index finger as
vVector2, and middle finger shows direction of resulting vector from cross product. Take a look at wikipedia for a picture
http://en.wikipedia.org/wiki/Righthand_rule.
It's a cube. Now, we want to calculate its normals. For lighting effects and backface culling. We will take as example the red side (front):
We want its normal to be pointing to the front (so the resulting vector should have direction (0, 0, 1) ). Look at this code:




CVector3 fourNormals[4];
fourNormals[0] = vecCross(P2  P1, P3  P2);
fourNormals[1] = vecCross(P3  P2, P4  P3);
fourNormals[2] = vecCross(P4  P3, P1  P4);
fourNormals[3] = vecCross(P1  P4, P2  P1);
for(int i = 0; i < 4; i++)vecNormalize(fourNormals[i]);





Now all of the four normals are the same and are pointing to the front (to us). Of course, you don't need to calculate all 4 (or more, if polygon has more vertices), you just need to calculate one normal.
You cannot forget to normalize it, because its length probably won't be 1. Normal's length must always be 1. As you can see, it's pointing where we wanted it to point. I used counterclockwise
order. Look (green vector is normal):
Edit on 21.01.2012: Directions put here correspond with right hand rule, ignore clockwise and counterclockwise stuff .
If we would have put them in clockwise direction, normal would be (0, 0, 1). The clockwise direction would be such:
Dot Product
Another important operation is dot product. It can be used to find angle between two directional vectors. It can be used when you want to find angle to rotate some object to face another. The dot product
doesn't return a vector, it returns only a number (scalar). The dot product is calculated this way:




float vecDot(CVector3 vVector1, CVector3 vVector2)
{
return (vVector1.x * vVector2.x) +
(vVector1.y * vVector2.y) +
(vVector1.z * vVector2.z);
}





If we have only 2 dimensions, we would remove z from this formula (the dot product calculation is same for any number of dimensions, but this isn't much important here). So this is how we calculate it.
In any book that deals with math, you will find something like this about dot product:
A.B = A*B*cos theta
It means that dot product of vector A and B equals to length of A * length of B * cosine of angle between them. We want to find the angle.
From that:
cos theta = (A.B) / (A*B)
So now we have the cosine of angle. To get actual angle, we need to use arc cosine. Following code does it all:




double vecAngle(CVector3 vVector1, CVector3 vVector2)
{
float fDotProduct = vecDot(vVector1, vVector2);
float fVectorsMagnitude = vecMagnitude(vVector1) * vecMagnitude(vVector2) ;
if(fVectorsMagnitude == 0.0)return 0.0; // Avoid division by zero
double angle = acos(fDotProduct / fVectorsMagnitude);
// The angle is in radians, so convert it to degrees return angle * 180 / PI;
}





It returns angle from 0 to PI (0 to 180).
If you want to see usage of dot and cross products, check the codes of Ruined city of Verion (OpenGL Misc).
Now that's all I know about this. And I think it's enough. Yet. Maybe later it won't be enough and I will have to dive deeper into cross and dot products. I hope you
learned something from this article. If you've got any questions about this article, put them either into Message Board or email them to
michalbb1@gmail.com. And try to play around with these cross and dot products in order to fully understand them.
No comments. Be the first to comment!.
