🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

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

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

I have just looked over the api and it seem pretty reasonable, but here are some tips:

- The naming of the structs are too long (cvector2? cvec2 or even vec2 are much better)

- If you want to convince people to use your library or given proper feedback you better add C++ operator overloading and namespace support. Through ifdef you can exclude that features from native C if needed
- There are no swizzling, array, or union support (This so much more usable):

- There are no vec2i (Its not always float, sometimes there is even a double vec4d or mat4d)

- No SIMD (SSE/SSE2) implementation (This improves performance a lot, especially for mat4 operations)

 

Example of a better struct definition:


union vec2i {
	struct {
		int x, y;
	};
	struct {
		int w, h;
	};
	int m[2];
};

union vec2f {
	struct {
		float x, y;
	};
	struct {
		float w, h;
	};
	float m[2];
};

union vec4f {
	struct {
		union {
			vec3f xyz;
			struct {
				float x, y, z;
			};
		};
		float w;
	};
	struct {
		union {
			vec3f rgb;
			struct {
				float r, g, b;
			};
		};
		float a;
	};
	struct {
		vec3f xyz;
		float w;
	};
	struct {
		vec2f xy;
		float ignored0;
		float ignored1;
	};
	struct {
		float ignored2;
		vec2f yz;
		float ignored3;
	};
	struct {
		float ignored4;
		float ignored5;
		vec2f zw;
	};
	float m[4];
};

union mat4f {
	struct {
		vec4f col1;
		vec4f col2;
		vec4f col3;
		vec4f col4;
	};
	float m[16];
};

 

Advertisement

Few seldom things (that might have already been said above):

Consider passing parameters by pointers for most of your operations involving vectors, matrices or quaternions. This will be far more fast. Make them const if necessary.

Consider using an array for your structures. Well, at least if in C (which I'm not sure about), alignment is not mandatory for structures members.

Consider splitting your file. If you create something for 2D and 3D games, then one that would like to make 2D games only does not care about vector3 for example.

 

5 hours ago, ferreiradaselva said:

Especially on the math aspects (lacking functions, math errors)

For lacking functions, depending on what you want, many may be lacking :) I suggest you to add them as you need them, or as your potential users will require them.

7 hours ago, Finalspace said:

- The naming of the structs are too long (cvector2? cvec2 or even vec2 are much better)

Not sure if the "tor" add too much to it. But I will keep an open mind about it.

7 hours ago, Finalspace said:

- If you want to convince people to use your library or given proper feedback you better add C++ operator overloading and namespace support. Through ifdef you can exclude that features from native C if needed

I will make a wrap for c++, probably on a different header.

7 hours ago, Finalspace said:

- There are no swizzling, array, or union support (This so much more usable):

That's a very nice change, and I will work on it soon.

7 hours ago, Finalspace said:

- There are no vec2i (Its not always float, sometimes there is even a double vec4d or mat4d)

I will add the integer implementations. Not sure about the double, though.

7 hours ago, Finalspace said:

- No SIMD (SSE/SSE2) implementation (This improves performance a lot, especially for mat4 operations)

I was aware about SIMD, but it's still something I never worked with, so that one will probably take some time to implement. Still on the list, tho.

6 hours ago, _Silence_ said:

Consider passing parameters by pointers for most of your operations involving vectors, matrices or quaternions. This will be far more fast. Make them const if necessary.

This is a good thing (and was requested on other forum). I will add functions that take the parameters as pointers. Probably adding a `p` prefix will suffice to determine they are for pointers.

I want to keep the functions that take them as value (affect performance, but quick to work with).

6 hours ago, _Silence_ said:

