Welcome to Arkanis Development

Math 3D - A simple vector and matrix library for C

Published

If you've done a bit of graphics programming with OpenGL you're probably familiar with vector and matrix math. Every point or direction in 3D space can be represented as a vector and most manipulations of those can be represented as matrices (moving them around, rotating them, projecting them on the screen, etc.).

I wasn't happy with the C math libraries I found so I wrote a new one (surprise!). Read on if you want to know why. But here is what using it looks like:

mat4_t projection = m4_perspective(60, 800.0 / 600.0, 1, 10);
vec3_t from = vec3(0, 0.5, 2), to = vec3(0, 0, 0), up = vec3(0, 1, 0);
mat4_t transform = m4_look_at(from, to, up);

vec3_t world_space = vec3(1, 1, -1);
mat4_t world_to_screen_space = m4_mul(projection, transform);
vec3_t screen_space = m4_mul_pos(world_to_screen_space, world_space);

OpenGL provides a lot of vector and matrix math for shaders that run on the GPU but on the CPU you have to do it yourself. I like it this way because it allows you to choose what kind of 3D math library you want: One that tries to optimize every last bit of performance but is complicated to use or one that is easy to use but lax on performance. Depending on the project you can pick what you need.

I do pretty much all of my low level graphics programming in C (I know, I'm weird, but OpenGL is a C API after all). And I haven't found a 3D math library I'm happy with for C. I don't know all of them but the ones I've looked at were complicated to use and vague on their semantics. Where they written with the OpenGL or Direct3D conventions in mind? How are matrices laid out in memory? Can I pass them into OpenGL directly or do I have to transpose them before hand?

There are good C++ math libraries that perfectly fit my purpose but I'm an awful C++ programmer. I spend way more time fiddling around with the language than I spend on solving the problem. So I stayed with C. Maybe someone else will find non-templated math code similarly appealing.

All this drove me to write my own small 3D math library for C. Just the basics, nothing fancy. A friend of mine joined in and together we started out from scratch. It was quite a nice learning experience. We spend a lot of time on the whiteboard, calculated a lot of the math by hand and wrote a lot of tests until we understood what the math should actually mean. It was just there that we realized that the perspective divide step in OpenGL is just an fixed function hack to fit a perspective projection into a 4x4 matrix. Kind of pointless with shaders...

Anyway, if you ever do OpenGL stuff in C and need a simple to use math library you can pick it up here: math_3d.h. It's a single header-file library in the style of stb_image.h so it's easy to integrate into projects.

It covers basic 3D vector math, transformation and camera matrices (translation, rotation, scaling and look at), projection matrices (orthographic and perspective) as well as basic matrix math (matrix-matrix, matrix-point and matrix-direction multiplication, inversion of affine transformations). The documentation is in the file itself so take a look if you're interested.

Happy programming. :)

5 comments for this post

leave a new one

#1 by
Patrick
,

oh man, you saved my life. there are, as you already said, only overly complex and overloaded c math libraries around. I have been searching for something like your for quite some time. c ist also my favorite, but not very popular around other devs, as it seems. thank your very much, that lib will be part of my routine as soon as I am finished writing this comment. really great work :)

#2 by
Stephan
,

Thanks for the comment. It's always good to know that the work is useful to someone else, too. :)

Have a good time with the library and don't hessitate to let me know if something isn't like you expect it to be.

#3 by
Skandar
,

You saved me too. I was looking exactly for this a vector math for C. I was using C++ but I got tired of it, As you said just fighting the language instead getting job done.

#4 by
bartek
,

Thank you so much - exactly what I was looking for ;)

#5 by
Sébastien Le Roux
,

Hello there, first of all thanks for this library, that is a great tool indeed ! I write first to let you know that I think that there is an error in your file, I pointed it in the 'm4_invert_affine(mat4_t matrix)' calculation: The following condition is not accurate enough:

if (fabsf(det) < 0.00001)
			return m4_identity();

You should write instead:

if (fabsf(det) == 0.00000)
			return m4_identity();

I actually came up with the error case and I struggled to find out that error was coming from this, and it does.

Also I came up with few improvements of the file, like the 'vec4_t' type (in particular for quaternions), 'm4_quat_rotation (vec4_t q)' for quaternion rotation, 'm4_frustum' … I will be happy to share it with you, but I think this message box is too small for that. If you are interested just let me know how to contact you.

Best.

Leave a new comment

Having thoughts on your mind about this stuff here? Want to tell me and the rest of the world your opinion? Write and post it right here. Be sure to check out the format help (focus the large text field) and give the preview button a try.

Format help

Please us the following stuff to spice up your comment.

An empty line starts a new paragraph. ---- print "---- lines start/end code" ---- * List items start with a * or -

or