cglm is one of those libraries that fills a very specific niche: fast, low-level math for graphics, written purely in C but competing with the widely used GLM library from C++. It’s designed to deliver the kind of performance and API convenience usually associated with C++ templates and SIMD intrinsics, but without stepping outside the C99 standard or relying on dynamic memory. If you’ve ever wished for a GLM-like experience in C, cglm is worth a close look.
what cglm provides and how it’s structured
At its core, cglm is a 2D/3D math library targeting graphics programmers who want a lightweight, high-performance toolset for vector and matrix operations, quaternions, Euler angles, frustums, bounding volumes, and curve interpolation. Unlike GLM, which is a heavyweight C++ template library, cglm stays in C and avoids any dependency on a graphics API. This makes it versatile for projects using OpenGL, Vulkan, Metal, or even custom engines.
The library is header-only, meaning you can include it directly in your projects without linking external binaries. It actually offers three related APIs:
- Header-only API (
glm_prefix): Inline functions implemented in headers, optimized for speed and convenience. - Struct API (
glms_prefix): Uses C11 anonymous unions and structs to provide more expressive vector and matrix types, making the code more readable and closer to how you’d handle math objects in higher-level languages. - Linked API (
glmc_prefix): Traditional library approach for those who prefer separate compilation.
Under the hood, cglm leverages SIMD optimizations tailored to the platform: SSE and AVX on x86, NEON on ARM. These are hand-tuned for the “hot paths” like affine transformations. It avoids any dynamic memory allocation, which is critical for real-time graphics and embedded systems.
Memory layout defaults to column-major order, matching OpenGL, which helps integration without extra conversions. For Vulkan and Metal users, recent flags adjust depth normalization and handedness to fit those graphics APIs’ conventions.
The codebase is clean and well-commented, aiming for clarity without sacrificing performance. It supports a wide range of math utilities common in graphics, from basic vector ops to complex curve interpolations.
why cglm’s design stands out among C math libraries
The standout aspect of cglm is how it achieves a GLM-like experience purely in C99. Header-only SIMD libraries in C are rare because C lacks the template meta-programming facilities that make GLM flexible and efficient in C++. Instead, cglm uses a combination of inline functions, macros, and C11 features like anonymous unions to replicate a similar ergonomic API.
Here is a simple example of zeroing a 2D vector using cglm’s header-only API:
#include "cglm/cglm.h"
vec2 vector;
glm_vec2_zero(vector);
This is straightforward, lightweight, and doesn’t involve hidden allocations or complex setup.
To put it in perspective, here’s a side-by-side comparison of vector zeroing with GLM (C++) and cglm (C):
// GLM (C++)
#include <glm/glm.hpp>
glm::vec2 v(0.0f);
// cglm (C)
#include "cglm/cglm.h"
vec2 v;
glm_vec2_zero(v);
Both are concise, but cglm achieves this without templates or constructors, relying instead on inline functions and macros. This makes it compatible with any C99 compiler, which is a huge plus for portability.
Performance-wise, cglm’s use of SIMD intrinsics is explicit and optimized. While GLM relies on the compiler’s auto-vectorization and template tricks, cglm hand-crafts SIMD paths for SSE, AVX, and NEON. This gives it a predictable and consistent performance profile in real-world scenarios.
Regarding build systems, cglm integrates smoothly with CMake and Meson. You can add it as a subdirectory or find package and link it easily. This is practical for projects that want a clean, header-only dependency without complicated build scripts.
The tradeoff is that cglm stays within C99 and avoids heavy abstraction, so some of the syntactic sugar and type safety from C++ are missing. For example, you won’t get operator overloading or templates, so code might feel a bit more verbose. But that’s a conscious design decision favoring portability and simplicity.
explore the project
The repository is organized with clear folders for headers and source files. The main entry point is the cglm folder containing headers and inline implementations. Documentation is mostly in the README and inline comments.
You can start by including cglm/cglm.h in your C project and calling functions like glm_vec2_zero or glm_mat4_mul. The README provides minimal examples, but the API is consistent and well-documented in the header files.
If you want to use the struct API for more expressive types, include cglm/struct.h and use glms_vec3, glms_mat4, etc. This adds some syntactic niceties by leveraging C11 features.
No external dependencies or complex setup steps are required. The focus is on zero-configuration and maximum portability.
verdict
cglm is a solid choice if you need a performant, portable 2D/3D math library in pure C that doesn’t compromise on SIMD optimizations. It’s especially relevant for graphics programmers working outside C++ or in environments where C99 compatibility is a must.
The tradeoff is the lack of C++ features like templates and operator overloading, which means the API is more verbose and less flexible than GLM. But the payoff is a header-only, zero-allocation library that fits easily into almost any C build system.
If you’re building OpenGL, Vulkan, or Metal applications in C and want a clean, fast math library with a familiar API, cglm is worth testing. Keep in mind that while it covers a broad range of graphics math needs, it’s not a general-purpose math library outside of this domain.
Overall, cglm strikes a pragmatic balance between performance, portability, and API usability in pure C — a combination that’s surprisingly rare.
→ GitHub Repo: recp/cglm ⭐ 2,924 · C