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