Math Library

Note: These Game Engine blogs are a series of write-ups I did when I was in school for my master’s degree. I took a series of three courses run by Ed Keenan where we built a game engine from scratch in C++.

This week is super straight forward and not very sexy at all so I’m going to keep it short. We’re creating some classes to use as our math library. When we start to integrate OpenGL (GPU API) into our engine, we don’t want to use their built-in matrix and vector classes because they’re bloated and slow. So we make our own.

The Vect Class

Games use vectors and matrices to do all the calculations of objects, lighting, shading, and some other stuff. The Vect class is simply 4 floats. That’s all the data it has. It’s a three-dimensional vector with a w coordinate which we’ll use later to do quaternions. So what am I building then? Well, it’s basically a ton of operator overloading. We want to create a math library that is very easy for our programmers to use. By doing all the work up front, we’ll save lots of time in the end. I built methods for dot and cross products. Methods for calculating the angle between two Vects, methods for normalizing a Vect. This goes on and on to build a fairly large class, but a robust one with just 4 pieces of data (the floats). We also overloaded all the arithmetic operators to use Vects (this means adding, subtracting, and multiplying Vects with Vects and also Vects with Matrices).

The Matrix Class

This guy is a bit more complicated because he has a lot more data: 16 floats. But my teacher showed us a cool trick here. Because our Vect class is just four floats, we can use an anonymous union to build our Matrix class’ data

  union
{

struct
{
Vect _v0;
Vect _v1;
Vect _v2;
Vect _v3;
};
struct
{
float _m0;
float _m1;
float _m2;
float _m3;
float _m4;
float _m5;
float _m6;
float _m7;
float _m8;
float _m9;
float _m10;
float _m11;
float _m12;
float _m13;
float _m14;
float _m15;
};
};

What this union does is say that our Matrix data can be 16 floats or 4 Vects. This doesn’t change the data at all. The bit pattern remains exactly the same. But because our Vect class is just 4 floats, we can do this. So now when you access a Matrix’s data, you can do it by accessing by a Vect (which is an entire row of the matrix in floats), or you can access the float directly. This gives us some added robustness when doing calculations and also creating new matrices. We’ve also added all the necessary overloaded operators for arithmetic. Next week we’ll build a filesystem and revisit the PCSTree to add forward and reverse iterators.

Previous
Previous

1st Wrap-Up

Next
Next

Memory System: Part II