MathC - a C math library for 2D and 3D programming

Started by
25 comments, last by penguinbyebye 6 years, 5 months ago

I was in doubt whether to post this on Programming -> Math and Physics or in Your Announcements. Since it's a project, I will leave here. 

As I was writing my C game engine, I decided to decouple the math implementation and make its own library.

It has implementation for 2D vectors, 3D vectors, 4D vectors, quaternions and matrices.

It's mainly for game programming.

Github: https://github.com/ferreiradaselva/mathc

Feedback is appreciated, too. Especially on the math aspects (lacking functions, math errors), since I don't have a particularly professional background with math.

Advertisement

I havent had time to look through it thoroughly, but :

There's no point in declaring an input parameter const if it's being passed by value:


cvector2 vector2_add(const cvector2 a, const cvector2 b);

You should just either declare it without the const, or declare it as a const reference:


cvector2 vector2_add(cvector2 a, cvector2 b);

or

cvector2 vector2_add(const cvector2& a, const cvector2& b);

 

Is passing by reference a thing in C? I'm trying to keep it usable from C.

As for the const, that's a good point. Thanks!

Edit: just checked the reference thing. It's not possible to pass by reference in C.

2 minutes ago, ferreiradaselva said:

Is passing by reference a thing in C? I'm trying to keep it usable from C.

As for the const, that's a good point. Thanks!

Oh... in that case, then no.  I didnt realize you're trying to stick to pure C.

Is there a reason for that decision?  

I just like it more. The whole engine is in C. And I wouldn't like to have to use other compiler only because of one part of the library.

1 minute ago, ferreiradaselva said:

I just like it more. The whole engine is in C. I wouldn't like to have to use other compiler only because of one part of the library.

You wouldnt need to use two different compilers just because some parts use C++ features and others dont.

I'd suggest reconsidering not using C++.  Especially for math, and especially for math in games, this C style can make for some absolutely unreadable and tedious code.  There's many parts of a game like physics or AI where you'll be doing a lot of math and the more natural and readable the code the better... not just to write, but to read/debug/maintain later.

For example, here's just one line of physics code that I dug up:


// Pre-collision relative velocity at point of contact
v3 vr = (v1 + w1.cross(r1)) - (v2 + w2.cross(r2));

If I rewrite it with your math library it'd be like this:


cvector3 temp1 = vector3_cross(w1, r1);
cvector3 temp2 = vector3_cross(w2, r2);
temp1 = vector3_add(v1, temp1);
temp2 = vector3_add(v2, temp2);
cvector3 vr = vector3_sub(temp1, temp2);

And that's just one line, from a function that has around 60 lines of math code like that.

30 minutes ago, 0r0d said:

You wouldnt need to use two different compilers just because some parts use C++ features and others dont.

With Visual Studio, probably I wouldn't, but I use gcc (for Linux) and mingw (for Windows).

30 minutes ago, 0r0d said:

I'd suggest reconsidering not using C++.  Especially for math, and especially for math in games, this C style can make for some absolutely unreadable and tedious code.  There's many parts of a game like physics or AI where you'll be doing a lot of math and the more natural and readable the code the better... not just to write, but to read/debug/maintain later.

I get it that some people prefer C++ and find it more readable, but I prefer C (and I know there are people there that prefer C, too). (before programming only in C, I programmed in C++, too) I don't want to make this post a C vs C++, bc there's already a bunch on that in this forum.

 