Consider using an array for your structures. Well, at least if in C (which I'm not sure about), alignment is not mandatory for structures members.

This is similar with the union mentioned above. I will work on it.

6 hours ago, _Silence_ said:

Consider splitting your file. If you create something for 2D and 3D games, then one that would like to make 2D games only does not care about vector3 for example.

I will probably make add an ifdef/endif with macros like VEC2_IMPL, VEC3_IMPL, etc. Just to keep it only two files (easier to add to a project).

 

Everyone, thanks for the feedback! :D

My lib was trending on github yesterday (on the C category, at least)! :D

I decided to not to make a C++ binding. It doesn't make sense. There's already GLM for that.

I have added functions that take pointers, and still giving support to the functions that take the structures as pointers:


void pvector3_multiply(cvector3 *a, cvector3 *b, cvector3 *result)
{
	result->x = a->x * b->x;
	result->y = a->y * b->y;
	result->z = a->z * b->z;
}

MATHC_EXTERN_INLINE cvector3 vector3_multiply(cvector3 a, cvector3 b)
{
	cvector3 result;
	pvector3_multiply(&a, &b, &result);
	return result;
}

All the math happens in the functions that take pointers, that way I don't need to rewrite two versions if something needs to change.

Also, I made a quaternion slerp function today. I still need to compare with other engines, but it gives the same results with Blender, but not with Godot. Since the Godot implementation works (according with some youtube videos), I imagine the slerp function is different to satisfy something with the other Godot math functions. 

On 10/5/2017 at 3:39 AM, 0r0d said:

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

Technically, you can re-assign the passed parameters to a function in C/C++.

I wonder if one could actually obtain a performance benefit by adding the "const" since in 99.99% of the cases you don't modify the passed parameters?

🧙

5 hours ago, matt77hias said:

Technically, you can re-assign the passed parameters to a function in C/C++.

I wonder if one could actually obtain a performance benefit by adding the "const" since in 99.99% of the cases you don't modify the passed parameters?

Those were the reason I used 'const', BUT apparently there's not performance benefit from using 'const'. I couldn't find any difference in the assembly output between the version with 'const' and the version without it.

1 minute ago, ferreiradaselva said:

Those were the reason I used 'const', BUT apparently there's not performance benefit from using 'const'. I couldn't find any difference in the assembly output between the version with 'const' and the version without it.

Thanks for letting me know! (If someone claimed the opposite, I would become crazy changing all my code bases) :)

🧙

Bumping this because I've added a bunch of operations with quaternions and I have an almost complete reference at this point:

https://github.com/ferreiradaselva/mathc/blob/master/REFERENCE.md

So to get to your library:

You have no different vector types, you have just one "vec" structure which is 32 bytes long, but you have functions which operates on 2D and 3D and 4D data only. So this will waste memory when you use 2D operations only.

Really there should be a vec2, vec3 and a vec4 and even quaternion should be a seperate quaternion structure. For matrices its the same, mat2, mat3 and mat4. Access them by an array and wrap them to union makes that possible without problems.

 

Now to const:

Const or const reference has no difference for generated code vs pointers - so no difference in performance.

But it makes the documentation / api of your functions more clear, which is input and which is output.

From what i have read about consts and seen in practice, it will just produce compiler errors when you try to modify something which is marked as const. And this gets really persistent in class methods. It forces you to use const in all places.

The best explanation about const i found so far (..."Its kind of a fake keyword"...):

 

1 hour ago, Finalspace said:

 

From what i have read about consts and seen in practice, it will just produce compiler errors when you try to modify something which is marked as const. And this gets really persistent in class methods. It forces you to use const in all places.

 

Well, when you specify something as "const", as with function input parameters, you're defining your contract with the user of that function.  If you find yourself trying to modify something that's const, you either screwed up or the person who defined that API screwed up.  Getting rid of the const is not the answer because that just hides the fact that there's some lazy programming going on.  Now, it's true that if the laziness is pervasive throughout the codebase, then you will find yourself having to go around modifying a bunch of stuff... and some might be difficult because of said laziness in the coding.   So, of course, it's up to you on how to proceed.  My personal approach is to make sure the entire codebase is const-correct as I write it and the problem never arises.  It's not hard, it's just a matter of thinking about what a function/variable does when you write it, and then declare it appropriately.  If some assumption changes, then I change the API and everyone is happy.  This pays off later in better code, fewer bugs or bugs caught earlier, and less headaches.  You also give the compiler the option to generate more optimal code.  It might not in most cases, but it could in certain specific situations.

More information on const correctness:

https://isocpp.org/wiki/faq/const-correctness

This topic is closed to new replies.

Advertisement