KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
matrix.h
Go to the documentation of this file.
1/* KallistiOS ##version##
2
3 dc/matrix.h
4 Copyright (C) 2000 Megan Potter
5 Copyright (C) 2013, 2014 Josh "PH3NOM" Pearson
6 Copyright (C) 2018 Lawrence Sebald
7
8*/
9
10/** \file dc/matrix.h
11 \brief Basic matrix operations.
12 \ingroup math_matrices
13
14 This file contains various basic matrix math functionality for using the
15 SH4's matrix transformation unit. Higher level functionality, like the 3D
16 functionality is built off of these operations.
17
18 \see dc/matrix3d.h
19
20 \author Megan Potter
21 \author Josh "PH3NOM" Pearson
22*/
23
24#ifndef __DC_MATRIX_H
25#define __DC_MATRIX_H
26
27#include <sys/cdefs.h>
28__BEGIN_DECLS
29
30#include <dc/vector.h>
31
32/** \defgroup math_matrices Matrices
33 \brief SH4-optimized matrix and linear algebra routines
34 \ingroup math
35 @{
36*/
37
38/** \brief Copy the internal matrix to a memory one.
39
40 This function stores the current internal matrix to one in memory.
41
42 \warning
43 \p out MUST be at least 8-byte aligned!
44
45 \note
46 For best performance, 32-byte alignment of \p out is recommended.
47
48 \param out A pointer to where to store the matrix (must be at
49 least 8-byte aligned, should be 32-byte aligned).
50*/
52
53/** \brief Copy a memory matrix into the internal one.
54
55 This function loads the internal matrix with the values of one in memory.
56
57 \warning
58 \p out MUST be at least 8-byte aligned!
59
60 \note
61 For best performance, 32-byte alignment of \p out is recommended.
62
63 \param src A pointer to where to load the matrix from (must be
64 at least 8-byte aligned, should be 32-byte aligned).
65*/
66void mat_load(const matrix_t *src);
67
68/** \brief Clear the internal matrix to identity.
69
70 This function clears the internal matrix to a standard identity matrix.
71*/
72void mat_identity(void);
73
74/** \brief Apply a matrix.
75
76 This function multiplies a matrix in memory onto the internal matrix.
77
78 \warning
79 \p src MUST be at least 8-byte aligned!
80
81 \note
82 For best performance, 32-byte alignment of \p src is recommended.
83
84 \param src A pointer to the matrix to multiply.
85*/
86void mat_apply(const matrix_t *src);
87
88/** \brief Multiply a matrix.
89
90 This function multiplies a matrix in memory with the internal matrix
91 and stores the result into a new matrix.
92
93 \warning
94 \p src and dst MUST be at least 8-byte aligned!
95
96 \note
97 For best performance, 32-byte alignment of \p src and \p dst is recommended.
98
99 \param dst A pointer to the destination matrix.
100 \param src A pointer to the matrix to multiply.
101*/
102void mat_multiply(matrix_t *dst, const matrix_t *src);
103
104/** \brief Transform vectors by the internal matrix.
105
106 This function transforms zero or more sets of vectors by the current
107 internal matrix. Each vector is 3 single-precision floats long.
108
109 \param invecs The list of input vectors.
110 \param outvecs The list of output vectors.
111 \param veccnt How many vectors are in the list.
112 \param stride Number of bytes between vectors.
113*/
114void mat_transform(const vector_t *invecs, vector_t *outvecs,
115 int veccnt, int stride);
116
117/** \brief Transform vectors by the internal matrix into the store queues.
118
119 This function transforms one or more sets of vertices using the current
120 internal matrix directly into the store queues. Each vertex is exactly
121 32-bytes long, and the non-xyz data that is with it will be copied over with
122 the transformed coordinates. This is perfect, for instance, for transforming
123 pvr_vertex_t vertices.
124
125 \note sq_lock() must have been called beforehand
126
127 \param input The list of input vertices.
128 \param output The output pointer (SQ address)
129 \param veccnt The number of vertices to transform.
130
131 \author Jim Ursetto
132*/
133void mat_transform_sq(void *input, void *output, int veccnt);
134
135/** \brief Macro to transform a single vertex by the internal matrix.
136
137 This macro is an inline assembly operation to transform a single vertex. It
138 works most efficiently if the x value is in fr0, y is in fr1, and z is in
139 fr2 before using the macro.
140
141 \param x The X coordinate to transform.
142 \param y The Y coordinate to transform.
143 \param z The Z coordinate to transform.
144*/
145#define mat_trans_single(x, y, z) { \
146 register float __x __asm__("fr0") = (x); \
147 register float __y __asm__("fr1") = (y); \
148 register float __z __asm__("fr2") = (z); \
149 __asm__ __volatile__( \
150 "fldi1 fr3\n" \
151 "ftrv xmtrx,fv0\n" \
152 "fldi1 fr2\n" \
153 "fdiv fr3,fr2\n" \
154 "fmul fr2,fr0\n" \
155 "fmul fr2,fr1\n" \
156 : "=f" (__x), "=f" (__y), "=f" (__z) \
157 : "0" (__x), "1" (__y), "2" (__z) \
158 : "fr3" ); \
159 x = __x; y = __y; z = __z; \
160 }
161
162/** \brief Macro to transform a single vertex by the internal matrix.
163
164 This macro is an inline assembly operation to transform a single vertex. It
165 works most efficiently if the x value is in fr0, y is in fr1, z is in
166 fr2, and w is in fr3 before using the macro. This macro is similar to
167 \ref mat_trans_single(), but this one allows an input to and preserves the
168 Z/W value.
169
170 \param x The X coordinate to transform.
171 \param y The Y coordinate to transform.
172 \param z The Z coordinate to transform.
173 \param w The W coordinate to transform.
174*/
175#define mat_trans_single4(x, y, z, w) { \
176 register float __x __asm__("fr0") = (x); \
177 register float __y __asm__("fr1") = (y); \
178 register float __z __asm__("fr2") = (z); \
179 register float __w __asm__("fr3") = (w); \
180 __asm__ __volatile__( \
181 "ftrv xmtrx,fv0\n" \
182 "fdiv fr3,fr0\n" \
183 "fdiv fr3,fr1\n" \
184 "fdiv fr3,fr2\n" \
185 "fldi1 fr4\n" \
186 "fdiv fr3,fr4\n" \
187 "fmov fr4,fr3\n" \
188 : "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w) \
189 : "0" (__x), "1" (__y), "2" (__z), "3" (__w) \
190 : "fr4" ); \
191 x = __x; y = __y; z = __z; w = __w; \
192 }
193
194/** \brief Macro to transform a single vertex by the internal matrix.
195
196 This macro is an inline assembly operation to transform a single vertex. It
197 works most efficiently if the x value is in fr0, y is in fr1, and z is in
198 fr2 before using the macro. This macro is similar to
199 \ref mat_trans_single(), but this one leaves z/w instead of 1/w for the z
200 component.
201
202 \param x The X coordinate to transform.
203 \param y The Y coordinate to transform.
204 \param z The Z coordinate to transform.
205*/
206#define mat_trans_single3(x, y, z) { \
207 register float __x __asm__("fr0") = (x); \
208 register float __y __asm__("fr1") = (y); \
209 register float __z __asm__("fr2") = (z); \
210 __asm__ __volatile__( \
211 "fldi1 fr3\n" \
212 "ftrv xmtrx,fv0\n" \
213 "fdiv fr3,fr0\n" \
214 "fdiv fr3,fr1\n" \
215 "fdiv fr3,fr2\n" \
216 : "=f" (__x), "=f" (__y), "=f" (__z) \
217 : "0" (__x), "1" (__y), "2" (__z) \
218 : "fr3" ); \
219 x = __x; y = __y; z = __z; \
220 }
221
222/** \brief Macro to transform a single vertex by the internal matrix with no
223 perspective division.
224
225 This macro is an inline assembly operation to transform a single vertex. It
226 works most efficiently if the x value is in fr0, y is in fr1, z is in
227 fr2, and w is in fr3 before using the macro. This macro is similar to
228 \ref mat_trans_single(), but this one does not do any perspective division.
229
230 \param x The X coordinate to transform.
231 \param y The Y coordinate to transform.
232 \param z The Z coordinate to transform.
233 \param w The W coordinate to transform.
234*/
235#define mat_trans_nodiv(x, y, z, w) { \
236 register float __x __asm__("fr0") = (x); \
237 register float __y __asm__("fr1") = (y); \
238 register float __z __asm__("fr2") = (z); \
239 register float __w __asm__("fr3") = (w); \
240 __asm__ __volatile__( \
241 "ftrv xmtrx,fv0\n" \
242 : "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w) \
243 : "0" (__x), "1" (__y), "2" (__z), "3" (__w) ); \
244 x = __x; y = __y; z = __z; w = __w; \
245 }
246
247/** \brief Macro to transform a single 3d vertex coordinate by the internal
248 matrix with no perspective division.
249
250 This macro is an inline assembly operation to transform a 3 float vertex
251 coordinate. It works most efficiently if the x value is in fr12, y is in
252 fr13, and z is in fr14 before using the macro. This macro is similar to
253 \ref mat_trans_nodiv(), but this one sets the W component to 1 for use with
254 a 3d vector.
255
256 \param x The X coordinate to transform.
257 \param y The Y coordinate to transform.
258 \param z The Z coordinate to transform.
259*/
260#define mat_trans_single3_nodiv(x, y, z) { \
261 register float __x __asm__("fr12") = (x); \
262 register float __y __asm__("fr13") = (y); \
263 register float __z __asm__("fr14") = (z); \
264 __asm__ __volatile__( \
265 "fldi1 fr15\n" \
266 "ftrv xmtrx, fv12\n" \
267 : "=f" (__x), "=f" (__y), "=f" (__z) \
268 : "0" (__x), "1" (__y), "2" (__z) \
269 : "fr15" ); \
270 x = __x; y = __y; z = __z; \
271 }
272
273/** \brief Macro to transform a single 3d vertex coordinate by the internal
274 matrix with perspective division.
275
276 This macro is an inline assembly operation to transform a 3 float vertex
277 coordinate. It works most efficiently if the x value is in fr12, y is in
278 fr13, and z is in fr14 before using the macro. This macro is similar to
279 \ref mat_trans_single(), but this one does not modify the input operands,
280 instead storing the transformed vector to the output operands.
281
282 \param x The X coordinate to input transform.
283 \param y The Y coordinate to input transform.
284 \param z The Z coordinate to input transform.
285 \param x2 The X coordinate to output transform.
286 \param y2 The Y coordinate to output transform.
287 \param z2 The Z coordinate to output transform.
288*/
289#define mat_trans_single3_nomod(x, y, z, x2, y2, z2) { \
290 register float __x __asm__("fr12") = (x); \
291 register float __y __asm__("fr13") = (y); \
292 register float __z __asm__("fr14") = (z); \
293 __asm__ __volatile__( \
294 "fldi1 fr15\n" \
295 "ftrv xmtrx, fv12\n" \
296 "fldi1 fr14\n" \
297 "fdiv fr15, fr14\n" \
298 "fmul fr14, fr12\n" \
299 "fmul fr14, fr13\n" \
300 : "=f" (__x), "=f" (__y), "=f" (__z) \
301 : "0" (__x), "1" (__y), "2" (__z) \
302 : "fr15" ); \
303 x2 = __x; y2 = __y; z2 = __z; \
304 }
305
306/** \brief Macro to transform a single 3d vertex coordinate by the internal
307 matrix.
308
309 This macro is an inline assembly operation to transform a 3 float vertex
310 coordinate. It works most efficiently if the x value is in fr12, y is in
311 fr13, and z is in fr14 before using the macro. This macro is similar to
312 \ref mat_trans_single3_nodiv(), but this one does not modify the input
313 operands, instead storing the transformed vector to the output operands.
314
315 \param x The X coordinate to input transform.
316 \param y The Y coordinate to input transform.
317 \param z The Z coordinate to input transform.
318 \param x2 The X coordinate to output transform.
319 \param y2 The Y coordinate to output transform.
320 \param z2 The Z coordinate to output transform.
321*/
322#define mat_trans_single3_nodiv_nomod(x, y, z, x2, y2, z2) { \
323 register float __x __asm__("fr12") = (x); \
324 register float __y __asm__("fr13") = (y); \
325 register float __z __asm__("fr14") = (z); \
326 __asm__ __volatile__( \
327 "fldi1 fr15\n" \
328 "ftrv xmtrx, fv12\n" \
329 : "=f" (__x), "=f" (__y), "=f" (__z) \
330 : "0" (__x), "1" (__y), "2" (__z) \
331 : "fr15" ); \
332 x2 = __x; y2 = __y; z2 = __z; \
333 }
334
335/** \brief Macro to transform a single 3d vertex coordinate by the internal
336 matrix.
337
338 This macro is an inline assembly operation to transform a 3 float vertex
339 coordinate. It works most efficiently if the x value is in fr12, y is in
340 fr13, and z is in fr14 before using the macro. This macro is similar to
341 \ref mat_trans_single3_nodiv(), but this one stores the W component of
342 transform for later perspective divide.
343
344 \param x The X coordinate to transform.
345 \param y The Y coordinate to transform.
346 \param z The Z coordinate to transform.
347 \param w The W coordinate output of transform.
348*/
349#define mat_trans_single3_nodivw(x, y, z, w) { \
350 register float __x __asm__("fr12") = (x); \
351 register float __y __asm__("fr13") = (y); \
352 register float __z __asm__("fr14") = (z); \
353 register float __w __asm__("fr15") = 1.0f; \
354 __asm__ __volatile__( \
355 "ftrv xmtrx, fv12\n" \
356 : "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w) \
357 : "0" (__x), "1" (__y), "2" (__z), "3" (__w) ); \
358 x = __x; y = __y; z = __z; w = __w; \
359 }
360
361/** \brief Macro to transform a single 3d vertex coordinate by the internal
362 matrix both with and without perspective division.
363
364 This macro is an inline assembly operation to transform a 3 float vertex
365 coordinate. It works most efficiently if the x value is in fr0, y is in fr1,
366 and z is in fr2 before using the macro. This macro is similar to
367 \ref mat_trans_single(), but this one is used for transforming input vertex
368 with and without perspective division.
369
370 \param x The X coordinate to transform without perspective
371 divide.
372 \param y The Y coordinate to transform without perspective
373 divide.
374 \param z The Z coordinate to transform without perspective
375 divide.
376 \param xd The X coordinate to output transform with
377 perspective divide.
378 \param yd The Y coordinate to output transform with
379 perspective divide.
380 \param zd The Z coordinate to output transform with
381 perspective divide.
382*/
383#define mat_trans_single3_nodiv_div(x, y, z, xd, yd, zd) { \
384 register float __x __asm__("fr0") = (x); \
385 register float __y __asm__("fr1") = (y); \
386 register float __z __asm__("fr2") = (z); \
387 register float __xd __asm__("fr4"); \
388 register float __yd __asm__("fr5"); \
389 register float __zd __asm__("fr6"); \
390 __asm__ __volatile__( \
391 "fldi1 fr3\n" \
392 "ftrv xmtrx, fv0\n" \
393 "fmov fr0, fr4\n" \
394 "fmov fr1, fr5\n" \
395 "fmov fr3, fr7\n" \
396 "fldi1 fr6\n" \
397 "fdiv fr7, fr6\n" \
398 "fmul fr6, fr4\n" \
399 "fmul fr6, fr5\n" \
400 : "=f" (__x), "=f" (__y), "=f" (__z), \
401 "=f" (__xd), "=f" (__yd), "=f" (__zd) \
402 : "0" (__x), "1" (__y), "2" (__z) \
403 : "fr3" ); \
404 x = __x; y = __y; z = __z; xd = __xd; yd = __yd; zd = __zd; \
405 }
406
407/** \brief Macro to transform a single vertex normal by the internal matrix.
408
409 This macro is an inline assembly operation to transform a 3 float vertex
410 normal. It works most efficiently if the x value is in fr8, y is in fr9,
411 and z is in fr10 before using the macro. This macro is similar to
412 \ref mat_trans_nodiv(), but this one sets the W component to 0 in order to
413 transform a vertex normal, rather than 1 for a vertex position.
414
415 \param x The X normal to transform.
416 \param y The Y normal to transform.
417 \param z The Z normal to transform.
418*/
419#define mat_trans_normal3(x, y, z) { \
420 register float __x __asm__("fr8") = (x); \
421 register float __y __asm__("fr9") = (y); \
422 register float __z __asm__("fr10") = (z); \
423 __asm__ __volatile__( \
424 "fldi0 fr11\n" \
425 "ftrv xmtrx, fv8\n" \
426 : "=f" (__x), "=f" (__y), "=f" (__z) \
427 : "0" (__x), "1" (__y), "2" (__z) \
428 : "fr11" ); \
429 x = __x; y = __y; z = __z; \
430 }
431
432/** \brief Macro to transform a single vertex normal by the internal matrix.
433
434 This macro is an inline assembly operation to transform a 3 float vertex
435 normal. It works most efficiently if the x value is in fr8, y is in fr9,
436 and z is in fr10 before using the macro. This macro is similar to
437 \ref mat_trans_normal3(), but this one does not modify the input operands,
438 instead storing the transformed vector to the output operands.
439
440 \param x The X normal to input transform.
441 \param y The Y normal to input transform.
442 \param z The Z normal to input transform.
443 \param x2 The X normal to output transform.
444 \param y2 The Y normal to output transform.
445 \param z2 The Z normal to output transform.
446*/
447#define mat_trans_normal3_nomod(x, y, z, x2, y2, z2) { \
448 register float __x __asm__("fr8") = (x); \
449 register float __y __asm__("fr9") = (y); \
450 register float __z __asm__("fr10") = (z); \
451 __asm__ __volatile__( \
452 "fldi0 fr11\n" \
453 "ftrv xmtrx, fv8\n" \
454 : "=f" (__x), "=f" (__y), "=f" (__z) \
455 : "0" (__x), "1" (__y), "2" (__z) \
456 : "fr11" ); \
457 x2 = __x; y2 = __y; z2 = __z; \
458 }
459
460/** @} */
461
462__END_DECLS
463
464#endif /* !__DC_MATRIX_H */
void mat_transform_sq(void *input, void *output, int veccnt)
Transform vectors by the internal matrix into the store queues.
void mat_identity(void)
Clear the internal matrix to identity.
void mat_apply(const matrix_t *src)
Apply a matrix.
void mat_multiply(matrix_t *dst, const matrix_t *src)
Multiply a matrix.
void mat_load(const matrix_t *src)
Copy a memory matrix into the internal one.
void mat_transform(const vector_t *invecs, vector_t *outvecs, int veccnt, int stride)
Transform vectors by the internal matrix.
float matrix_t[4][4]
Basic 4x4 matrix type.
Definition vector.h:37
void mat_store(matrix_t *out)
Copy the internal matrix to a memory one.
Primitive matrix, vector, and point types.
4-part vector type.
Definition vector.h:42