107 #ifndef MATH_3D_HEADER
108 #define MATH_3D_HEADER
114 #define M_PI 3.14159265358979323846
129 static inline vec3_t vec3(
float x,
float y,
float z) {
return (
vec3_t){x, y, z };}
132 static inline vec3_t v3_adds (
vec3_t a,
float s) {
return (
vec3_t){a.x + s, a.y + s, a.z + s };}
134 static inline vec3_t v3_subs (
vec3_t a,
float s) {
return (
vec3_t){a.x - s, a.y - s, a.z - s };}
136 static inline vec3_t v3_muls (
vec3_t a,
float s) {
return (
vec3_t){a.x * s, a.y * s, a.z * s };}
138 static inline vec3_t v3_divs (
vec3_t a,
float s) {
return (
vec3_t){a.x / s, a.y / s, a.z / s };}
139 static inline float v3_length(
vec3_t v) {
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);}
141 static inline float v3_dot (
vec3_t a,
vec3_t b) {
return a.x * b.x + a.y * b.y + a.z * b.z;}
144 static inline float v3_angle_between(
vec3_t a,
vec3_t b);
192 float m00, m01, m02, m03;
193 float m10, m11, m12, m13;
194 float m20, m21, m22, m23;
195 float m30, m31, m32, m33;
199 static inline mat4_t mat4(
200 float m00,
float m10,
float m20,
float m30,
201 float m01,
float m11,
float m21,
float m31,
202 float m02,
float m12,
float m22,
float m32,
203 float m03,
float m13,
float m23,
float m33
206 static inline mat4_t m4_identity ();
209 static inline mat4_t m4_rotation_x (
float angle_in_rad);
210 static inline mat4_t m4_rotation_y (
float angle_in_rad);
211 static inline mat4_t m4_rotation_z (
float angle_in_rad);
215 mat4_t m4_ortho_RH (
float left,
float right,
float bottom,
float top,
float back,
float front);
216 mat4_t m4_perspective_RH (
float vertical_field_of_view_in_deg,
float aspect_ratio,
float near_view_distance,
float far_view_distance);
224 mat4_t m4_frustum (
float left,
float right,
float bottom,
float top,
float near,
float far);
232 void m4_print (
mat4_t matrix);
233 void m4_printp (
mat4_t matrix,
int width,
int precision);
234 void m4_fprint (FILE* stream,
mat4_t matrix);
235 void m4_fprintp (FILE* stream,
mat4_t matrix,
int width,
int precision);
238 void m4_print2 (
mat4_t matrix,
const char *line_start);
239 void m4_printp2 (
mat4_t matrix,
int width,
int precision,
const char *line_start);
240 void m4_fprint2 (FILE* stream,
mat4_t matrix,
const char *line_start);
241 void m4_fprintp2 (FILE* stream,
mat4_t matrix,
int width,
int precision,
const char *line_start);
250 float len = v3_length(v);
252 return (
vec3_t){v.x / len, v.y / len, v.z / len};
260 return v3_muls(onto, v3_dot(v, onto) / v3_dot(onto, onto));
266 a.y * b.z - a.z * b.y,
267 a.z * b.x - a.x * b.z,
268 a.x * b.y - a.y * b.x
272 static inline float v3_angle_between(
vec3_t a,
vec3_t b)
274 return acosf(v3_dot(a, b) / (v3_length(a) * v3_length(b)));
281 static inline mat4_t mat4(
282 float m00,
float m10,
float m20,
float m30,
283 float m01,
float m11,
float m21,
float m31,
284 float m02,
float m12,
float m22,
float m32,
285 float m03,
float m13,
float m23,
float m33
289 .m[0][0] = m00, .m[1][0] = m10, .m[2][0] = m20, .m[3][0] = m30,
290 .m[0][1] = m01, .m[1][1] = m11, .m[2][1] = m21, .m[3][1] = m31,
291 .m[0][2] = m02, .m[1][2] = m12, .m[2][2] = m22, .m[3][2] = m32,
292 .m[0][3] = m03, .m[1][3] = m13, .m[2][3] = m23, .m[3][3] = m33
296 static inline mat4_t m4_identity()
318 float x = scale.x, y = scale.y, z = scale.z;
327 static inline mat4_t m4_rotation_x(
float angle_in_rad)
329 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
338 static inline mat4_t m4_rotation_y(
float angle_in_rad)
340 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
349 static inline mat4_t m4_rotation_z(
float angle_in_rad)
351 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
363 matrix.m00, matrix.m01, matrix.m02, matrix.m03,
364 matrix.m10, matrix.m11, matrix.m12, matrix.m13,
365 matrix.m20, matrix.m21, matrix.m22, matrix.m23,
366 matrix.m30, matrix.m31, matrix.m32, matrix.m33
385 for (i = 0; i < 4; i++) {
386 for (j = 0; j < 4; j++) {
388 for (k = 0; k < 4; k++) {
389 sum += a.m[k][j] * b.m[i][k];
391 result.m[i][j] = sum;
398 #endif // MATH_3D_HEADER
401 #ifdef MATH_3D_IMPLEMENTATION
413 vec3_t normalized_axis = v3_norm(axis);
414 float x = normalized_axis.x, y = normalized_axis.y, z = normalized_axis.z;
415 float c = cosf(angle_in_rad), s = sinf(angle_in_rad);
418 c + x * x * (1 - c), x * y * (1 - c) - z * s, x * z * (1 - c) + y * s, 0,
419 y * x * (1 - c) + z * s, c + y * y * (1 - c), y * z * (1 - c) - x * s, 0,
420 z * x * (1 - c) - y * s, z * y * (1 - c) + x * s, c + z * z * (1 - c), 0,
452 mat4_t m4_ortho_RH(
float left,
float right,
float bottom,
float top,
float back,
float front)
454 float l = left, r = right, b = bottom, t = top, n = front, f = back;
455 float tx = -(r + l) / (r - l);
456 float ty = -(t + b) / (t - b);
457 float tz = -(f + n) / (f - n);
460 2 / (r - l), 0, 0, tx,
461 0, 2 / (t - b), 0, ty,
462 0, 0, 2 / (f - n), tz,
487 mat4_t m4_perspective_RH(
float vertical_field_of_view_in_deg,
float aspect_ratio,
float near_view_distance,
float far_view_distance)
489 float fovy_in_rad = vertical_field_of_view_in_deg / 180 * M_PI;
490 float f = 1.0f / tanf(fovy_in_rad / 2.0f);
491 float ar = aspect_ratio;
492 float nd = near_view_distance, fd = far_view_distance;
497 0, 0, (fd + nd) / (nd - fd), (2 * fd * nd) / (nd - fd),
540 vec3_t z = v3_muls(v3_norm(v3_sub(to, from)), -1);
541 vec3_t x = v3_norm(v3_cross(up, z));
542 vec3_t y = v3_cross(z, x);
545 x.x, x.y, x.z, -v3_dot(from, x),
546 y.x, y.y, y.z, -v3_dot(from, y),
547 z.x, z.y, z.z, -v3_dot(from, z),
561 mat4_t m4_frustum(
float left,
float right,
float bottom,
float top,
float near,
float far)
564 if (fabs(left - right) < LG_FLOAT_EPSILON) {
565 INFO_ERR(
"left == right\n")
566 }
else if (fabs(bottom - top) < LG_FLOAT_EPSILON) {
567 INFO_ERR(
"bottom == top\n")
568 }
else if (far <= near) {
569 INFO_ERR(
"far <= near\n")
570 }
else if (near <= 0.0f) {
571 INFO_ERR(
"near <= 0.0f\n")
572 }
else if (far <= 0.0f) {
573 INFO_ERR(
"far <= 0.0f\n")
576 float width = right - left;
577 float height = top - bottom;
578 float depth = far - near;
579 float x = (2.0 * near) / width;
580 float y = (2.0 * near) / height;
581 float A = (right + left) / width;
582 float B = (top + bottom) / height;
583 float C = - (far + near) / depth;
584 float D = - (2.0 * far * near) / depth;
628 float m00 = matrix.m00, m10 = matrix.m10, m20 = matrix.m20, m30 = matrix.m30;
629 float m01 = matrix.m01, m11 = matrix.m11, m21 = matrix.m21, m31 = matrix.m31;
630 float m02 = matrix.m02, m12 = matrix.m12, m22 = matrix.m22, m32 = matrix.m32;
636 float c00 = m11 * m22 - m12 * m21, c10 = -(m01 * m22 - m02 * m21), c20 = m01 * m12 - m02 * m11;
637 float c01 = -(m10 * m22 - m12 * m20), c11 = m00 * m22 - m02 * m20, c21 = -(m00 * m12 - m02 * m10);
638 float c02 = m10 * m21 - m11 * m20, c12 = -(m00 * m21 - m01 * m20), c22 = m00 * m11 - m01 * m10;
643 float det = m00 * c00 + m10 * c10 + m20 * c20;
644 if (fabsf(det) < 0.00001) {
645 return m4_identity();
650 float i00 = c00 / det, i10 = c01 / det, i20 = c02 / det;
651 float i01 = c10 / det, i11 = c11 / det, i21 = c12 / det;
652 float i02 = c20 / det, i12 = c21 / det, i22 = c22 / det;
656 i00, i10, i20, -(i00 * m30 + i10 * m31 + i20 * m32),
657 i01, i11, i21, -(i01 * m30 + i11 * m31 + i21 * m32),
658 i02, i12, i22, -(i02 * m30 + i12 * m31 + i22 * m32),
673 matrix.m00 * position.x + matrix.m10 * position.y + matrix.m20 * position.z + matrix.m30,
674 matrix.m01 * position.x + matrix.m11 * position.y + matrix.m21 * position.z + matrix.m31,
675 matrix.m02 * position.x + matrix.m12 * position.y + matrix.m22 * position.z + matrix.m32
678 float w = matrix.m03 * position.x + matrix.m13 * position.y + matrix.m23 * position.z + matrix.m33;
679 if (w != 0 && w != 1) {
680 return vec3(result.x / w, result.y / w, result.z / w);
700 matrix.m00 * direction.x + matrix.m10 * direction.y + matrix.m20 * direction.z,
701 matrix.m01 * direction.x + matrix.m11 * direction.y + matrix.m21 * direction.z,
702 matrix.m02 * direction.x + matrix.m12 * direction.y + matrix.m22 * direction.z
705 float w = matrix.m03 * direction.x + matrix.m13 * direction.y + matrix.m23 * direction.z;
706 if (w != 0 && w != 1) {
707 return vec3(result.x / w, result.y / w, result.z / w);
713 void m4_print(
mat4_t matrix)
715 m4_fprintp(STD_OUT, matrix, 6, 2);
718 void m4_printp(
mat4_t matrix,
int width,
int precision)
720 m4_fprintp(STD_OUT, matrix, width, precision);
723 void m4_fprint(FILE* stream,
mat4_t matrix)
725 m4_fprintp(stream, matrix, 6, 2);
728 void m4_fprintp(FILE* stream,
mat4_t matrix,
int width,
int precision)
731 int w = width, p = precision, r;
733 for (r = 0; r < 4; r++) {
734 fprintf(stream,
"| %*.*f %*.*f %*.*f %*.*f |\n",
735 w, p, m.m[0][r], w, p, m.m[1][r], w, p, m.m[2][r], w, p, m.m[3][r]
741 void m4_print2(
mat4_t matrix,
const char *line_start)
743 m4_fprintp2(STD_OUT, matrix, 6, 2, line_start);
746 void m4_printp2(
mat4_t matrix,
int width,
int precision,
const char *line_start)
748 m4_fprintp2(STD_OUT, matrix, width, precision, line_start);
751 void m4_fprint2(FILE* stream,
mat4_t matrix,
const char *line_start)
753 m4_fprintp2(stream, matrix, 6, 2, line_start);
755 void m4_fprintp2(FILE* stream,
mat4_t matrix,
int width,
int precision,
const char *line_start)
758 int w = width, p = precision, r;
760 for (r = 0; r < 4; r++) {
761 fprintf(stream,
"%s| %*.*f %*.*f %*.*f %*.*f |\n",
762 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]
767 #endif // MATH_3D_IMPLEMENTATION