90 #ifndef MATH_3D_HEADER
91 #define MATH_3D_HEADER
97 #define M_PI 3.14159265358979323846
112 static inline vec3_t vec3(
float x,
float y,
float z) {
return (
vec3_t){x, y, z };}
115 static inline vec3_t v3_adds (
vec3_t a,
float s) {
return (
vec3_t){a.x + s, a.y + s, a.z + s };}
117 static inline vec3_t v3_subs (
vec3_t a,
float s) {
return (
vec3_t){a.x - s, a.y - s, a.z - s };}
119 static inline vec3_t v3_muls (
vec3_t a,
float s) {
return (
vec3_t){a.x * s, a.y * s, a.z * s };}
121 static inline vec3_t v3_divs (
vec3_t a,
float s) {
return (
vec3_t){a.x / s, a.y / s, a.z / s };}
122 static inline float v3_length(
vec3_t v) {
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);}
124 static inline float v3_dot (
vec3_t a,
vec3_t b) {
return a.x * b.x + a.y * b.y + a.z * b.z;}
127 static inline float v3_angle_between(
vec3_t a,
vec3_t b);
175 float m00, m01, m02, m03;
176 float m10, m11, m12, m13;
177 float m20, m21, m22, m23;
178 float m30, m31, m32, m33;
182 static inline mat4_t mat4(
183 float m00,
float m10,
float m20,
float m30,
184 float m01,
float m11,
float m21,
float m31,
185 float m02,
float m12,
float m22,
float m32,
186 float m03,
float m13,
float m23,
float m33
189 static inline mat4_t m4_identity ();
192 static inline mat4_t m4_rotation_x (
float angle_in_rad);
193 static inline mat4_t m4_rotation_y (
float angle_in_rad);
194 static inline mat4_t m4_rotation_z (
float angle_in_rad);
197 mat4_t m4_ortho (
float left,
float right,
float bottom,
float top,
float back,
float front);
198 mat4_t m4_perspective (
float vertical_field_of_view_in_deg,
float aspect_ratio,
float near_view_distance,
float far_view_distance);
199 mat4_t m4_frustum (
float left,
float right,
float bottom,
float top,
float near,
float far);
208 void m4_print (
mat4_t matrix);
209 void m4_printp (
mat4_t matrix,
int width,
int precision);
210 void m4_fprint (FILE* stream,
mat4_t matrix);
211 void m4_fprintp (FILE* stream,
mat4_t matrix,
int width,
int precision);
214 void m4_print2 (
mat4_t matrix,
const char *line_start);
215 void m4_printp2 (
mat4_t matrix,
int width,
int precision,
const char *line_start);
216 void m4_fprint2 (FILE* stream,
mat4_t matrix,
const char *line_start);
217 void m4_fprintp2 (FILE* stream,
mat4_t matrix,
int width,
int precision,
const char *line_start);
226 float len = v3_length(v);
228 return (
vec3_t){v.x / len, v.y / len, v.z / len};
236 return v3_muls(onto, v3_dot(v, onto) / v3_dot(onto, onto));
242 a.y * b.z - a.z * b.y,
243 a.z * b.x - a.x * b.z,
244 a.x * b.y - a.y * b.x
248 static inline float v3_angle_between(
vec3_t a,
vec3_t b)
250 return acosf(v3_dot(a, b) / (v3_length(a) * v3_length(b)));
257 static inline mat4_t mat4(
258 float m00,
float m10,
float m20,
float m30,
259 float m01,
float m11,
float m21,
float m31,
260 float m02,
float m12,
float m22,
float m32,
261 float m03,
float m13,
float m23,
float m33
265 .m[0][0] = m00, .m[1][0] = m10, .m[2][0] = m20, .m[3][0] = m30,
266 .m[0][1] = m01, .m[1][1] = m11, .m[2][1] = m21, .m[3][1] = m31,
267 .m[0][2] = m02, .m[1][2] = m12, .m[2][2] = m22, .m[3][2] = m32,
268 .m[0][3] = m03, .m[1][3] = m13, .m[2][3] = m23, .m[3][3] = m33
272 static inline mat4_t m4_identity()
294 float x = scale.x, y = scale.y, z = scale.z;
303 static inline mat4_t m4_rotation_x(
float angle_in_rad)
305 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
314 static inline mat4_t m4_rotation_y(
float angle_in_rad)
316 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
325 static inline mat4_t m4_rotation_z(
float angle_in_rad)
327 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
339 matrix.m00, matrix.m01, matrix.m02, matrix.m03,
340 matrix.m10, matrix.m11, matrix.m12, matrix.m13,
341 matrix.m20, matrix.m21, matrix.m22, matrix.m23,
342 matrix.m30, matrix.m31, matrix.m32, matrix.m33
361 for (i = 0; i < 4; i++) {
362 for (j = 0; j < 4; j++) {
364 for (k = 0; k < 4; k++) {
365 sum += a.m[k][j] * b.m[i][k];
367 result.m[i][j] = sum;
374 #endif // MATH_3D_HEADER
377 #ifdef MATH_3D_IMPLEMENTATION
389 vec3_t normalized_axis = v3_norm(axis);
390 float x = normalized_axis.x, y = normalized_axis.y, z = normalized_axis.z;
391 float c = cosf(angle_in_rad), s = sinf(angle_in_rad);
394 c + x * x * (1 - c), x * y * (1 - c) - z * s, x * z * (1 - c) + y * s, 0,
395 y * x * (1 - c) + z * s, c + y * y * (1 - c), y * z * (1 - c) - x * s, 0,
396 z * x * (1 - c) - y * s, z * y * (1 - c) + x * s, c + z * z * (1 - c), 0,
428 mat4_t m4_ortho(
float left,
float right,
float bottom,
float top,
float back,
float front)
430 float l = left, r = right, b = bottom, t = top, n = front, f = back;
431 float tx = -(r + l) / (r - l);
432 float ty = -(t + b) / (t - b);
433 float tz = -(f + n) / (f - n);
436 2 / (r - l), 0, 0, tx,
437 0, 2 / (t - b), 0, ty,
438 0, 0, 2 / (f - n), tz,
463 mat4_t m4_perspective(
float vertical_field_of_view_in_deg,
float aspect_ratio,
float near_view_distance,
float far_view_distance)
465 float fovy_in_rad = vertical_field_of_view_in_deg / 180 * M_PI;
466 float f = 1.0f / tanf(fovy_in_rad / 2.0f);
467 float ar = aspect_ratio;
468 float nd = near_view_distance, fd = far_view_distance;
473 0, 0, (fd + nd) / (nd - fd), (2 * fd * nd) / (nd - fd),
487 mat4_t m4_frustum(
float left,
float right,
float bottom,
float top,
float near,
float far)
490 if (fabs(left - right) < LG_FLOAT_EPSILON) {
491 INFO_ERR(
"left == right\n")
492 }
else if (fabs(bottom - top) < LG_FLOAT_EPSILON) {
493 INFO_ERR(
"bottom == top\n")
494 }
else if (far <= near) {
495 INFO_ERR(
"far <= near\n")
496 }
else if (near <= 0.0f) {
497 INFO_ERR(
"near <= 0.0f\n")
498 }
else if (far <= 0.0f) {
499 INFO_ERR(
"far <= 0.0f\n")
502 float width = right - left;
503 float height = top - bottom;
504 float depth = far - near;
505 float x = (2.0 * near) / width;
506 float y = (2.0 * near) / height;
507 float A = (right + left) / width;
508 float B = (top + bottom) / height;
509 float C = - (far + near) / depth;
510 float D = - (2.0 * far * near) / depth;
559 vec3_t z = v3_muls(v3_norm(v3_sub(to, from)), -1);
560 vec3_t x = v3_norm(v3_cross(up, z));
561 vec3_t y = v3_cross(z, x);
564 x.x, x.y, x.z, -v3_dot(from, x),
565 y.x, y.y, y.z, -v3_dot(from, y),
566 z.x, z.y, z.z, -v3_dot(from, z),
604 float m00 = matrix.m00, m10 = matrix.m10, m20 = matrix.m20, m30 = matrix.m30;
605 float m01 = matrix.m01, m11 = matrix.m11, m21 = matrix.m21, m31 = matrix.m31;
606 float m02 = matrix.m02, m12 = matrix.m12, m22 = matrix.m22, m32 = matrix.m32;
612 float c00 = m11 * m22 - m12 * m21, c10 = -(m01 * m22 - m02 * m21), c20 = m01 * m12 - m02 * m11;
613 float c01 = -(m10 * m22 - m12 * m20), c11 = m00 * m22 - m02 * m20, c21 = -(m00 * m12 - m02 * m10);
614 float c02 = m10 * m21 - m11 * m20, c12 = -(m00 * m21 - m01 * m20), c22 = m00 * m11 - m01 * m10;
619 float det = m00 * c00 + m10 * c10 + m20 * c20;
620 if (fabsf(det) < 0.00001) {
621 return m4_identity();
626 float i00 = c00 / det, i10 = c01 / det, i20 = c02 / det;
627 float i01 = c10 / det, i11 = c11 / det, i21 = c12 / det;
628 float i02 = c20 / det, i12 = c21 / det, i22 = c22 / det;
632 i00, i10, i20, -(i00 * m30 + i10 * m31 + i20 * m32),
633 i01, i11, i21, -(i01 * m30 + i11 * m31 + i21 * m32),
634 i02, i12, i22, -(i02 * m30 + i12 * m31 + i22 * m32),
649 matrix.m00 * position.x + matrix.m10 * position.y + matrix.m20 * position.z + matrix.m30,
650 matrix.m01 * position.x + matrix.m11 * position.y + matrix.m21 * position.z + matrix.m31,
651 matrix.m02 * position.x + matrix.m12 * position.y + matrix.m22 * position.z + matrix.m32
654 float w = matrix.m03 * position.x + matrix.m13 * position.y + matrix.m23 * position.z + matrix.m33;
655 if (w != 0 && w != 1) {
656 return vec3(result.x / w, result.y / w, result.z / w);
676 matrix.m00 * direction.x + matrix.m10 * direction.y + matrix.m20 * direction.z,
677 matrix.m01 * direction.x + matrix.m11 * direction.y + matrix.m21 * direction.z,
678 matrix.m02 * direction.x + matrix.m12 * direction.y + matrix.m22 * direction.z
681 float w = matrix.m03 * direction.x + matrix.m13 * direction.y + matrix.m23 * direction.z;
682 if (w != 0 && w != 1) {
683 return vec3(result.x / w, result.y / w, result.z / w);
689 void m4_print(
mat4_t matrix)
691 m4_fprintp(STD_OUT, matrix, 6, 2);
694 void m4_printp(
mat4_t matrix,
int width,
int precision)
696 m4_fprintp(STD_OUT, matrix, width, precision);
699 void m4_fprint(FILE* stream,
mat4_t matrix)
701 m4_fprintp(stream, matrix, 6, 2);
704 void m4_fprintp(FILE* stream,
mat4_t matrix,
int width,
int precision)
707 int w = width, p = precision, r;
709 for (r = 0; r < 4; r++) {
710 fprintf(stream,
"| %*.*f %*.*f %*.*f %*.*f |\n",
711 w, p, m.m[0][r], w, p, m.m[1][r], w, p, m.m[2][r], w, p, m.m[3][r]
717 void m4_print2(
mat4_t matrix,
const char *line_start)
719 m4_fprintp2(STD_OUT, matrix, 6, 2, line_start);
722 void m4_printp2(
mat4_t matrix,
int width,
int precision,
const char *line_start)
724 m4_fprintp2(STD_OUT, matrix, width, precision, line_start);
727 void m4_fprint2(FILE* stream,
mat4_t matrix,
const char *line_start)
729 m4_fprintp2(stream, matrix, 6, 2, line_start);
731 void m4_fprintp2(FILE* stream,
mat4_t matrix,
int width,
int precision,
const char *line_start)
734 int w = width, p = precision, r;
736 for (r = 0; r < 4; r++) {
737 fprintf(stream,
"%s| %*.*f %*.*f %*.*f %*.*f |\n",
738 line_start, w, p, m.m[0][r], w, p, m.m[1][r], w, p, m.m[2][r], w, p, m.m[3][r]
743 #endif // MATH_3D_IMPLEMENTATION