3d Programming Basics: Vector addition/Subtraction
In this post, we’re going to paint a picture in our minds of what goes on as we add or subtract vectors. Then were going to see an example of a couple uses for vector addition/subtraction in 3d programming. The math to add or subtract vectors is not that hard. And if you intend a career in game development, you will even eventually learn all about it and how to perform it with both hands tied behind your back. But for now, you can enjoy the benefits of vector addition and/or subtraction without doing a lick of the math yourself. But what you do need to understand, is why you add or subtract one vector from another. Once you get that down, the math is done behind the scenes for you with built in XNA methods. For example, this code snippet gets the developer the results he needs without needing to work with the math:
Vector3 myVector1 = new Vector3(?, ?, ?);//arbitrary vector
Vector3 myVector2 = new Vector3(?, ?, ?);//different arbitrary vector
Vector3 resultVector = myVector1 + myVector2;
XNA knows how to add the two vectors together behind the scenes using the proper vector math, you can relax and not worry about it. What you really need to concern yourself with is why we wanted to add them in the first place and what the resulting vector can do for your game. As it turns out, just about all motion in 3d programming involves adding or subtracting vectors which have had their length or direction adjusted in order to provide the motion desired.
First, let’s get a visualization foundation for you to use when visualizing vector addition, then we’ll get into examples of why you would add or subtract a vector in a game. In the graphic below are four arbitrary white vectors that will get added together to result in the vector colored in yellow. In code, it would look like this:
Vector3 yellowVector = whiteVec1 + whiteVec2 + whiteVec3 + whiteVec4;
So how do you visualize the four white vectors adding up to the yellow one? By viewing the graphic above, it’s not very intuitive how the yellow vector resulted from the white ones. But simply put, when adding these white vectors, you just line each of the white ones up nose to tail and you will end up in the correct spot, with the last white vector’s arrow-head matching the yellow vector’s arrow-head. Here is a video demonstrating this.
And it doesn’t matter what order you add them (line them up). It will still come out to the correct spot.
If you don’t see the difference between these two videos, run them both again and pause them both about 1 second from the end and you can see that we used a different order to line them up. Since it’s addition, it’s like saying 3+2+7 gets you the same result as 2+7+3.
For subtraction, you simply code it as:
Vector3 result = vector1 – vector2;
Duh, right? Showing the code there is easier than explaining the visualization of that. But here it goes. For visualization purposes, you simply add its opposite. for instance 3 -2 would be the equivalent of saying 3 + (-2). Subtracting 2 is the same as adding -2. Since you are still adding, you can still line the vectors up nose to tail, you just have to line up the opposite vector when subtracting. Here is a video of how the following code should play out in your mind’s eye. We’ll mix it up with some adding & some subtracting.
Vector3 yellowVector = white1 + white2 – white3 – white4;
Notice white3 & white4 get transformed into their opposites before applying (adding) them. That’s real important to see and understand. Also notice I got lazy and didn’t include the resulting yellow vector .
OK, now that you can ‘see’ what adding or subtracting looks like, let’s see a couple practical applications of when you would add or subtract a vector. One that comes up often is when you have two game objects, let’s say they are tanks, and you want to figure out what direction a bullet would go if you shot it from tank1 to tank2. You want to create a vector that goes from tank1 to tank2. No math is required, no angles will be worked with. Here is a graphic to set the scene.
Assume we are keeping track of each tank’s position in a Vector3s. 1 each for tank1Position & tank2Position. To calculate the direction a bullet would go if shot from tank1 to tank2 you would code it like this:
Vector3 bulletDirection = tank2Position – tank1Position; //vector subtraction like we just went over.
Notice we are wanting the direction from tank number 1 to tank number 2 so we must list tank2 first in the subtraction equation. if you pause the following video as the direction vector appears and think about what would have happened if we had listed tank1 first, you would see that the result would have been backwards. So while adding vectors can be done in any order, if you subtract them, make sure you place them in the order you need them.
This resulting vector represents the direction & distance from tank1 to tank2.
In our next example, we’ll use vector addition to move the bullet from tank1 to tank2. Normally, you would move it each frame an amount that would be a factor of how much time has elapsed since the last time you moved it. For the sake of simplicity here and for focusing on the vector addition, let’s just make the bullet to go from tank1 to tanl2 in five frames. Lets take that bulletDirection vector and shorten it to 1/5 the distance to tank2. Then well add a bullet and set it’s position to that of tank1 and each frame well add the bullet velocity to it so it will move from tank1 to tank2.
Vector3 bulletVelocity = bulletDirection * 0.2f;
//this doesn’t alter the direction the vector is pointing, it just makes it 1/5 the length.
//Then run this next line each frame
bulletPosition += bulletVelocity;
Here is a video demonstrating that the velocity gets added to the bulletPosition each frame. We’re not going to concern ourselves with the direction the turrets are pointing at the moment, we’ll just focus on the vectors representing the bulletPosition & velocityVector.
Remember from the previous section’s talk about visualizing a vector differently depending on what information it holds that you happen to need, well, that’s why we don’t visualize the bulletPosition as a ray/arrow. The only bit of information that we use from the bulletPosition vector is the position of its arrow-head (the position in world space that this vector represents). We think of it only as a point in space without care for its direction or length. On the other hand, we do care about the direction and length of the bulletVelocity vector so we vizualize it as an arrow, and since we are not as concerend with its actual position in space, we are free to move it around to any location that suits us.