handmade.network » Forums » Work-in-Progress » MATHC - Pure C math library for 2D and 3D programming
ferreiradaselva
Pengo
6 posts

Biologist (genomics); C programmer; Game development and art as hobbies.

#13545 MATHC - Pure C math library for 2D and 3D programming
4 weeks ago Edited by Pengo on Nov. 19, 2017, 9:57 a.m.

As I was working on my own game framework, I decided to decouple the math source on its own library:

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

This is mainly for OpenGL.

Features
  • 2D vectors
  • 3D vectors
  • Quaternions
  • Matrices
  • Easing functions

Planned Features
Currently the library reached the first major release, but I'm adding features that don't break compatibility, and suggestions for features that break compatibility are welcome, saved for the next major release (2.0.0).

The next feature I'm planning is detection for 2D and 3D primitives (circles, lines and triangles, both 2D and 3D).

Pointers vs. Values
There are two versions of the same function, one that take pointer arguments and other that take value arguments:

1
2
pmatrix_look_at(&pos, &target, &view);
view = matrix_look_at(pos, target);

Other examples in the GitHub page.

Taking pointers is certainly faster, but you can use the function that take values if performance is not critical for you, as they are more readable.

Single Vector Structure
There's only one vector structure, used for 2D vectors, 3D vectors and quaternions. When I had to use 2D vectors, sometimes I would want to use them as 3D vectors and vice-versa. So I decided to use the same structure to make this possible.

Easing Functions
The easing functions are great for animations: it makes easier to make smooth and organic motions.

Why another math library?
This is not intended to be a competitor with other math libraries, but a small and simple alternative.

CGDFW - C Game Development Framework | MATHC - Math library for 2D and 3D programming
ratchetfreak
322 posts
#13547 MATHC - Pure C math library for 2D and 3D programming
4 weeks ago

A few comments about the quaternion part:

The null quaternion is 0,0,0,1 instead of all 0. There is no construction function for that.

The way to get the shortest rotation between 2 vectors can be faster if you skip the acos into sincos by doing:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void pquaternion_from_2_vectors(struct vec *a, struct vec *b, struct vec *result){
    float dot = pvector3_dot(a, b);
    struct vec cross;

    float a_length_sq = pvector3_length_squared(a);
    float b_length_sq = pvector3_length_squared(a);

    pvector3_cross(a, b, &cross);
    to_pquaternion(cross.x, cross.y, cross.z, dot+sqrtf(a_length_sq*b_length_sq), result);
    pquaternion_normalize(result, result);
}


Your quat to matrix codes expects normalized quaternions, if you replace the 1.0f with the length squared or divide the xx, yy, zz, etd. with that you can fix that.
ferreiradaselva
Pengo
6 posts

Biologist (genomics); C programmer; Game development and art as hobbies.

#13548 MATHC - Pure C math library for 2D and 3D programming
4 weeks ago

ratchetfreak
A few comments about the quaternion part:

The null quaternion is 0,0,0,1 instead of all 0. There is no construction function for that.

The way to get the shortest rotation between 2 vectors can be faster if you skip the acos into sincos by doing:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void pquaternion_from_2_vectors(struct vec *a, struct vec *b, struct vec *result){
    float dot = pvector3_dot(a, b);
    struct vec cross;

    float a_length_sq = pvector3_length_squared(a);
    float b_length_sq = pvector3_length_squared(a);

    pvector3_cross(a, b, &cross);
    to_pquaternion(cross.x, cross.y, cross.z, dot+sqrtf(a_length_sq*b_length_sq), result);
    pquaternion_normalize(result, result);
}


Your quat to matrix codes expects normalized quaternions, if you replace the 1.0f with the length squared or divide the xx, yy, zz, etd. with that you can fix that.


Thanks for those inputs (and the ones on GitHub)! I will work on the fix for that :)

CGDFW - C Game Development Framework | MATHC - Math library for 2D and 3D programming
ratchetfreak
322 posts
#13549 MATHC - Pure C math library for 2D and 3D programming
4 weeks ago

one more comment, the reason most slerp implementations use 0.95 as the cutoff for switching to normalized lerp. Is because there is a pole of inaccuracy when the input of acos nears 1 and less bits have useful information.

I've derived that using the normalized lerp to 0.5 is the exact same as the slerp to 0.5. So you can binary search into that for up to 5 iterations and then lerp to finish off. The 5 is based on how quickly the 2 boundaries converge from nearly opposite (dot~-1) to above the traditional cutoff (dot~0.95).
mmozeiko
Mārtiņš Možeiko
1520 posts
1 project
#13555 MATHC - Pure C math library for 2D and 3D programming
4 weeks ago

I don't think this is link to what you want: http://reference.md/
raysan5
Ray
35 posts
1 project

I teach videogames programming.

#13570 MATHC - Pure C math library for 2D and 3D programming
3 weeks, 5 days ago

I created a similar library for raylib, it's a single-file header-only Vector2-Vector3-Quaternion-Matrix math library: raymath.h.

Maybe it could be useful for you as a reference.

And also created easings.h based on Robert Penner's easing functions.

ferreiradaselva
Pengo
6 posts

Biologist (genomics); C programmer; Game development and art as hobbies.

#13575 MATHC - Pure C math library for 2D and 3D programming
3 weeks, 4 days ago

ratchetfreak
one more comment, the reason most slerp implementations use 0.95 as the cutoff for switching to normalized lerp. Is because there is a pole of inaccuracy when the input of acos nears 1 and less bits have useful information.

I've derived that using the normalized lerp to 0.5 is the exact same as the slerp to 0.5. So you can binary search into that for up to 5 iterations and then lerp to finish off. The 5 is based on how quickly the 2 boundaries converge from nearly opposite (dot~-1) to above the traditional cutoff (dot~0.95).

And I thought that was something arbitrary! :P Thanks for the info, I fixed that.

mmozeiko
I don't think this is link to what you want: http://reference.md/

Fixed.

raysan5
I created a similar library for raylib, it's a single-file header-only Vector2-Vector3-Quaternion-Matrix math library: raymath.h.

Maybe it could be useful for you as a reference.


Thanks! I will make some comparisons, indeed 😄

raysan5

And also created easings.h based on Robert Penner's easing functions.

We both used the same reference 😄 I'm really thinking about expanding that list of easing functions. I currently use some of the functions in a game I'm making and they are great to add some juicyness to the game!

CGDFW - C Game Development Framework | MATHC - Math library for 2D and 3D programming
ferreiradaselva
Pengo
6 posts

Biologist (genomics); C programmer; Game development and art as hobbies.

#13576 MATHC - Pure C math library for 2D and 3D programming
3 weeks, 4 days ago

UPDATE

Added some functions to test if a pointer is inside or outside a circle or triangle:

1
2
3
4
5
bool pvector2_in_circle(struct vec *v, struct vec *circle_position, float radius);
bool pvector2_in_triangle(struct vec *v, struct vec *a, struct vec *b, struct vec *c);

bool vector2_in_circle(struct vec v, struct vec circle_position, float radius);
bool vector2_in_triangle(struct vec v, struct vec a, struct vec b, struct vec c);


I will soon add some functions to test circle-circle, circle-triangle, triangle-triangle intersection both 2D and 3D (sphere in the case of 3D). That's how far I will go with intersections, because I want to provide only test with primitives.


CGDFW - C Game Development Framework | MATHC - Math library for 2D and 3D programming