A lightweight, C++ math library for game development and graphics programming.
libgmath is a modern, template-based C++ mathematics library designed for game engines, graphics applications, and computational geometry. Inspired by GLM (OpenGL Mathematics), it provides a complete set of vector, matrix, and utility functions with a clean, intuitive API.
The libgmath can replace the GLM in OpenGL/Vulkan projects.
- ✅ Template-based - Full support for
float,double, and custom numeric types - ✅ GLM-like API - Familiar syntax for developers experienced with GLM
- ✅ Zero dependencies - Fully self-contained, no external libraries required
- ✅ Game-ready - Optimized for real-time applications
- ✅ Modern C++ - Clean C++17 codebase with best practices
You can add it into you meson.build
dependencies : [
dependency('libgmath', static: true),
]And creating the file subprojects/libgmath.wrap
[wrap-git]
url =https://github.com/agtdbx/libgmath.git
revision = HEAD
depth =1#include<gmath.hpp>intmain(void)
{
// Create vectors
gm::Vec3f position(1.0f, 2.0f, 3.0f);
gm::Vec3f velocity(0.5f, 0.0f, -0.2f);
// Vector operations
gm::Vec3f newPosition = position + velocity;
float distance = gm::length(position);
gm::Vec3f normalized = gm::normalize(velocity);
// Create a 4x4 identity matrix
gm::Mat4f transform(1);
// Perlin noise generation
gm::PerlinNoisef noise(42, gm::Vec2i(256, 256), 4, 0.5f);
float value = noise.getNoise(10.5f, 20.3f);
return (0);
}libgmath provides 2D, 3D, and 4D vector types for both float and double precision:
// 2D Vectors
gm::Vec2<T> // Generic 2D vector
gm::Vec2f // float version
gm::Vec2d // double version
gm::Vec2i // int version
gm::Vec2u // unsigned int version// 3D Vectors
gm::Vec3<T> // Generic 3D vector
gm::Vec3f // float version
gm::Vec3d // double version
gm::Vec3i // int version
gm::Vec3u // unsigned int version// 4D Vectors
gm::Vec4<T> // Generic 4D vector
gm::Vec4f // float version
gm::Vec4d // double version
gm::Vec4i // int version
gm::Vec4u // unsigned int version// Construction
gm::Vec3f v1(1.0f, 2.0f, 3.0f);
gm::Vec3f v2(v1); // Copy constructor// Arithmetic operations
gm::Vec3f sum = v1 + v2;
gm::Vec3f diff = v1 - v2;
gm::Vec3f scaled = v1 * 2.0f;
gm::Vec3f divided = v1 / 2.0f;
// Comparisonbool equal = (v1 == v2);
bool notEqual = (v1 != v2);
// Accessfloat x = v1.x; // or v1[0]float y = v1.y; // or v1[1]float z = v1.z; // or v1[2]Full support for 2x2, 3x3, and 4x4 matrices:
// 2x2 Matrices
gm::Mat2<T> // Generic 2x2 matrix
gm::Mat2f // float version
gm::Mat2d // double version
gm::Mat2i // int version
gm::Mat2u // unsigned int version// 3x3 Matrices
gm::Mat3<T> // Generic 3x3 matrix
gm::Mat3f // float version
gm::Mat3d // double version
gm::Mat3i // int version
gm::Mat3u // unsigned int version// 4x4 Matrices
gm::Mat4<T> // Generic 4x4 matrix
gm::Mat4f // float version
gm::Mat4d // double version
gm::Mat4i // int version
gm::Mat4u // unsigned int version// Identity matrix
gm::Mat4f identity(1);
// Matrix arithmetic
gm::Mat4f result = mat1 + mat2;
gm::Mat4f product = mat1 * mat2;
// Matrix-vector multiplication
gm::Vec4f transformed = matrix * vector;
// Transpose and inverse (if available)
gm::Mat4f transposed = gm::transpose(matrix);namespacegm {
// Vector operationstemplate<typename T>
T norm(const Vec3<T> &v); // Vector magnitudetemplate<typename T>
T norm2(const Vec3<T> &v); // Vector magnitude squarredtemplate<typename T>
Vec3<T> normalize(const Vec3<T> &v); // Normalized vectortemplate<typename T>
T dot(const Vec3<T> &a, const Vec3<T> &b); // Dot producttemplate<typename T>
Vec3<T> cross(const Vec3<T> &a, const Vec3<T> &b); // Cross producttemplate<typename T>
T hash(const Vec3<T> &vec); // Hashing// Interpolationtemplate<typename T>
T lerp(T a, T b, float/double t); // Linear interpolation// Random number generationvoidinitRandom(unsignedint seed); // Initialize RNGintiRand(int min, int max); // Random integerunsignedintuRand(); // Random unsigned intfloatfRand(); // Random float [0, 1]doubledRand(2.1, 42.0); // Random double [2.1, 42.0]
}Generate seamless, tileable 2D Perlin noise for procedural content generation.
gm::PerlinNoise<T> // Generic Perlin noise
gm::PerlinNoisef // float version
gm::PerlinNoised // double version// Default constructor (seed=42, shape=16x16, octaves=1)
gm::PerlinNoisef noise1;
// Custom seed and shape
gm::PerlinNoisef noise2(12345, gm::Vec2i(512, 512));
// Fractal Brownian Motion (FBM) with octaves
gm::PerlinNoisef noise3(
42, // Seedgm::Vec2i(256, 256), // Grid shape
6, // Number of octaves
0.5f // Persistence (amplitude decay)
);// Get noise value at coordinates [-1, 1]float value = noise.getNoise(x, y);
// Get normalized noise value [0, 1]float normalized = noise.getNoiseNormalize(x, y);
// Accessorsunsignedint seed = noise.getSeed();
unsignedint octaves = noise.getOctaves();
float persistence = noise.getPersistence();
gm::Vec2i shape = noise.getShape();#include<gmath.hpp>// Create fractal noise with 5 octaves
gm::PerlinNoisef terrain(
42, // Seed for reproducibilitygm::Vec2i(256, 256), // 256x256 grid
5, // 5 octaves for detail
0.5f // Standard persistence
);
// Generate heightmapfor (int y = 0; y < 256; y++) {
for (int x = 0; x < 256; x++) {
// Scale coordinates for smoother noisefloat nx = x / 32.0f;
float ny = y / 32.0f;
// Get height value [0, 1]float height = terrain.getNoiseNormalize(nx, ny);
// Use height for terrain generation// ...
}
}#include<gmath.hpp>classCamera {
public:
gm::Vec3f position;
gm::Vec3f forward;
gm::Vec3f up;
Camera() :
position(0.0f, 0.0f, 5.0f),
forward(0.0f, 0.0f, -1.0f),
up(0.0f, 1.0f, 0.0f) {}
voidmoveForward(float distance) {
position += gm::normalize(forward) * distance;
}
gm::Vec3f getRight() const {
returngm::normalize(gm::cross(forward, up));
}
};#include<gmath.hpp>
#include<vector>structParticle {
gm::Vec3f position;
gm::Vec3f velocity;
float lifetime;
};
voidupdateParticles(std::vector<Particle>& particles, float deltaTime) {
for (auto& p : particles) {
p.position += p.velocity * deltaTime;
p.lifetime -= deltaTime;
// Apply gravity
p.velocity += gm::Vec3f(0.0f, -9.81f, 0.0f) * deltaTime;
}
}#include<gmath.hpp>voidgenerateCloudTexture(unsignedchar* texture, int width, int height) {
gm::PerlinNoisef noise(12345, gm::Vec2i(256, 256), 4, 0.5f);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float value = noise.getNoiseNormalize(
x / 64.0f,
y / 64.0f
);
// Convert to grayscale [0, 255]
texture[y * width + x] = static_cast<unsignedchar>(value * 255);
}
}
}#include<gmath.hpp>structRigidBody {
gm::Vec3f position;
gm::Vec3f velocity;
float mass;
voidapplyForce(const gm::Vec3f& force, float deltaTime) {
// F = ma -> a = F/m
gm::Vec3f acceleration = force / mass;
velocity += acceleration * deltaTime;
position += velocity * deltaTime;
}
floatkineticEnergy() const {
// KE = 0.5 * m * v²float speed = gm::length(velocity);
return0.5f * mass * speed * speed;
}
};The librairy use meson for build system. You can use the makefile that wrap meson.
make # compile library. libgmath.so will be in ./build/libgmath.so
make run # Run basics tests on the lib.- C++17 or later
- Zero-overhead abstraction: Template-based design incurs no runtime cost
- Inlining: Most functions are candidates for compiler inlining
- Type safety: Compile-time type checking prevents errors
- Cache-friendly: Contiguous memory layout for vectors and matrices
This project is free to used, just credit the repo.
agtdbx
- GitHub: @agtdbx
- Inspired by GLM (OpenGL Mathematics)
- Perlin noise implementation based on Ken Perlin's improved noise
- Built for game developers, by a game developer
Happy coding! 🚀