*Chapter 2*: Implementing Vectors

In this chapter, you will learn the basics of vector math. Much of what you will code throughout the rest of this book relies on having a strong understanding of vectors. Vectors will be used to represent displacement and direction.

By the end of this chapter, you will have implemented a robust vector library and will be able to perform a variety of vector operations, including component-wise and non-component-wise operations.

We will cover the following topics in this chapter:

- Introducing vectors
- Creating a vector
- Understanding component-wise operations
- Understanding non-component-wise operations
- Interpolating vectors
- Comparing vectors
- Exploring more vectors
Important information:

In this chapter, you will learn how to implement vectors in an intuitive, visual way that relies on code more than math formulas. If you are interested in math formulas or want some interactive examples to try out, go to https://gabormakesgames...

# Introducing vectors

What is a vector? A vector is an n-tuple of numbers. It represents a displacement measured as a magnitude and a direction. Each element of a vector is usually expressed as a subscript, such as *(V*0*, V*1*, V*2*, … V*N*)*. In the context of games, vectors usually have two, three, or four components.

For example, a three-dimensional vector measures displacement on three unique axes: *x*, *y*, and *z*. Elements of vectors are often subscripted with the axis they represent, rather than an index. *(V*X*, V*Y*, V*Z*)* and *(V*0*, V*1*, V*2*)* are used interchangeably.

When visualizing vectors, they are often drawn as arrows. The position of the base of an arrow does not matter because vectors measure displacement, not a position. The end of the arrow follows the displacement of the arrow on each axis.

For example, all of the arrows in the following figure represent the same vector:

Each arrow has the same...

# Creating a vector

Vectors will be implemented as structures, not classes. The vector struct will contain an anonymous union that allows the vector's components to be accessed as an array or as individual elements.

To declare the `vec3`

structure and the function headers, create a new file, `vec3.h`

. Declare the new `vec3`

structure in this file. The `vec3`

struct needs three constructors—a default constructor, one that takes each component as an element, and one that takes a pointer to a float array:

#ifndef _H_VEC3_ #define _H_VEC3_ struct vec3 { union { struct { float x; float y; float z; }; &...

# 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...

# Understanding non-component-wise operations

Not all vector operations are component-wise; some operations require more math. In this section, you are going to learn how to implement common vector operations that are not component-based. These operations are as follows:

- How to find the length of a vector
- What a normal vector is
- How to normalize a vector
- How to find the angle between two vectors
- How to project vectors and what rejection is
- How to reflect vectors
- What the cross product is and how to implement it

Let's take a look at each one in more detail.

## Vector length

Vectors represent a direction and a magnitude; the magnitude of a vector is its length. The formula for finding the length of a vector comes from trigonometry. In the following figure, a two-dimensional vector is broken down into parallel and perpendicular components. Notice how this forms a right triangle, with the vector being the hypotenuse:

# Interpolating vectors

Two vectors can be interpolated linearly by scaling the difference between the two vectors and adding the result back to the original vector. This linear interpolation is often abbreviated to `lerp`

. The amount to `lerp`

by is a normalized value between *0* and *1*; this normalized value is often represented by the letter *t*. The following figure shows `lerp`

between two vectors with several values for *t*:

When *t = 0*, the interpolated vector is the same as the starting vector. When *t = 1*, the interpolated vector is the same as the end vector.

Implement the `lerp`

function in `vec3.cpp`

. Don't forget to add the function declaration to `vec3.h`

:

vec3 lerp(const vec3 &s, const vec3 &e, float t) { return vec3( s.x + (e.x - s.x) * t, s.y + (e.y - s.y) * t, ...

# Comparing vectors

The last operation that needs to be implemented is vector comparison. Comparison is a component-wise operation; each element must be compared using an epsilon. Another way to measure whether two vectors are the same is to subtract them. If they were equal, subtracting them would yield a vector with no length.

Overload the `==`

and `!=`

operators in `vec3.cpp`

. Don't forget to add the function declarations to `vec3.h`

:

bool operator==(const vec3 &l, const vec3 &r) { vec3 diff(l - r); return lenSq(diff) < VEC3_EPSILON; } bool operator!=(const vec3 &l, const vec3 &r) { return !(l == r); }

Important note:

Finding the right epsilon value to use for comparison operations is difficult. In this chapter, you declared `0.000001f`

as the epsilon. This value is the result of some trial and error. To learn more about comparing floating point values, check out https://bitbashing.io...

# Exploring more vectors

At some point later on in this book, you will need to utilize two- and four-component vectors as well. The two- and four-component vectors don't need any mathematical functions defined as they will be used exclusively as containers used to pass data to the GPU.

Unlike the three-component vector you have implemented, the two- and four-component vectors need to exist as both integer and floating point vectors. To avoid duplicating code, both structures will be implemented using a template:

- Create a new file,
`vec2.h`

, and add the definition of the`vec2`

struct. All the`vec2`

constructors are inline; there is no need for a`cpp`

file. The`TVec2`

struct is templated and`typedef`

is used to declare`vec2`

and`ivec2`

:template<typename T> struct TVec2 { union { struct { T x; ...

# Summary

In this chapter, you have learned the vector math required to create a robust animation system. Animation is a math-heavy topic; the skills you have learned in this chapter are required to complete the rest of this book. You implemented all the common vector operations for three-component vectors. The `vec2`

and `vec4`

structures don't have a full implementation like `vec3`

, but they are only used to send data to the GPU.

In the next chapter, you will continue to learn more about game-related math by learning about matrices.