The math part is kinda the one I'm more concerned to improve, tbh, as I don't have a great math background (I should've added that in the first post). I made this library checking codes from MonoGame and linmath. Linmath is in C, too, but missing some features that I added there (especially on quaternions and matrices).

2 minutes ago, ferreiradaselva said:

With Visual Studio, probably I wouldn't, but I use gcc (for Linux) and mingw (for Windows).

28 minutes ago, 0r0d said:

GCC can do this to.

2 minutes ago, ferreiradaselva said:

I get it that some people prefer C++ and find it more readable, but I prefer C

One thing to consider is offering optional extra headers that wrap the C stuff you've written in operator overloads that let C++ users avoid some of the more onerous aspects of having to type out "vector3_add" all the time. This is generally a reasonable compromise between keeping the core ideology of your library ("it's for C") and getting more users who might be able to provide you useful feedback on the inner workings of the library (or find bugs). Generally the surface area involved in C++ overload shims is small relative to the rest of the library -- although in your case, less so, since the library itself is still pretty small -- so you don't pay much more continued upkeep for it and most of the cost is in the initial implementation.

5 minutes ago, ferreiradaselva said:

The math part is kinda the one I'm more concerned to improve, tbh, as I don't have a great math background. I made this library checking codes from MonoGame and linmath. Linmath is in C, too, but missing some features that I added there (especially on quaternions and matrices).

Consider adding tests. This also works towards making your library more approachable (people can see there is a verification framework), and it tells you when you make a change that accidentally breaks stuff somehow. It also serves as a kind of documentation (although again, your library is still small and straightforward enough you don't really need that).

And it serves as a way to prove to yourself you're doing it right, especially when you're adding functionality for orthogonality (that is, because you think it's a function you should have since you have similar ones, not because you're actively needing it now yourself): you can verify your tests are correct by running them against another library that you know to be correct, if you're not comfortable working out and verifying the math by hand. Or you're too lazy to, like I am.

More generally, you might benefit from either providing some one-line comments above certain functions, or making their names slightly longer to make them more explicit in their purpose. There's a handful of them (like vectorX_angle, vectorX_min, vectorX_max, some rotation stuff) where the semantics aren't immediately obvious, or where absent any other information I can guess that they might do one or two potentially different things.

You may also want to consider taking the appropriate steps to ensure any particular alignment or padding guarantees, or at least document that you expect somebody else to do that via the appropriate magics before including your header.

2 minutes ago, jpetrie said:

One thing to consider is offering optional extra headers that wrap the C stuff you've written in operator overloads that let C++ users avoid some of the more onerous aspects of having to type out "vector3_add" all the time. This is generally a reasonable compromise between keeping the core ideology of your library ("it's for C") and getting more users who might be able to provide you useful feedback on the inner workings of the library (or find bugs). Generally the surface area involved in C++ overload shims is small relative to the rest of the library -- although in your case, less so, since the library itself is still pretty small -- so you don't pay much more continued upkeep for it and most of the cost is in the initial implementation.

I can get behind that :thumbsup:

4 minutes ago, jpetrie said:

Consider adding tests. This also works towards making your library more approachable (people can see there is a verification framework), and it tells you when you make a change that accidentally breaks stuff somehow. It also serves as a kind of documentation (although again, your library is still small and straightforward enough you don't really need that).

And it serves as a way to prove to yourself you're doing it right, especially when you're adding functionality for orthogonality (that is, because you think it's a function you should have since you have similar ones, not because you're actively needing it now yourself): you can verify your tests are correct by running them against another library that you know to be correct, if you're not comfortable working out and verifying the math by hand. Or you're too lazy to, like I am.

Those are good ideas! I have some code already with my own game, it's a matter of copy-paste.

5 minutes ago, jpetrie said:

More generally, you might benefit from either providing some one-line comments above certain functions, or making their names slightly longer to make them more explicit in their purpose. There's a handful of them (like vectorX_angle, vectorX_min, vectorX_max, some rotation stuff) where the semantics aren't immediately obvious, or where absent any other information I can guess that they might do one or two potentially different things.

Good points. Adding some prepositions (as "from") will probably make the name of some functions more explicit.

7 minutes ago, jpetrie said:

You may also want to consider taking the appropriate steps to ensure any particular alignment or padding guarantees, or at least document that you expect somebody else to do that via the appropriate magics before including your header.

Hmm, that's a good feature. I suppose the main use would be being able to use the structs as if they were arrays? Like this:


cmatrix m = matrix_ortho(...);
float *v = &m;

/* Can edit as an array */
v[0] = 0.5f;

/* Or send to the GPU */
glUniform4fv(view_loc, 16, v);

 

 

1 hour ago, ferreiradaselva said:

With Visual Studio, probably I wouldn't, but I use gcc (for Linux) and mingw (for Windows).

I get it that some people prefer C++ and find it more readable, but I prefer C (and I know there are people there that prefer C, too). (before programming only in C, I programmed in C++, too) I don't want to make this post a C vs C++, bc there's already a bunch on that in this forum.

 

The math part is kinda the one I'm more concerned to improve, tbh, as I don't have a great math background (I should've added that in the first post). I made this library checking codes from MonoGame and linmath. Linmath is in C, too, but missing some features that I added there (especially on quaternions and matrices).

Well, I totally get if you prefer the C style of coding over some of the C++ way of doing things.  So, if that's what you want then go for it.  But, my comments were not about C++ over C, they were about writing math code in math-heavy applications such as physics, or AI, or animation.  Having had to write a lot of that code, what I told you is the best advice I can give you.   You can have small code that closely resembles the mathematics your encoding, or you can have something that doesnt.  Considering you're already using a compiler that will compile both C and C++ (gcc compiles both very well), the only obstacle is really your personal preference.  And like I said, that's fine... especially if you're the only one who's every going to look at or work with that code.  In that situation, whatever makes you happy is the most important thing. 

On the other hand, if anyone else is ever going to work with your code, then you need to consider other things than your current personal preferences.  And I can guarantee you, anyone who has to come in and do any kind of math heavy lifting with this math library will not be a happy camper, unless they enjoy this type of code as much as you do.  I really doubt many people would consider 5 lines of code more readable than 1 line, especially when that 1 line closely matches the underlying mathematical equation that the code is executing.  And I doubt you will either in a few years if you have to do a lot of math coding.  

This topic is closed to new replies.

Advertisement