101 #ifndef MATH_3D_HEADER
102 #define MATH_3D_HEADER
109 #define M_PI 3.14159265358979323846
124 static inline vec3_t vec3(
float x,
float y,
float z) {
return (
vec3_t){x, y, z };}
127 static inline vec3_t v3_adds (
vec3_t a,
float s) {
return (
vec3_t){a.x + s, a.y + s, a.z + s };}
129 static inline vec3_t v3_subs (
vec3_t a,
float s) {
return (
vec3_t){a.x - s, a.y - s, a.z - s };}
131 static inline vec3_t v3_muls (
vec3_t a,
float s) {
return (
vec3_t){a.x * s, a.y * s, a.z * s };}
133 static inline vec3_t v3_divs (
vec3_t a,
float s) {
return (
vec3_t){a.x / s, a.y / s, a.z / s };}
134 static inline float v3_length(
vec3_t v) {
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);}
136 static inline float v3_dot (
vec3_t a,
vec3_t b) {
return a.x * b.x + a.y * b.y + a.z * b.z;}
139 static inline float v3_angle_between(
vec3_t a,
vec3_t b);
188 float m00, m01, m02, m03;
189 float m10, m11, m12, m13;
190 float m20, m21, m22, m23;
191 float m30, m31, m32, m33;
195 static inline mat4_t mat4(
196 float m00,
float m10,
float m20,
float m30,
197 float m01,
float m11,
float m21,
float m31,
198 float m02,
float m12,
float m22,
float m32,
199 float m03,
float m13,
float m23,
float m33
202 static inline mat4_t m4_identity ();
205 static inline mat4_t m4_rotation_x (
float angle_in_rad);
206 static inline mat4_t m4_rotation_y (
float angle_in_rad);
207 static inline mat4_t m4_rotation_z (
float angle_in_rad);
211 mat4_t m4_ortho_RH (
float left,
float right,
float bottom,
float top,
float back,
float front);
212 mat4_t m4_perspective_RH (
float vertical_field_of_view_in_deg,
float aspect_ratio,
float near_view_distance,
float far_view_distance);
220 mat4_t m4_frustum (
float left,
float right,
float bottom,
float top,
float near,
float far);
228 void m4_print (
mat4_t matrix);
229 void m4_printp (
mat4_t matrix,
int width,
int precision);
230 void m4_fprint (FILE* stream,
mat4_t matrix);
231 void m4_fprintp (FILE* stream,
mat4_t matrix,
int width,
int precision);
234 void m4_print2 (
mat4_t matrix,
const char *line_start);
235 void m4_printp2 (
mat4_t matrix,
int width,
int precision,
const char *line_start);
236 void m4_fprint2 (FILE* stream,
mat4_t matrix,
const char *line_start);
237 void m4_fprintp2 (FILE* stream,
mat4_t matrix,
int width,
int precision,
const char *line_start);
246 float len = v3_length(v);
248 return (
vec3_t){v.x / len, v.y / len, v.z / len};
256 return v3_muls(onto, v3_dot(v, onto) / v3_dot(onto, onto));
262 a.y * b.z - a.z * b.y,
263 a.z * b.x - a.x * b.z,
264 a.x * b.y - a.y * b.x
268 static inline float v3_angle_between(
vec3_t a,
vec3_t b)
270 return acosf(v3_dot(a, b) / (v3_length(a) * v3_length(b)));
277 static inline mat4_t mat4(
278 float m00,
float m10,
float m20,
float m30,
279 float m01,
float m11,
float m21,
float m31,
280 float m02,
float m12,
float m22,
float m32,
281 float m03,
float m13,
float m23,
float m33
285 .m[0][0] = m00, .m[1][0] = m10, .m[2][0] = m20, .m[3][0] = m30,
286 .m[0][1] = m01, .m[1][1] = m11, .m[2][1] = m21, .m[3][1] = m31,
287 .m[0][2] = m02, .m[1][2] = m12, .m[2][2] = m22, .m[3][2] = m32,
288 .m[0][3] = m03, .m[1][3] = m13, .m[2][3] = m23, .m[3][3] = m33
292 static inline mat4_t m4_identity()
314 float x = scale.x, y = scale.y, z = scale.z;
323 static inline mat4_t m4_rotation_x(
float angle_in_rad)
325 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
334 static inline mat4_t m4_rotation_y(
float angle_in_rad)
336 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
345 static inline mat4_t m4_rotation_z(
float angle_in_rad)
347 float s = sinf(angle_in_rad), c = cosf(angle_in_rad);
359 matrix.m00, matrix.m01, matrix.m02, matrix.m03,
360 matrix.m10, matrix.m11, matrix.m12, matrix.m13,
361 matrix.m20, matrix.m21, matrix.m22, matrix.m23,
362 matrix.m30, matrix.m31, matrix.m32, matrix.m33
381 for (i = 0; i < 4; i++) {
382 for (j = 0; j < 4; j++) {
384 for (k = 0; k < 4; k++) {
385 sum += a.m[k][j] * b.m[i][k];
387 result.m[i][j] = sum;
394 #endif // MATH_3D_HEADER
397 #ifdef MATH_3D_IMPLEMENTATION
415 vec3_t normalized_axis = v3_norm(axis);
416 float x = normalized_axis.x, y = normalized_axis.y, z = normalized_axis.z;
417 float c = cosf(angle_in_rad), s = sinf(angle_in_rad);
420 c + x * x * (1 - c), x * y * (1 - c) - z * s, x * z * (1 - c) + y * s, 0,
421 y * x * (1 - c) + z * s, c + y * y * (1 - c), y * z * (1 - c) - x * s, 0,
422 z * x * (1 - c) - y * s, z * y * (1 - c) + x * s, c + z * z * (1 - c), 0,
454 mat4_t m4_ortho_RH(
float left,
float right,
float bottom,
float top,
float back,
float front)
456 float l = left, r = right, b = bottom, t = top, n = front, f = back;
457 float tx = -(r + l) / (r - l);
458 float ty = -(t + b) / (t - b);
459 float tz = -(f + n) / (f - n);
462 2 / (r - l), 0, 0, tx,
463 0, 2 / (t - b), 0, ty,
464 0, 0, 2 / (f - n), tz,
489 mat4_t m4_perspective_RH(
float vertical_field_of_view_in_deg,
float aspect_ratio,
float near_view_distance,
float far_view_distance)
491 float fovy_in_rad = vertical_field_of_view_in_deg / 180 * M_PI;
492 float f = 1.0f / tanf(fovy_in_rad / 2.0f);
493 float ar = aspect_ratio;
494 float nd = near_view_distance, fd = far_view_distance;
499 0, 0, (fd + nd) / (nd - fd), (2 * fd * nd) / (nd - fd),
542 vec3_t z = v3_muls(v3_norm(v3_sub(to, from)), -1);
543 vec3_t x = v3_norm(v3_cross(up, z));
544 vec3_t y = v3_cross(z, x);
547 x.x, x.y, x.z, -v3_dot(from, x),
548 y.x, y.y, y.z, -v3_dot(from, y),
549 z.x, z.y, z.z, -v3_dot(from, z),
563 mat4_t m4_frustum(
float left,
float right,
float bottom,
float top,
float near,
float far)
566 if (fabs(left - right) < LG_FLOAT_EPSILON) {
567 INFO_ERR(
"left == right\n")
568 }
else if (fabs(bottom - top) < LG_FLOAT_EPSILON) {
569 INFO_ERR(
"bottom == top\n")
570 }
else if (far <= near) {
571 INFO_ERR(
"far <= near\n")
572 }
else if (near <= 0.0f) {
573 INFO_ERR(
"near <= 0.0f\n")
574 }
else if (far <= 0.0f) {
575 INFO_ERR(
"far <= 0.0f\n")
578 float width = right - left;
579 float height = top - bottom;
580 float depth = far - near;
581 float x = (2.0 * near) / width;
582 float y = (2.0 * near) / height;
583 float A = (right + left) / width;
584 float B = (top + bottom) / height;
585 float C = - (far + near) / depth;
586 float D = - (2.0 * far * near) / depth;
630 float m00 = matrix.m00, m10 = matrix.m10, m20 = matrix.m20, m30 = matrix.m30;
631 float m01 = matrix.m01, m11 = matrix.m11, m21 = matrix.m21, m31 = matrix.m31;
632 float m02 = matrix.m02, m12 = matrix.m12, m22 = matrix.m22, m32 = matrix.m32;
638 float c00 = m11 * m22 - m12 * m21, c10 = -(m01 * m22 - m02 * m21), c20 = m01 * m12 - m02 * m11;
639 float c01 = -(m10 * m22 - m12 * m20), c11 = m00 * m22 - m02 * m20, c21 = -(m00 * m12 - m02 * m10);
640 float c02 = m10 * m21 - m11 * m20, c12 = -(m00 * m21 - m01 * m20), c22 = m00 * m11 - m01 * m10;
645 float det = m00 * c00 + m10 * c10 + m20 * c20;
646 if (fabsf(det) < 0.00001) {
647 return m4_identity();
652 float i00 = c00 / det, i10 = c01 / det, i20 = c02 / det;
653 float i01 = c10 / det, i11 = c11 / det, i21 = c12 / det;
654 float i02 = c20 / det, i12 = c21 / det, i22 = c22 / det;
658 i00, i10, i20, -(i00 * m30 + i10 * m31 + i20 * m32),
659 i01, i11, i21, -(i01 * m30 + i11 * m31 + i21 * m32),
660 i02, i12, i22, -(i02 * m30 + i12 * m31 + i22 * m32),
675 matrix.m00 * position.x + matrix.m10 * position.y + matrix.m20 * position.z + matrix.m30,
676 matrix.m01 * position.x + matrix.m11 * position.y + matrix.m21 * position.z + matrix.m31,
677 matrix.m02 * position.x + matrix.m12 * position.y + matrix.m22 * position.z + matrix.m32
680 float w = matrix.m03 * position.x + matrix.m13 * position.y + matrix.m23 * position.z + matrix.m33;
681 if (w != 0 && w != 1) {
682 return vec3(result.x / w, result.y / w, result.z / w);
702 matrix.m00 * direction.x + matrix.m10 * direction.y + matrix.m20 * direction.z,
703 matrix.m01 * direction.x + matrix.m11 * direction.y + matrix.m21 * direction.z,
704 matrix.m02 * direction.x + matrix.m12 * direction.y + matrix.m22 * direction.z
707 float w = matrix.m03 * direction.x + matrix.m13 * direction.y + matrix.m23 * direction.z;
708 if (w != 0 && w != 1) {
709 return vec3(result.x / w, result.y / w, result.z / w);
715 void m4_print(
mat4_t matrix)
717 m4_fprintp(STD_OUT, matrix, 6, 2);
720 void m4_printp(
mat4_t matrix,
int width,
int precision)
722 m4_fprintp(STD_OUT, matrix, width, precision);
725 void m4_fprint(FILE* stream,
mat4_t matrix)
727 m4_fprintp(stream, matrix, 6, 2);
730 void m4_fprintp(FILE* stream,
mat4_t matrix,
int width,
int precision)
733 int w = width, p = precision, r;
735 for (r = 0; r < 4; r++) {
736 fprintf(stream,
"| %*.*f %*.*f %*.*f %*.*f |\n",
737 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 void m4_print2(
mat4_t matrix,
const char *line_start)
745 m4_fprintp2(STD_OUT, matrix, 6, 2, line_start);
748 void m4_printp2(
mat4_t matrix,
int width,
int precision,
const char *line_start)
750 m4_fprintp2(STD_OUT, matrix, width, precision, line_start);
753 void m4_fprint2(FILE* stream,
mat4_t matrix,
const char *line_start)
755 m4_fprintp2(stream, matrix, 6, 2, line_start);
757 void m4_fprintp2(FILE* stream,
mat4_t matrix,
int width,
int precision,
const char *line_start)
760 int w = width, p = precision, r;
762 for (r = 0; r < 4; r++) {
763 fprintf(stream,
"%s| %*.*f %*.*f %*.*f %*.*f |\n",
764 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]
769 #endif // MATH_3D_IMPLEMENTATION