Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 11

Vector Magnitude and Normalization

Recommended resources

Hello! Welcome back to our module on 3D Math Fundamentals.

In our last lesson, we explored the dot and cross products, which are essential for understanding the relationship between two vectors—like the angle between them or a direction perpendicular to them. Today, we'll shift our focus to a fundamental property of a single vector: its magnitude, or length. We will then learn how to use the magnitude to perform one of the most common operations in all of 3D graphics: normalization.

This lesson will equip you with the ability to separate a vector's two key properties: its magnitude and its direction. This is crucial for countless applications in game development, from ensuring consistent character movement speed to performing complex lighting calculations. By the end, you'll be able to calculate a vector's length and create a unit vector that represents its pure direction.

Vector Magnitude (Length)

A vector in Cartesian coordinates, like (x, y, z), represents a direction and a magnitude simultaneously. The magnitude is simply the vector's length—a scalar value that tells us "how much" displacement the vector represents.

So, how do we calculate it? The process is a direct application of the Pythagorean theorem, which you are likely familiar with from geometry.

  • For a 2D vector (x, y), we can imagine a right-angled triangle where the sides have lengths x and y. The hypotenuse is the vector itself, and its length is .
  • In 3D, we just extend this principle. The magnitude of a vector (x, y, z) is .
Vector Length or Magnitude in 3D
This diagram illustrates how the magnitude (or length) of a 3D vector \(\mathbf{a}\) is calculated using its components \(a_1, a_2, a_3\) by extending the Pythagorean theorem into three dimensions.

Let's look at a more formal definition and the standard notation.

Vectors - 3D Math Primer for Graphics and Game Development

The book '3D Math Primer for Graphics and Game Development' offers a clear explanation of vector magnitude, which it also calls 'length' or 'norm'.

Please read Section 2.8, 'Vector Magnitude (Length)'. Focus on the formulas for 2D and 3D vectors and the geometric interpretation which connects it to the Pythagorean theorem.

Calculating Magnitude in C

In C, we can write a function to calculate the magnitude. We'll need the sqrtf function from the standard math library, which you can include with #include <math.h>.




#include <math.h>

// Represents a 3D vector
typedef struct {
    float x, y, z;
} Vec3;

// Calculates the magnitude (length) of a vector
float vec3_len(Vec3 v) {
    return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}

A Quick Optimization Tip: The sqrtf function can be computationally more expensive than simple arithmetic. In many game-related scenarios, we only need to compare lengths (e.g., "is object A closer than object B?"). In these cases, we can compare the squared magnitudes to get the same result without the cost of a square root. It's a common practice to have a function for this.

// Calculates the squared magnitude of a vector
float vec3_len_sq(Vec3 v) {
    return v.x * v.x + v.y * v.y + v.z * v.z;
}

// Example usage:
// if (vec3_len_sq(dist_to_A) < vec3_len_sq(dist_to_B)) {
//     // Object A is closer
// }

Vector Normalization

Now that we can find a vector's length, we can perform normalization. Normalizing a vector means altering it so that its length becomes 1, without changing its direction. The resulting vector is called a unit vector.

Why is this so important? A unit vector is a representation of pure direction. It has a standard "unit" of length, so we can use it in calculations without its magnitude affecting the result.

A classic example in games is handling diagonal movement.

Vector Normalization EXPLAINED - Game Dev Math

This video, 'Vector Normalization EXPLAINED', does an excellent job of demonstrating a common problem in game development and how normalization solves it.

Please watch the segment from 02:13 to 04:13. Pay close attention to: The problem of faster diagonal movement (02:13 - 02:51). The process of dividing the vector's components by its magnitude (02:51 - 03:41). The final visualization using a unit circle to show that all normalized vectors have a length of 1 (03:41 - 04:13).

As the video explained, normalization ensures fairness and consistency. We use it for:

  • Movement vectors: To ensure constant speed in any direction.
  • Surface normals: To define the direction a surface is facing for lighting calculations.
  • Directional vectors: For things like camera orientation or the direction of a projectile.

The Normalization Process

The process is simple:

  1. Calculate the magnitude of the original vector.
  2. Divide each component of the vector by this magnitude.

The formula for normalizing a vector to get the unit vector is:

Vector Magnitude and Normalization Example
This image provides a complete step-by-step example. First, the magnitude of the vector (3, 4) is calculated as 5 using the Pythagorean theorem. Then, each component is divided by the magnitude to produce the normalized unit vector (3/5, 4/5), which has a length of 1 but points in the same direction.

Let's get the formal definition from our reference text.

Vectors - 3D Math Primer for Graphics and Game Development

Let's return to the '3D Math Primer' to read about unit vectors and normalization.

Read Section 2.9, 'Unit Vectors'. It formally defines unit vectors and the normalization process. Note the warning about the term 'normal' vs. 'normalized'—it's a good distinction to remember.

An Important Edge Case: What if we try to normalize the zero vector (0, 0, 0)? Its magnitude is 0, and dividing by zero is an undefined operation that will crash your program. A robust normalization function must check for this. If the magnitude is zero, you should simply return the zero vector.

Normalization in C

Here is a C function that implements normalization, including the check for a zero-length vector.

// Normalizes a vector to have a length of 1
Vec3 vec3_normalize(Vec3 v) {
    float len = vec3_len(v);
    
    // Check for zero length to avoid division by zero
    if (len > 0.0f) {
        float inv_len = 1.0f / len; // Use multiplication instead of division for performance
        return (Vec3){
            .x = v.x * inv_len,
            .y = v.y * inv_len,
            .z = v.z * inv_len
        };
    }
    
    // Return the zero vector if the input was also a zero vector
    return (Vec3){0.0f, 0.0f, 0.0f};
}

Practice

Let's put this into practice. Try to normalize the following vector: .

Step 1: Calculate the magnitude.

Step 2: Divide each component by the magnitude.

As an optional exercise, you can try normalizing the other vectors from Exercise 6 in the 3D Math Primer text (Section 2.15).


Conclusion

Today we've covered two simple but vital concepts. You now have the tools to handle a vector's direction and magnitude independently.

Key Takeaways:

  • Vector Magnitude is its length, calculated using the Pythagorean theorem: .
  • Comparing squared magnitudes is often a faster way to compare distances.
  • Normalization is the process of scaling a vector to have a magnitude of 1, which creates a unit vector.
  • A unit vector represents a pure direction and is fundamental for consistent calculations in movement, lighting, and more.
  • Always handle the zero vector case when normalizing to prevent division-by-zero errors.

In our next lesson, we will make a significant jump to a new topic: matrices. You'll learn how to perform matrix-vector and matrix-matrix multiplication. This will lay the groundwork for the next set of lessons, where we will use matrices to perform transformations like translation (moving), rotation, and scaling on our 3D objects.