X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Frasterize;a=blobdiff_plain;f=mat.h;h=c188723346fce7faeec94210a2eca2d9a61fa042;hp=f6d4c1b119f8042e8370e8695f4fb34861f4a8cc;hb=09dd89d10e65029f0be313dd463ba1f43cac2fbb;hpb=0f2508a4f227523a6b7e54798487af19d06a6ce9 diff --git a/mat.h b/mat.h index f6d4c1b..c188723 100644 --- a/mat.h +++ b/mat.h @@ -5,8 +5,8 @@ * mcgarvey@eng.utah.edu */ -#ifndef __MAT_H__ -#define __MAT_H__ +#ifndef _MAT_H_ +#define _MAT_H_ #include "common.h" #include "vec.h" @@ -24,7 +24,7 @@ typedef struct mat mat_t; /* * Initialize a matrix with individual components, row by row. */ -__fast__ +INLINE_MAYBE void mat_init(mat_t* m, scal_t m11, scal_t m12, scal_t m13, scal_t m14, scal_t m21, scal_t m22, scal_t m23, scal_t m24, scal_t m31, scal_t m32, scal_t m33, scal_t m34, @@ -40,7 +40,7 @@ void mat_init(mat_t* m, scal_t m11, scal_t m12, scal_t m13, scal_t m14, /* * Create a new matrix with individual components, row by row. */ -__fast__ +INLINE_MAYBE mat_t mat_new(scal_t m11, scal_t m12, scal_t m13, scal_t m14, scal_t m21, scal_t m22, scal_t m23, scal_t m24, scal_t m31, scal_t m32, scal_t m33, scal_t m34, @@ -57,7 +57,7 @@ mat_t mat_new(scal_t m11, scal_t m12, scal_t m13, scal_t m14, /* * Create a new matrix with four column vectors. */ -__fast__ +INLINE_MAYBE mat_t mat_new2(vec_t a, vec_t b, vec_t c, vec_t d) { mat_t m; @@ -74,10 +74,83 @@ mat_t mat_new2(vec_t a, vec_t b, vec_t c, vec_t d) S(0.0), S(0.0), S(0.0), S(1.0)) +/* + * Get a column vector (can also access the vector array directly). + */ +INLINE_MAYBE +vec_t mat_col(mat_t m, int i) +{ + return m.v[i]; +} + +/* + * Get a row vector. + */ +INLINE_MAYBE +vec_t mat_row(mat_t m, int i) +{ + switch (i) { + case 0: + return vec_new2(m.v[0].x, m.v[1].x, m.v[2].x, m.v[3].x); + case 1: + return vec_new2(m.v[0].y, m.v[1].y, m.v[2].y, m.v[3].y); + case 2: + return vec_new2(m.v[0].z, m.v[1].z, m.v[2].z, m.v[3].z); + case 3: + return vec_new2(m.v[0].w, m.v[1].w, m.v[2].w, m.v[3].w); + } +} + + +/* + * Print the matrix to stdout. + */ +INLINE_MAYBE +void mat_print(mat_t m) +{ + printf("|"); + vec_print(mat_row(m, 0)); + printf("|\n|"); + vec_print(mat_row(m, 1)); + printf("|\n|"); + vec_print(mat_row(m, 2)); + printf("|\n|"); + vec_print(mat_row(m, 3)); + printf("|"); +} + + +/* + * Multiply two matrices together. + */ +INLINE_MAYBE +mat_t mat_mult(mat_t a, mat_t b) +{ +#define _DOT(I,J) vec_dot2(mat_row(a,I), mat_col(b,J)) + return mat_new(_DOT(0,0), _DOT(0,1), _DOT(0,2), _DOT(0,3), + _DOT(1,0), _DOT(1,1), _DOT(1,2), _DOT(1,3), + _DOT(2,0), _DOT(2,1), _DOT(2,2), _DOT(2,3), + _DOT(3,0), _DOT(3,1), _DOT(3,2), _DOT(3,3)); +#undef _DOT +} + +/* + * Transform a vector using a matrix. + */ +INLINE_MAYBE +vec_t mat_apply(mat_t m, vec_t v) +{ + return vec_new2(vec_dot2(v,mat_row(m,0)), + vec_dot2(v,mat_row(m,1)), + vec_dot2(v,mat_row(m,2)), + vec_dot2(v,mat_row(m,3))); +} + + /* * Create a new translate matrix. */ -__fast__ +INLINE_MAYBE mat_t MAT_TRANSLATE(scal_t x, scal_t y, scal_t z) { return mat_new(S(1.0), S(0.0), S(0.0), x, @@ -86,119 +159,182 @@ mat_t MAT_TRANSLATE(scal_t x, scal_t y, scal_t z) S(0.0), S(0.0), S(0.0), S(1.0)); } +/* + * Create a new translate matrix from a vector. + */ +INLINE_MAYBE +mat_t MAT_TRANSLATE2(vec_t v) +{ + return MAT_TRANSLATE(v.x, v.y, v.z); +} + /* * Create a new scale matrix. */ -__fast__ +INLINE_MAYBE mat_t MAT_SCALE(scal_t x, scal_t y, scal_t z) { - return mat_new( x, S(0.0), S(0.0), S(0.0), - S(0.0), y, S(0.0), S(0.0), - S(0.0), S(0.0), z, S(0.0), - S(0.0), S(0.0), S(0.0), S(1.0)); + return mat_new(x, S(0.0), S(0.0), S(0.0), + S(0.0), y, S(0.0), S(0.0), + S(0.0), S(0.0), z, S(0.0), + S(0.0), S(0.0), S(0.0), S(1.0)); } /* - * Create a rotation matrix (around the Z axis). + * Create a new scale matrix from a vector. + */ +INLINE_MAYBE +mat_t MAT_SCALE2(vec_t v) +{ + return MAT_SCALE(v.x, v.y, v.z); +} + +/* + * Create a rotation matrix (around the X axis). */ -__fast__ -mat_t MAT_ROTATE_Z(scal_t a) +INLINE_MAYBE +mat_t MAT_ROTATE_X(scal_t theta) { - scal_t sin_a = scal_sin(a); - scal_t cos_a = scal_cos(a); - return mat_new( cos_a, -sin_a, S(0.0), S(0.0), - sin_a, cos_a, S(0.0), S(0.0), - S(0.0), S(0.0), S(1.0), S(0.0), + scal_t sin_a = scal_sin(theta); + scal_t cos_a = scal_cos(theta); + return mat_new(S(1.0), S(0.0), S(0.0), S(0.0), + S(0.0), cos_a, -sin_a, S(0.0), + S(0.0), sin_a, cos_a, S(0.0), S(0.0), S(0.0), S(0.0), S(1.0)); } /* - * Create a 2D orthogonal projection matrix. + * Create a rotation matrix (around the Y axis). */ -__fast__ -mat_t MAT_ORTHO(scal_t left, scal_t right, scal_t bottom, scal_t top) +INLINE_MAYBE +mat_t MAT_ROTATE_Y(scal_t theta) { - scal_t rml = right - left; - scal_t rpl = right + left; - scal_t tmb = top - bottom; - scal_t tpb = top + bottom; - return mat_new(S(2.0) / rml, S(0.0), S(0.0), -rpl / rml, - S(0.0), S(2.0) / tmb, S(0.0), -tpb / tmb, - S(0.0), S(0.0), S(-1.0), S(0.0), - S(0.0), S(0.0), S(0.0), S(1.0)); + scal_t sin_a = scal_sin(theta); + scal_t cos_a = scal_cos(theta); + return mat_new(cos_a, S(0.0), sin_a, S(0.0), + S(0.0), S(1.0), S(0.0), S(0.0), + -sin_a, S(0.0), cos_a, S(0.0), + S(0.0), S(0.0), S(0.0), S(1.0)); } /* - * Create a viewport matrix. + * Create a rotation matrix (around the Z axis). */ -__fast__ -mat_t MAT_VIEWPORT(int x, int y, unsigned w, unsigned h) +INLINE_MAYBE +mat_t MAT_ROTATE_Z(scal_t theta) { - scal_t xs = (scal_t)x; - scal_t ys = (scal_t)y; - scal_t ws = (scal_t)w / S(2.0); - scal_t hs = (scal_t)h / S(2.0); - return mat_new( ws, S(0.0), S(0.0), ws + xs, - S(0.0), hs, S(0.0), hs + ys, - S(0.0), S(0.0), S(1.0), S(0.0), - S(0.0), S(0.0), S(0.0), S(1.0)); + scal_t sin_a = scal_sin(theta); + scal_t cos_a = scal_cos(theta); + return mat_new(cos_a, -sin_a, S(0.0), S(0.0), + sin_a, cos_a, S(0.0), S(0.0), + S(0.0), S(0.0), S(1.0), S(0.0), + S(0.0), S(0.0), S(0.0), S(1.0)); } +/* + * Create a rotation matrix (around an arbitrary axis). + */ +INLINE_MAYBE +mat_t MAT_ROTATE(scal_t theta, scal_t x, scal_t y, scal_t z) +{ + vec_t v = vec_normalize(vec_new(x, y, z)); + x = v.x; + y = v.y; + z = v.z; + scal_t c = scal_cos(-theta); + scal_t s = scal_sin(-theta); + scal_t t = S(1.0) - c; + return mat_new(t * x * x + c, t * x * y + s * z, t * x * z - s * y, S(0.0), + t * x * y - s * z, t * y * y + c, t * y * z + s * x, S(0.0), + t * x * z + s * y, t * y * z - s * x, t * z * z + c, S(0.0), + S(0.0), S(0.0), S(0.0), S(1.0)); +} /* - * Get a column vector (can also access the vector array directly). + * Create a view matrix based on eye, spot, and an up vector. */ -__fast__ -vec_t mat_col(mat_t m, int i) +INLINE_MAYBE +mat_t MAT_LOOKAT(vec_t eye, vec_t spot, vec_t up) { - return m.v[i]; + vec_t f = vec_normalize(vec_sub(spot, eye)); + vec_t s = vec_normalize(vec_cross(f, up)); + vec_t u = vec_cross(s, f); + return mat_mult(mat_new(s.x, s.y, s.z, S(0.0), + u.x, u.y, u.z, S(0.0), + -f.x, -f.y, -f.z, S(0.0), + S(0.0), S(0.0), S(0.0), S(1.0)), MAT_TRANSLATE2(vec_neg(eye))); } /* - * Get a row vector. + * Create a 3D orthogonal projection matrix. */ -__fast__ -vec_t mat_row(mat_t m, int i) +INLINE_MAYBE +mat_t MAT_ORTHO(scal_t left, scal_t right, + scal_t bottom, scal_t top, + scal_t near, scal_t far) { - switch (i) { - case 0: - return vec_new2(m.v[0].x, m.v[1].x, m.v[2].x, m.v[3].x); - case 1: - return vec_new2(m.v[0].y, m.v[1].y, m.v[2].y, m.v[3].y); - case 2: - return vec_new2(m.v[0].z, m.v[1].z, m.v[2].z, m.v[3].z); - case 3: - return vec_new2(m.v[0].w, m.v[1].w, m.v[2].w, m.v[3].w); - } + scal_t rml = right - left; + scal_t rpl = right + left; + scal_t tmb = top - bottom; + scal_t tpb = top + bottom; + scal_t fmn = far - near; + scal_t fpn = far + near; + return mat_new(S(2.0)/rml, S(0.0), S(0.0), -rpl / rml, + S(0.0), S(2.0)/tmb, S(0.0), -tpb / tmb, + S(0.0), S(0.0), S(-2.0)/fmn, -fpn / fmn, + S(0.0), S(0.0), S(0.0), S(1.0)); } +/* + * Create a frustum-based projection matrix. + */ +INLINE_MAYBE +mat_t MAT_FRUSTUM(scal_t left, scal_t right, + scal_t bottom, scal_t top, + scal_t near, scal_t far) +{ + scal_t rml = right - left; + scal_t rpl = right + left; + scal_t tmb = top - bottom; + scal_t tpb = top + bottom; + scal_t fmn = far - near; + scal_t fpn = far + near; + scal_t n2 = near * S(2.0); + return mat_new(n2/rml, S(0.0), rpl/rml, S(0.0), + S(0.0), n2/tmb, tpb/tmb, S(0.0), + S(0.0), S(0.0), -fpn/fmn, -n2*far/fmn, + S(0.0), S(0.0), S(-1.0), S(0.0)); +} /* - * Multiply two matrices together. + * Create a perspective projection matrix. */ -__fast__ -mat_t mat_mult(mat_t a, mat_t b) +INLINE_MAYBE +mat_t MAT_PERSPECTIVE(scal_t fovy, scal_t aspect, scal_t near, scal_t far) { -#define _DOT(I,J) vec_dot(mat_row(a,I), mat_col(b,J)) - return mat_new(_DOT(0,0), _DOT(0,1), _DOT(0,2), _DOT(0,3), - _DOT(1,0), _DOT(1,1), _DOT(1,2), _DOT(1,3), - _DOT(2,0), _DOT(2,1), _DOT(2,2), _DOT(2,3), - _DOT(3,0), _DOT(3,1), _DOT(3,2), _DOT(3,3)); -#undef _DOT + scal_t top = near * scal_tan(fovy * S(0.5)); + scal_t bottom = -top; + scal_t left = bottom * aspect; + scal_t right = top * aspect; + return MAT_FRUSTUM(left, right, bottom, top, near, far); } /* - * Transform a vector using a matrix. + * Create a viewport matrix. */ -__fast__ -vec_t mat_apply(mat_t m, vec_t v) +INLINE_MAYBE +mat_t MAT_VIEWPORT(int x, int y, int w, int h) { - return vec_new2(vec_dot(v,mat_row(m,0)), - vec_dot(v,mat_row(m,1)), - vec_dot(v,mat_row(m,2)), - vec_dot(v,mat_row(m,3))); + scal_t xs = (scal_t)x; + scal_t ys = (scal_t)y; + scal_t ws = (scal_t)w * S(0.5); + scal_t hs = (scal_t)h * S(0.5); + return mat_new(ws, S(0.0), S(0.0), ws+xs, + S(0.0), hs, S(0.0), hs+ys, + S(0.0), S(0.0), S(1.0), S(0.0), + S(0.0), S(0.0), S(0.0), S(1.0)); } -#endif // __MAT_H__ +#endif // _MAT_H_