Under Construction About Me Projects Previous Work

MGMath

MGMath is a vector/matrix math library for C++17.

Its advantage over other similar libraries is the modular, simple, extensible design.

Everything is in a single header, and all of the components use a similar structure, so any extensions are trivial to implement.

// Define vectors using the default template class
mgm::vec<3, float> v0 = { 1.0f, 2.0f, 3.0f };

// Define vectors using aliases
// (vec3f is short for vec<3, float>)
mgm::vec3f v1 = v0;

// There are plenty of aliases
// vec4u8 works well for 32-bit rgba colors
vec4u8 v2 = { 255, 100, 100, 255 };
            
The main selling point of the library is its modularity.
The actual storage for the xyz components of the vector is abstracted.
This way, everything can be exposed to users through the same templated class.

This makes generic implementations in the actual vector class a lot easier.
By extension, the development of the library is also easier and faster, because functions or components don't need to be specialized (unless necessary for some specific case for example optimizations).

// Generic vec_storage template for sizes >= 5
template<size_t S, typename T>
class vec_storage {
public:
    T _data[S];
};

// Example of specialized implementation, for size 4
template<typename T>
class vec_storage<4, T> {
public:
    T x, y, z, w;
};

// Actual vector class
template<size_t S, typename T>
class vec : public vec_storage<S, T> {};
            
This aspect makes it easy to write generalized tools for any vector size, again without specializations

For example, this function, which serializes a vector into a json object and returns it.

This is different from other math libraries, like glm, where although code like this is possible to write, because many vector types are manually specialized, it makes development of generic code like this much harder.

template<size_t S, typename T>
SerializedData<vec<S, T>> serialize(const vec<S, T>& v) {
    SerializedData<vec<S, T>> res{};

    if constexpr (S > 4) {
        // If vectors are too big to have xyzw components, save it as an array
        for (int i = 0; i < S; ++i)
            res.as_array().push_back(v[i]);
    }
    else {
        // For sizes of 4 or less, save vector data in named keys
        res["x"] = v.x;

        if constexpr (S >= 2)
            res["y"] = v.y;
        if constexpr (S >= 3)
            res["z"] = v.z;
        if constexpr (S >= 4)
            res["w"] = v.w;
    }

    return res;
}