Understanding component-wise operations
Several vector operations are just component-wise operations. A component-wise operation is one that you perform on each component of a vector or on like components of two vectors. Like components are components that have the same subscript. The component-wise operations that you will implement are as follows:
- Vector addition
- Vector subtraction
- Vector scaling
- Multiplying vectors
- Dot product
Let's look at each of these in more detail.
Vector addition
Adding two vectors together yields a third vector, which has the combined displacement of both input vectors. Vector addition is a component-wise operation; to perform it, you need to add like components.
To visualize the addition of two vectors, draw the base of the second vector at the tip of the first vector. Next, draw an arrow from the base of the first vector to the tip of the second vector. This arrow represents the vector that is the result of the addition:
To implement vector addition in code, add like components of the input vectors. Create a new file, vec3.cpp
. This is where you will define functions related to the vec3
struct. Don't forget to include vec3.h
. Overload the + operator
to perform vector addition. Don't forget to add the function signature to vec3.h
:
vec3 operator+(const vec3 &l, const vec3 &r) { return vec3(l.x + r.x, l.y + r.y, l.z + r.z); }
When thinking about vector addition, remember that a vector represents a displacement. When adding two vectors, the result is the combined displacement of both input vectors.
Vector subtraction
As with adding vectors, subtracting vectors is also a component-wise operation. You can think of subtracting vectors as adding the negative of the second vector to the first vector. When visualized as an arrow, subtraction points from the tip of the second vector to the tip of the first one.
To visually subtract vectors, place both vectors so they share the same origin. Draw a vector from the tip of the second arrow to the tip of the first one. The resulting arrow is the subtraction result vector:
To implement vector subtraction, subtract like components. Implement the subtraction function by overloading the -
operator in vec3.cpp
. Don't forget to add the function declaration to vec3.h
:
vec3 operator-(const vec3 &l, const vec3 &r) { return vec3(l.x - r.x, l.y - r.y, l.z - r.z); }
The steps and logic are very similar to vector addition. It might help to think of vector subtraction as adding a negative vector.
Scaling vectors
When a vector is scaled, it only changes in magnitude, not direction. As with addition and subtraction, scaling is a component-wise operation. Unlike addition and subtraction, a vector is scaled by a scalar, not another vector.
Visually, a scaled vector points in the same direction as the original vector, but it has a different length. The following figure shows two vectors: (2, 1) and (2, 4). Both vectors share the same direction, but the magnitude of the second vector is longer:
To implement vector scaling, multiply every component of the vector by the given scalar value.
Implement the scale function by overloading the *
operator in vec3.cpp
. Don't forget to add the function declaration to vec3.h
:
vec3 operator*(const vec3 &v, float f) { return vec3(v.x * f, v.y * f, v.z * f); }
Negating a vector can be done by scaling the vector by -1. When negating a vector, the vector maintains its magnitude but changes its direction.
Multiplying vectors
Vector multiplication can be considered a non-uniform scale. Instead of scaling every component of a vector by a scalar, to multiply two vectors, you scale every component of a vector by the like component of another vector.
You can implement vector multiplication by overloading the *
operator in vec3.cpp
. Don't forget to add the function declaration to vec3.h
:
vec3 operator*(const vec3 &l, const vec3 &r) { return vec3(l.x * r.x, l.y * r.y, l.z * r.z); }
The result generated by multiplying two vectors will have a different direction and magnitude.
Dot product
The dot product is used to measure how similar two vectors are. Given two vectors, the dot product returns a scalar value. The result of the dot product has the following properties:
- It is positive if the vectors point in the same direction.
- It is negative if the vectors point in opposite directions.
- It is 0 if the vectors are perpendicular.
If both input vectors have a unit length (you will learn about unit length vectors in the Normal vectors section of this chapter), the dot product will have a range of -1 to 1.
The dot product between two vectors, A and B, is equal to the length of A multiplied by the length of B multiplied by the cosine of the angle between the two vectors:
The easiest way to calculate the dot product is to sum the products of like components in the input vectors:
Implement the dot
function in vec3.cpp
. Don't forget to add the function definition to vec3.h
:
float dot(const vec3 &l, const vec3 &r) { return l.x * r.x + l.y * r.y + l.z * r.z; }
The dot product is one of the most used operations for video games. It's often used to check angles and in lighting calculations.
With the dot product, you have implemented the common component-wise operations of vectors. Next, you will learn about some of the non-component-wise operations that can be performed on vectors.