]> Dogcows Code - chaz/rasterize/blob - mat.h
add opengl support
[chaz/rasterize] / mat.h
1
2 /*
3 * CS5600 University of Utah
4 * Charles McGarvey
5 * mcgarvey@eng.utah.edu
6 */
7
8 #ifndef _MAT_H_
9 #define _MAT_H_
10
11 #include "common.h"
12 #include "vec.h"
13
14
15 /*
16 * A simple matrix class with column-major storage and notation.
17 */
18 struct mat
19 {
20 vec_t v[4];
21 };
22 typedef struct mat mat_t;
23
24 /*
25 * Initialize a matrix with individual components, row by row.
26 */
27 INLINE_MAYBE
28 void mat_init(mat_t* m, scal_t m11, scal_t m12, scal_t m13, scal_t m14,
29 scal_t m21, scal_t m22, scal_t m23, scal_t m24,
30 scal_t m31, scal_t m32, scal_t m33, scal_t m34,
31 scal_t m41, scal_t m42, scal_t m43, scal_t m44)
32 {
33 m->v[0] = vec_new2(m11, m21, m31, m41);
34 m->v[1] = vec_new2(m12, m22, m32, m42);
35 m->v[2] = vec_new2(m13, m23, m33, m43);
36 m->v[3] = vec_new2(m14, m24, m34, m44);
37 }
38
39
40 /*
41 * Create a new matrix with individual components, row by row.
42 */
43 INLINE_MAYBE
44 mat_t mat_new(scal_t m11, scal_t m12, scal_t m13, scal_t m14,
45 scal_t m21, scal_t m22, scal_t m23, scal_t m24,
46 scal_t m31, scal_t m32, scal_t m33, scal_t m34,
47 scal_t m41, scal_t m42, scal_t m43, scal_t m44)
48 {
49 mat_t m;
50 mat_init(&m, m11, m12, m13, m14,
51 m21, m22, m23, m24,
52 m31, m32, m33, m34,
53 m41, m42, m43, m44);
54 return m;
55 }
56
57 /*
58 * Create a new matrix with four column vectors.
59 */
60 INLINE_MAYBE
61 mat_t mat_new2(vec_t a, vec_t b, vec_t c, vec_t d)
62 {
63 mat_t m;
64 m.v[0] = a;
65 m.v[1] = b;
66 m.v[2] = c;
67 m.v[3] = d;
68 return m;
69 }
70
71 #define MAT_IDENTITY mat_new(S(1.0), S(0.0), S(0.0), S(0.0), \
72 S(0.0), S(1.0), S(0.0), S(0.0), \
73 S(0.0), S(0.0), S(1.0), S(0.0), \
74 S(0.0), S(0.0), S(0.0), S(1.0))
75
76
77 /*
78 * Get a pointer to the matrix data.
79 */
80 INLINE_MAYBE
81 const scal_t* mat_data(const mat_t* m)
82 {
83 return &m->v[0].x;
84 }
85
86
87 /*
88 * Get a column vector (can also access the vector array directly).
89 */
90 INLINE_MAYBE
91 vec_t mat_col(mat_t m, int i)
92 {
93 return m.v[i];
94 }
95
96 /*
97 * Get a row vector.
98 */
99 INLINE_MAYBE
100 vec_t mat_row(mat_t m, int i)
101 {
102 switch (i) {
103 case 0:
104 return vec_new2(m.v[0].x, m.v[1].x, m.v[2].x, m.v[3].x);
105 case 1:
106 return vec_new2(m.v[0].y, m.v[1].y, m.v[2].y, m.v[3].y);
107 case 2:
108 return vec_new2(m.v[0].z, m.v[1].z, m.v[2].z, m.v[3].z);
109 case 3:
110 return vec_new2(m.v[0].w, m.v[1].w, m.v[2].w, m.v[3].w);
111 }
112 }
113
114
115 /*
116 * Print the matrix to stdout.
117 */
118 INLINE_MAYBE
119 void mat_print(mat_t m)
120 {
121 printf("|");
122 vec_print(mat_row(m, 0));
123 printf("|\n|");
124 vec_print(mat_row(m, 1));
125 printf("|\n|");
126 vec_print(mat_row(m, 2));
127 printf("|\n|");
128 vec_print(mat_row(m, 3));
129 printf("|");
130 }
131
132
133 /*
134 * Multiply two matrices together.
135 */
136 INLINE_MAYBE
137 mat_t mat_mult(mat_t a, mat_t b)
138 {
139 #define _DOT(I,J) vec_dot2(mat_row(a,I), mat_col(b,J))
140 return mat_new(_DOT(0,0), _DOT(0,1), _DOT(0,2), _DOT(0,3),
141 _DOT(1,0), _DOT(1,1), _DOT(1,2), _DOT(1,3),
142 _DOT(2,0), _DOT(2,1), _DOT(2,2), _DOT(2,3),
143 _DOT(3,0), _DOT(3,1), _DOT(3,2), _DOT(3,3));
144 #undef _DOT
145 }
146
147 /*
148 * Transform a vector using a matrix.
149 */
150 INLINE_MAYBE
151 vec_t mat_apply(mat_t m, vec_t v)
152 {
153 return vec_new2(vec_dot2(v,mat_row(m,0)),
154 vec_dot2(v,mat_row(m,1)),
155 vec_dot2(v,mat_row(m,2)),
156 vec_dot2(v,mat_row(m,3)));
157 }
158
159
160 /*
161 * Create a new translate matrix.
162 */
163 INLINE_MAYBE
164 mat_t MAT_TRANSLATE(scal_t x, scal_t y, scal_t z)
165 {
166 return mat_new(S(1.0), S(0.0), S(0.0), x,
167 S(0.0), S(1.0), S(0.0), y,
168 S(0.0), S(0.0), S(1.0), z,
169 S(0.0), S(0.0), S(0.0), S(1.0));
170 }
171
172 /*
173 * Create a new translate matrix from a vector.
174 */
175 INLINE_MAYBE
176 mat_t MAT_TRANSLATE2(vec_t v)
177 {
178 return MAT_TRANSLATE(v.x, v.y, v.z);
179 }
180
181 /*
182 * Create a new scale matrix.
183 */
184 INLINE_MAYBE
185 mat_t MAT_SCALE(scal_t x, scal_t y, scal_t z)
186 {
187 return mat_new(x, S(0.0), S(0.0), S(0.0),
188 S(0.0), y, S(0.0), S(0.0),
189 S(0.0), S(0.0), z, S(0.0),
190 S(0.0), S(0.0), S(0.0), S(1.0));
191 }
192
193 /*
194 * Create a new scale matrix from a vector.
195 */
196 INLINE_MAYBE
197 mat_t MAT_SCALE2(vec_t v)
198 {
199 return MAT_SCALE(v.x, v.y, v.z);
200 }
201
202 /*
203 * Create a rotation matrix (around the X axis).
204 */
205 INLINE_MAYBE
206 mat_t MAT_ROTATE_X(scal_t theta)
207 {
208 scal_t sin_a = scal_sin(theta);
209 scal_t cos_a = scal_cos(theta);
210 return mat_new(S(1.0), S(0.0), S(0.0), S(0.0),
211 S(0.0), cos_a, -sin_a, S(0.0),
212 S(0.0), sin_a, cos_a, S(0.0),
213 S(0.0), S(0.0), S(0.0), S(1.0));
214 }
215
216 /*
217 * Create a rotation matrix (around the Y axis).
218 */
219 INLINE_MAYBE
220 mat_t MAT_ROTATE_Y(scal_t theta)
221 {
222 scal_t sin_a = scal_sin(theta);
223 scal_t cos_a = scal_cos(theta);
224 return mat_new(cos_a, S(0.0), sin_a, S(0.0),
225 S(0.0), S(1.0), S(0.0), S(0.0),
226 -sin_a, S(0.0), cos_a, S(0.0),
227 S(0.0), S(0.0), S(0.0), S(1.0));
228 }
229
230 /*
231 * Create a rotation matrix (around the Z axis).
232 */
233 INLINE_MAYBE
234 mat_t MAT_ROTATE_Z(scal_t theta)
235 {
236 scal_t sin_a = scal_sin(theta);
237 scal_t cos_a = scal_cos(theta);
238 return mat_new(cos_a, -sin_a, S(0.0), S(0.0),
239 sin_a, cos_a, S(0.0), S(0.0),
240 S(0.0), S(0.0), S(1.0), S(0.0),
241 S(0.0), S(0.0), S(0.0), S(1.0));
242 }
243
244 /*
245 * Create a rotation matrix (around an arbitrary axis).
246 */
247 INLINE_MAYBE
248 mat_t MAT_ROTATE(scal_t theta, scal_t x, scal_t y, scal_t z)
249 {
250 vec_t v = vec_normalize(vec_new(x, y, z));
251 x = v.x;
252 y = v.y;
253 z = v.z;
254 scal_t c = scal_cos(-theta);
255 scal_t s = scal_sin(-theta);
256 scal_t t = S(1.0) - c;
257 return mat_new(t * x * x + c, t * x * y + s * z, t * x * z - s * y, S(0.0),
258 t * x * y - s * z, t * y * y + c, t * y * z + s * x, S(0.0),
259 t * x * z + s * y, t * y * z - s * x, t * z * z + c, S(0.0),
260 S(0.0), S(0.0), S(0.0), S(1.0));
261 }
262
263 /*
264 * Create a view matrix based on eye, spot, and an up vector.
265 */
266 INLINE_MAYBE
267 mat_t MAT_LOOKAT(vec_t eye, vec_t spot, vec_t up)
268 {
269 vec_t f = vec_normalize(vec_sub(spot, eye));
270 vec_t s = vec_normalize(vec_cross(f, up));
271 vec_t u = vec_cross(s, f);
272 return mat_mult(mat_new(s.x, s.y, s.z, S(0.0),
273 u.x, u.y, u.z, S(0.0),
274 -f.x, -f.y, -f.z, S(0.0),
275 S(0.0), S(0.0), S(0.0), S(1.0)), MAT_TRANSLATE2(vec_neg(eye)));
276 }
277
278 /*
279 * Create a 3D orthogonal projection matrix.
280 */
281 INLINE_MAYBE
282 mat_t MAT_ORTHO(scal_t left, scal_t right,
283 scal_t bottom, scal_t top,
284 scal_t near, scal_t far)
285 {
286 scal_t rml = right - left;
287 scal_t rpl = right + left;
288 scal_t tmb = top - bottom;
289 scal_t tpb = top + bottom;
290 scal_t fmn = far - near;
291 scal_t fpn = far + near;
292 return mat_new(S(2.0)/rml, S(0.0), S(0.0), -rpl / rml,
293 S(0.0), S(2.0)/tmb, S(0.0), -tpb / tmb,
294 S(0.0), S(0.0), S(-2.0)/fmn, -fpn / fmn,
295 S(0.0), S(0.0), S(0.0), S(1.0));
296 }
297
298 /*
299 * Create a frustum-based projection matrix.
300 */
301 INLINE_MAYBE
302 mat_t MAT_FRUSTUM(scal_t left, scal_t right,
303 scal_t bottom, scal_t top,
304 scal_t near, scal_t far)
305 {
306 scal_t rml = right - left;
307 scal_t rpl = right + left;
308 scal_t tmb = top - bottom;
309 scal_t tpb = top + bottom;
310 scal_t fmn = far - near;
311 scal_t fpn = far + near;
312 scal_t n2 = near * S(2.0);
313 return mat_new(n2/rml, S(0.0), rpl/rml, S(0.0),
314 S(0.0), n2/tmb, tpb/tmb, S(0.0),
315 S(0.0), S(0.0), -fpn/fmn, -n2*far/fmn,
316 S(0.0), S(0.0), S(-1.0), S(0.0));
317 }
318
319 /*
320 * Create a perspective projection matrix.
321 */
322 INLINE_MAYBE
323 mat_t MAT_PERSPECTIVE(scal_t fovy, scal_t aspect, scal_t near, scal_t far)
324 {
325 scal_t top = near * scal_tan(fovy * S(0.5));
326 scal_t bottom = -top;
327 scal_t left = bottom * aspect;
328 scal_t right = top * aspect;
329 return MAT_FRUSTUM(left, right, bottom, top, near, far);
330 }
331
332 /*
333 * Create a viewport matrix.
334 */
335 INLINE_MAYBE
336 mat_t MAT_VIEWPORT(int x, int y, int w, int h)
337 {
338 scal_t xs = (scal_t)x;
339 scal_t ys = (scal_t)y;
340 scal_t ws = (scal_t)w * S(0.5);
341 scal_t hs = (scal_t)h * S(0.5);
342 return mat_new(ws, S(0.0), S(0.0), ws+xs,
343 S(0.0), hs, S(0.0), hs+ys,
344 S(0.0), S(0.0), S(1.0), S(0.0),
345 S(0.0), S(0.0), S(0.0), S(1.0));
346 }
347
348
349 #endif // _MAT_H_
350
This page took 0.044137 seconds and 4 git commands to generate.