1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - GX -
3   File:     fx_mtx44.c
4 
5   Copyright 2003-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nitro/code32.h>              // Always generate ARM binary for efficiency
19 
20 #include <nitro/fx/fx_mtx44.h>
21 #include <nitro/fx/fx_vec.h>
22 #include <nitro/fx/fx_cp.h>
23 #include <nitro/mi/memory.h>
24 
mul64(fx64 x,fx32 y)25 inline fx32 mul64(fx64 x, fx32 y)
26 {
27     return (fx32)((x * y) >> FX32_SHIFT);
28 }
29 
MTX_Identity44_(register MtxFx44 * pDst)30 asm void MTX_Identity44_(register MtxFx44* pDst)
31 {
32     mov   r2, #4096                    // FX32_ONE
33     mov   r3, #0
34     stmia r0!, {r2,r3}
35     mov   r1, #0
36     stmia r0!, {r1,r3}
37     stmia r0!, {r1,r2,r3}
38     stmia r0!, {r1,r3}
39     stmia r0!, {r1,r2,r3}
40     stmia r0!, {r1,r3}
41     stmia r0!, {r1,r2}
42 
43     bx    lr
44 }
45 
MTX_Copy44To33_(register const MtxFx44 * pSrc,register MtxFx33 * pDst)46 asm void MTX_Copy44To33_(register const MtxFx44* pSrc, register MtxFx33* pDst)
47 {
48     ldmia r0!, {r2-r3, r12}
49     add   r0, r0, #4
50     stmia r1!, {r2-r3, r12}
51 
52     ldmia r0!, {r2-r3, r12}
53     add   r0, r0, #4
54     stmia r1!, {r2-r3, r12}
55 
56     ldmia r0!, {r2-r3, r12}
57     add   r0, r0, #4
58     stmia r1!, {r2-r3, r12}
59 
60     bx    lr
61 }
62 
MTX_Copy44To43_(register const MtxFx44 * pSrc,register MtxFx43 * pDst)63 asm void MTX_Copy44To43_(register const MtxFx44* pSrc, register MtxFx43* pDst)
64 {
65     ldmia r0!, {r2-r3, r12}
66     add   r0, r0, #4
67     stmia r1!, {r2-r3, r12}
68 
69     ldmia r0!, {r2-r3, r12}
70     add   r0, r0, #4
71     stmia r1!, {r2-r3, r12}
72 
73     ldmia r0!, {r2-r3, r12}
74     add   r0, r0, #4
75     stmia r1!, {r2-r3, r12}
76 
77     ldmia r0!, {r2-r3, r12}
78     add   r0, r0, #4
79     stmia r1!, {r2-r3, r12}
80 
81     bx    lr
82 }
83 
84 /*---------------------------------------------------------------------------*
85   Name:         MTX_TransApply44
86 
87   Description:  Calc T(x, y, z) * pSrc = pDst
88 
89   Arguments:    pSrc         a pointer to a 4x4 matrix
90                 pDst         a pointer to a 4x4 matrix
91                 x            x trans factor
92                 y            y trans factor
93                 z            z trans factor
94 
95   Returns:      None.
96  *---------------------------------------------------------------------------*/
MTX_TransApply44(const MtxFx44 * pSrc,MtxFx44 * pDst,fx32 x,fx32 y,fx32 z)97 void MTX_TransApply44(const MtxFx44 *pSrc, MtxFx44 *pDst, fx32 x, fx32 y, fx32 z)
98 {
99     SDK_NULL_ASSERT(pSrc);
100     SDK_NULL_ASSERT(pDst);
101 
102     if (pSrc != pDst)
103     {
104         MI_Copy48B(pSrc, pDst);
105     }
106     {
107         fx64    xx = x;
108         fx64    yy = y;
109         fx64    zz = z;
110 
111         pDst->_30 =
112             pSrc->_30 + (fx32)((xx * pSrc->_00 + yy * pSrc->_10 + zz * pSrc->_20) >> FX32_SHIFT);
113         pDst->_31 =
114             pSrc->_31 + (fx32)((xx * pSrc->_01 + yy * pSrc->_11 + zz * pSrc->_21) >> FX32_SHIFT);
115         pDst->_32 =
116             pSrc->_32 + (fx32)((xx * pSrc->_02 + yy * pSrc->_12 + zz * pSrc->_22) >> FX32_SHIFT);
117         pDst->_33 =
118             pSrc->_33 + (fx32)((xx * pSrc->_03 + yy * pSrc->_13 + zz * pSrc->_23) >> FX32_SHIFT);
119     }
120 }
121 
MTX_Transpose44_(register const MtxFx44 * pSrc,register MtxFx44 * pDst)122 asm void MTX_Transpose44_(register const MtxFx44* pSrc, register MtxFx44* pDst)
123 {
124     stmfd sp!, {r4-r11}
125 
126     ldr   r12, [r0, #48]
127     ldmia r0!, {r2-r11}
128     stmia r1!, {r2, r6, r10, r12}
129     ldr   r12, [r0, #12]
130     stmia r1!, {r3, r7, r11, r12}
131 
132     ldmia r0,  {r10-r11}
133     ldr   r12, [r0, #16]
134     stmia r1!, {r4, r8, r10, r12}
135 
136     ldr   r12, [r0, #20]
137     stmia r1!, {r5, r9, r11, r12}
138 
139     ldmfd sp!, {r4-r11}
140     bx    lr
141 }
142 
143 
144 #include <nitro/code16.h>
MTX_Scale44_(register MtxFx44 * pDst,register fx32 x,register fx32 y,register fx32 z)145 asm void MTX_Scale44_(register MtxFx44 * pDst, register fx32 x, register fx32 y, register fx32 z)
146 {
147     stmia r0!, {r1}
148     mov   r1, #0
149     str   r2, [r0, #16]
150     mov   r2, #0
151     stmia r0!, {r1, r2}
152     stmia r0!, {r1, r2}
153     add   r0, r0, #4
154     stmia r0!, {r1, r2}
155     stmia r0!, {r1, r2, r3}
156     stmia r0!, {r1, r2}
157     mov   r3, #1
158     lsl   r3, r3, #12
159     stmia r0!, {r1, r2}
160     str   r3, [r0, #0]
161     bx lr
162 }
163 #include <nitro/code32.h>
164 
165 
166 
167 
168 /*---------------------------------------------------------------------------*
169   Name:         MTX_ScaleApply44
170 
171   Description:  This function performs the operation equivalent to
172                 MTX_Scale44 + MTX_Concat44.
173 
174   Arguments:    pSrc         a pointer to a 4x4 matrix
175                 pDst         a pointer to a 4x4 matrix
176                 x            x scale factor
177                 y            y scale factor
178                 z            z scale factor
179 
180   Returns:      None.
181  *---------------------------------------------------------------------------*/
MTX_ScaleApply44(const MtxFx44 * pSrc,MtxFx44 * pDst,fx32 x,fx32 y,fx32 z)182 void MTX_ScaleApply44(const MtxFx44 *pSrc, MtxFx44 *pDst, fx32 x, fx32 y, fx32 z)
183 {
184     fx64    v;
185 
186     SDK_NULL_ASSERT(pSrc);
187     SDK_NULL_ASSERT(pDst);
188 
189     v = (fx64)x;
190     pDst->_00 = mul64(v, pSrc->_00);
191     pDst->_01 = mul64(v, pSrc->_01);
192     pDst->_02 = mul64(v, pSrc->_02);
193     pDst->_03 = mul64(v, pSrc->_03);
194 
195     v = (fx64)y;
196     pDst->_10 = mul64(v, pSrc->_10);
197     pDst->_11 = mul64(v, pSrc->_11);
198     pDst->_12 = mul64(v, pSrc->_12);
199     pDst->_13 = mul64(v, pSrc->_13);
200 
201     v = (fx64)z;
202     pDst->_20 = mul64(v, pSrc->_20);
203     pDst->_21 = mul64(v, pSrc->_21);
204     pDst->_22 = mul64(v, pSrc->_22);
205     pDst->_23 = mul64(v, pSrc->_23);
206 
207     if (pSrc != pDst)
208     {
209         register fx32 t1, t2;
210         t1 = pSrc->_30;
211         t2 = pSrc->_31;
212         pDst->_30 = t1;
213         pDst->_31 = t2;
214 
215         t1 = pSrc->_32;
216         t2 = pSrc->_33;
217         pDst->_32 = t1;
218         pDst->_33 = t2;
219     }
220 }
221 
222 #include <nitro/code16.h>
MTX_RotX44_(register MtxFx44 * pDst,register fx32 sinVal,register fx32 cosVal)223 asm void MTX_RotX44_(register MtxFx44 * pDst, register fx32 sinVal, register fx32 cosVal)
224 {
225 
226     str   r2, [r0, #20]
227     str   r2, [r0, #40]
228     str   r1, [r0, #24]
229     neg   r1, r1
230     str   r1, [r0, #36]
231 
232     mov   r1, #1
233     mov   r2, #0
234     lsl   r1, r1, #12
235     mov   r3, #0
236 
237     stmia r0!, {r1, r2, r3}
238     stmia r0!, {r2, r3}
239     add   r0, #8
240     stmia r0!, {r2, r3}
241     add   r0, #8
242     stmia r0!, {r2, r3}
243     stmia r0!, {r2, r3}
244     str   r1, [r0, #0]
245 
246     bx    lr
247 }
248 #include <nitro/code32.h>
249 
250 #include <nitro/code16.h>
MTX_RotY44_(register MtxFx44 * pDst,register fx32 sinVal,register fx32 cosVal)251 asm void MTX_RotY44_(register MtxFx44 * pDst, register fx32 sinVal, register fx32 cosVal)
252 {
253     str   r2, [r0, #0]
254     str   r2, [r0, #40]
255     str   r1, [r0, #32]
256     neg   r1, r1
257     str   r1, [r0, #8]
258 
259     mov   r3, #1
260     mov   r1, #0
261     lsl   r3, r3, #12
262     mov   r2, #0
263 
264     str   r2, [r0, #4]
265     add   r0, #12
266     stmia r0!, {r1, r2, r3}
267     stmia r0!, {r1, r2}
268     str   r2, [r0, #4]
269     add   r0, #12
270     stmia r0!, {r1, r2}
271     stmia r0!, {r1, r2, r3}
272 
273     bx    lr
274 }
275 #include <nitro/code32.h>
276 
277 #include <nitro/code16.h>
MTX_RotZ44_(register MtxFx44 * pDst,register fx32 sinVal,register fx32 cosVal)278 asm void MTX_RotZ44_(register MtxFx44 * pDst, register fx32 sinVal, register fx32 cosVal)
279 {
280     str   r2, [r0, #0]
281     str   r2, [r0, #20]
282     str   r1, [r0, #4]
283     neg   r1, r1
284     str   r1, [r0, #16]
285 
286     mov   r3, #1
287     mov   r1, #0
288     lsl   r3, r3, #12
289     mov   r2, #0
290 
291     add   r0, #8
292     stmia r0!, {r1, r2}
293     add   r0, #8
294     stmia r0!, {r1, r2}
295     stmia r0!, {r1, r2, r3}
296     stmia r0!, {r1, r2}
297     stmia r0!, {r1, r2, r3}
298 
299     bx    lr
300 }
301 #include <nitro/code32.h>
302 
303 
304 /*---------------------------------------------------------------------------*
305   Name:         MTX_RotAxis44
306 
307   Description:  Sets a rotation matrix about an arbitrary axis.
308 
309   Arguments:    pDst         a pointer to a 4x4 matrix
310                 vec          a pointer to a vector containing the x,y,z axis
311                              components. *vec must be a unit vector.
312                 sinVal       sine of an angle of rotation
313                 cosVal       cosine of an angle of rotation
314 
315   Returns:      None.
316  *---------------------------------------------------------------------------*/
MTX_RotAxis44(MtxFx44 * pDst,const VecFx32 * vec,fx32 sinVal,fx32 cosVal)317 void MTX_RotAxis44(MtxFx44 *pDst, const VecFx32 *vec, fx32 sinVal, fx32 cosVal)
318 {
319     fx64    t, ss, cc, xx, yy, zz;
320     fx32    t01;
321     fx32    s2;
322     SDK_NULL_ASSERT(pDst);
323     SDK_NULL_ASSERT(vec);
324 
325     t = (fx64)(FX32_ONE - cosVal);
326     ss = (fx64)sinVal;
327     cc = (fx64)cosVal;
328     xx = (fx64)vec->x;
329     yy = (fx64)vec->y;
330     zz = (fx64)vec->z;
331 
332     t01 = (fx32)((xx * xx * t) >> (FX64_SHIFT + FX64_SHIFT));
333     pDst->_00 = t01 + cosVal;
334 
335     t01 = (fx32)((yy * yy * t) >> (FX64_SHIFT + FX64_SHIFT));
336     pDst->_11 = t01 + cosVal;
337 
338     t01 = (fx32)((zz * zz * t) >> (FX64_SHIFT + FX64_SHIFT));
339     pDst->_22 = t01 + cosVal;
340 
341     t01 = (fx32)((t * xx * yy) >> (FX64_SHIFT + FX64_SHIFT));
342     s2 = (fx32)((ss * zz) >> FX64_SHIFT);
343     pDst->_01 = t01 + s2;
344     pDst->_10 = t01 - s2;
345 
346     t01 = (fx32)((t * xx * zz) >> (FX64_SHIFT + FX64_SHIFT));
347     s2 = (fx32)((ss * yy) >> FX64_SHIFT);
348     pDst->_02 = t01 - s2;
349     pDst->_20 = t01 + s2;
350 
351     t01 = (fx32)((t * yy * zz) >> (FX64_SHIFT + FX64_SHIFT));
352     s2 = (fx32)((ss * xx) >> FX64_SHIFT);
353     pDst->_12 = t01 + s2;
354     pDst->_21 = t01 - s2;
355 
356     pDst->_03 = pDst->_13 = pDst->_23 = pDst->_30 = pDst->_31 = pDst->_32 = 0;
357     pDst->_33 = FX32_ONE;
358 }
359 
360 
361 /*---------------------------------------------------------------------------*
362   Name:         MTX_Concat44
363 
364   Description:  Concatenates two 4x4 matrices.
365                 The order of operation is A x B = AB.
366                 OK for any of ab == a == b.
367 
368   Arguments:    a            a pointer to a 4x4 matrix
369                 b            a pointer to a 4x4 matrix
370                 ab           a pointer to the resultant matrix
371 
372   Returns:      None.
373  *---------------------------------------------------------------------------*/
MTX_Concat44(const MtxFx44 * a,const MtxFx44 * b,MtxFx44 * ab)374 void MTX_Concat44(const MtxFx44 *a, const MtxFx44 *b, MtxFx44 *ab)
375 {
376     MtxFx44 tmp;
377     MtxFx44 *p;
378 
379     register fx32 x, y, z, w;
380     register fx32 xx, yy, zz, ww;
381 
382     SDK_NULL_ASSERT(a);
383     SDK_NULL_ASSERT(b);
384     SDK_NULL_ASSERT(ab);
385 
386     if (ab == b)
387     {
388         p = &tmp;
389     }
390     else
391     {
392         p = ab;
393     }
394 
395     // compute (a x b) -> p
396 
397     // row 0
398     x = a->_00;
399     y = a->_01;
400     z = a->_02;
401     w = a->_03;
402 
403     p->_00 =
404         (fx32)(((fx64)x * b->_00 + (fx64)y * b->_10 + (fx64)z * b->_20 +
405                 (fx64)w * b->_30) >> FX32_SHIFT);
406     p->_01 =
407         (fx32)(((fx64)x * b->_01 + (fx64)y * b->_11 + (fx64)z * b->_21 +
408                 (fx64)w * b->_31) >> FX32_SHIFT);
409     p->_03 =
410         (fx32)(((fx64)x * b->_03 + (fx64)y * b->_13 + (fx64)z * b->_23 +
411                 (fx64)w * b->_33) >> FX32_SHIFT);
412 
413     xx = b->_02;
414     yy = b->_12;
415     zz = b->_22;
416     ww = b->_32;
417 
418     p->_02 = (fx32)(((fx64)x * xx + (fx64)y * yy + (fx64)z * zz + (fx64)w * ww) >> FX32_SHIFT);
419 
420     // row 1
421     x = a->_10;
422     y = a->_11;
423     z = a->_12;
424     w = a->_13;
425 
426     p->_12 = (fx32)(((fx64)x * xx + (fx64)y * yy + (fx64)z * zz + (fx64)w * ww) >> FX32_SHIFT);
427     p->_11 =
428         (fx32)(((fx64)x * b->_01 + (fx64)y * b->_11 + (fx64)z * b->_21 +
429                 (fx64)w * b->_31) >> FX32_SHIFT);
430     p->_13 =
431         (fx32)(((fx64)x * b->_03 + (fx64)y * b->_13 + (fx64)z * b->_23 +
432                 (fx64)w * b->_33) >> FX32_SHIFT);
433 
434     xx = b->_00;
435     yy = b->_10;
436     zz = b->_20;
437     ww = b->_30;
438 
439     p->_10 = (fx32)(((fx64)x * xx + (fx64)y * yy + (fx64)z * zz + (fx64)w * ww) >> FX32_SHIFT);
440 
441     // row 2
442     x = a->_20;
443     y = a->_21;
444     z = a->_22;
445     w = a->_23;
446 
447     p->_20 = (fx32)(((fx64)x * xx + (fx64)y * yy + (fx64)z * zz + (fx64)w * ww) >> FX32_SHIFT);
448     p->_21 =
449         (fx32)(((fx64)x * b->_01 + (fx64)y * b->_11 + (fx64)z * b->_21 +
450                 (fx64)w * b->_31) >> FX32_SHIFT);
451     p->_23 =
452         (fx32)(((fx64)x * b->_03 + (fx64)y * b->_13 + (fx64)z * b->_23 +
453                 (fx64)w * b->_33) >> FX32_SHIFT);
454 
455     xx = b->_02;
456     yy = b->_12;
457     zz = b->_22;
458     ww = b->_32;
459 
460     p->_22 = (fx32)(((fx64)x * xx + (fx64)y * yy + (fx64)z * zz + (fx64)w * ww) >> FX32_SHIFT);
461 
462     // row 3
463     x = a->_30;
464     y = a->_31;
465     z = a->_32;
466     w = a->_33;
467 
468     p->_32 = (fx32)(((fx64)x * xx + (fx64)y * yy + (fx64)z * zz + (fx64)w * ww) >> FX32_SHIFT);
469     p->_31 =
470         (fx32)(((fx64)x * b->_01 + (fx64)y * b->_11 + (fx64)z * b->_21 +
471                 (fx64)w * b->_31) >> FX32_SHIFT);
472     p->_30 =
473         (fx32)(((fx64)x * b->_00 + (fx64)y * b->_10 + (fx64)z * b->_20 +
474                 (fx64)w * b->_30) >> FX32_SHIFT);
475     p->_33 =
476         (fx32)(((fx64)x * b->_03 + (fx64)y * b->_13 + (fx64)z * b->_23 +
477                 (fx64)w * b->_33) >> FX32_SHIFT);
478 
479     if (p == &tmp)
480     {
481         *ab = tmp;
482     }
483 }
484 
485 /*---------------------------------------------------------------------------*
486   Name:         MTX_FrustumW
487 
488   Description:  Computes a 4x4 perspective projection matrix from a specified
489                 view volume.
490 
491   Arguments:    t            top coordinate of view volume at the near clipping plane
492                 b            bottom coordinate of view volume at the near clipping plane
493                 l            left coordinate of view volume at near clipping plane
494                 r            right coordinate of view volume at near clipping plane
495                 n            positive distance from camera to near clipping plane
496                 f            positive distance from camera to far clipping plane
497                 mtx          4x4 matrix to be set if not NULL
498 
499   Returns:      None.
500  *---------------------------------------------------------------------------*/
MTX_FrustumW(fx32 t,fx32 b,fx32 l,fx32 r,fx32 n,fx32 f,fx32 scaleW,MtxFx44 * mtx)501 void MTX_FrustumW(fx32 t, fx32 b, fx32 l, fx32 r, fx32 n, fx32 f, fx32 scaleW, MtxFx44 *mtx)
502 {
503     fx64c   inv1, inv2;
504     fx32    dblN;
505 
506     SDK_NULL_ASSERT(mtx);
507     SDK_ASSERTMSG(t != b, "MTX_Frustum: 't' and 'b' clipping planes are equal.");
508     SDK_ASSERTMSG(l != r, "MTX_Frustum: 'l' and 'r' clipping planes are equal.");
509     SDK_ASSERTMSG(n != f, "MTX_Frustum: 'n' and 'f' clipping planes are equal.");
510 
511     SDK_MINMAX_ASSERT(f, -0x10000 * FX32_ONE, 0x10000 * FX32_ONE - 1);
512     SDK_MINMAX_ASSERT(n, -0x10000 * FX32_ONE, 0x10000 * FX32_ONE - 1);
513 
514     /* Initialize matrix in parallel with asynchronous division */
515     {
516         FX_InvAsync(r - l);
517         mtx->_01 = 0;
518         mtx->_02 = 0;
519         mtx->_03 = 0;
520         mtx->_10 = 0;
521         mtx->_12 = 0;
522         mtx->_13 = 0;
523         mtx->_23 = -scaleW;
524         mtx->_30 = 0;
525         mtx->_31 = 0;
526         mtx->_33 = 0;
527         dblN = n << 1;
528         inv1 = FX_GetInvResultFx64c();
529     }
530     {
531         FX_InvAsyncImm(t - b);
532         if (scaleW != FX32_ONE)
533         {
534             inv1 = (inv1 * scaleW) / FX32_ONE;
535         }
536         mtx->_00 = FX_Mul32x64c(dblN, inv1);
537         inv2 = FX_GetInvResultFx64c();
538     }
539     {
540         FX_InvAsyncImm(n - f);
541         if (scaleW != FX32_ONE)
542         {
543             inv2 = (inv2 * scaleW) / FX32_ONE;
544         }
545         mtx->_11 = FX_Mul32x64c(dblN, inv2);
546         mtx->_20 = FX_Mul32x64c(r + l, inv1);
547         mtx->_21 = FX_Mul32x64c(t + b, inv2);
548         inv1 = FX_GetInvResultFx64c();
549     }
550     if (scaleW != FX32_ONE)
551     {
552         inv1 = (inv1 * scaleW) / FX32_ONE;
553     }
554     mtx->_22 = FX_Mul32x64c(f + n, inv1);
555     mtx->_32 = FX_Mul32x64c(FX_Mul(dblN, f), inv1);
556 }
557 
558 /*---------------------------------------------------------------------------*
559   Name:         MTX_PerspectiveW
560 
561   Description:  Computes a 4x4 perspective projection matrix from field of
562                 view and aspect ratio.
563 
564   Arguments:    fovySin      sine value of fovy
565                 fovyCos      cosine value of fovy
566                 aspect       ratio of view window width:height (X / Y)
567                 n            positive distance from camera to near clipping plane
568                 f            positive distance from camera to far clipping plane
569                 scaleW       W scale parameter that adjust precision of view volume.
570                 mtx          4x4 matrix to be set if not NULL
571 
572   Returns:      None.
573  *---------------------------------------------------------------------------*/
MTX_PerspectiveW(fx32 fovySin,fx32 fovyCos,fx32 aspect,fx32 n,fx32 f,fx32 scaleW,MtxFx44 * mtx)574 void MTX_PerspectiveW(fx32 fovySin, fx32 fovyCos, fx32 aspect, fx32 n, fx32 f, fx32 scaleW, MtxFx44 *mtx)
575 {
576     fx32    one_tan;
577     fx64    t;
578 
579     SDK_NULL_ASSERT(mtx);
580     SDK_ASSERTMSG(fovySin > 0 && fovySin < FX32_ONE, "G3_Perspective: sine of fovy out of range.");
581     SDK_ASSERTMSG(fovyCos > -FX32_ONE
582                   && fovyCos < FX32_ONE, "G3_Perspective: cosine of fovy out of range.");
583     SDK_ASSERTMSG(aspect != 0, "G3_Perspective: aspect is 0.");
584 
585     SDK_MINMAX_ASSERT(f, -0x10000 * FX32_ONE, 0x10000 * FX32_ONE - 1);
586     SDK_MINMAX_ASSERT(n, -0x10000 * FX32_ONE, 0x10000 * FX32_ONE - 1);
587 
588     one_tan = FX_Div((fx32)fovyCos, (fx32)fovySin);
589     FX_InvAsyncImm(n - f);
590     if (scaleW != FX32_ONE)
591     {
592         one_tan = (one_tan * scaleW) / FX32_ONE;
593     }
594     mtx->_01 = 0;
595     mtx->_02 = 0;
596     mtx->_03 = 0;
597     mtx->_10 = 0;
598     mtx->_11 = one_tan;
599     mtx->_12 = 0;
600     mtx->_13 = 0;
601     mtx->_20 = 0;
602     mtx->_21 = 0;
603     mtx->_23 = -scaleW;
604     mtx->_30 = 0;
605     mtx->_31 = 0;
606     mtx->_33 = 0;
607     t = FX_GetInvResultFx64c();
608     FX_DivAsyncImm(one_tan, aspect);
609     if (scaleW != FX32_ONE)
610     {
611         t = (t * scaleW) / FX32_ONE;
612     }
613     mtx->_22 = FX_Mul32x64c(f + n, t);
614     mtx->_32 = FX_Mul32x64c(FX_Mul(n << 1, f), t);
615     mtx->_00 = FX_GetDivResult();
616 }
617 
618 /*---------------------------------------------------------------------------*
619   Name:         MTX_OrthoW
620 
621   Description:  Computes a 4x4 orthographic projection matrix.
622 
623   Arguments:    t            top coordinate of parallel view volume
624                 b            bottom coordinate of parallel view volume
625                 l            left coordinate of parallel view volume
626                 r            right coordinate of parallel view volume
627                 n            positive distance from camera to near clipping plane
628                 f            positive distance from camera to far clipping plane
629                 scaleW       W scale parameter that adjust precision of view volume.
630                 mtx          4x4 matrix to be set if not NULL
631 
632   Returns:      None.
633  *---------------------------------------------------------------------------*/
MTX_OrthoW(fx32 t,fx32 b,fx32 l,fx32 r,fx32 n,fx32 f,fx32 scaleW,MtxFx44 * mtx)634 void MTX_OrthoW(fx32 t, fx32 b, fx32 l, fx32 r, fx32 n, fx32 f, fx32 scaleW, MtxFx44 *mtx)
635 {
636     fx64c   inv1, inv2, inv3;
637 
638     SDK_NULL_ASSERT(mtx);
639     SDK_ASSERTMSG(t != b, "G3_Ortho: 't' and 'b' clipping planes are equal.");
640     SDK_ASSERTMSG(l != r, "G3_Ortho: 'l' and 'r' clipping planes are equal.");
641     SDK_ASSERTMSG(n != f, "G3_Ortho: 'n' and 'f' clipping planes are equal.");
642 
643     SDK_MINMAX_ASSERT(f, -0x10000 * FX32_ONE, 0x10000 * FX32_ONE - 1);
644     SDK_MINMAX_ASSERT(n, -0x10000 * FX32_ONE, 0x10000 * FX32_ONE - 1);
645 
646     {
647         FX_InvAsync(r - l);
648         mtx->_01 = 0;
649         mtx->_02 = 0;
650         mtx->_03 = 0;
651         mtx->_10 = 0;
652         mtx->_12 = 0;
653         mtx->_13 = 0;
654         mtx->_20 = 0;
655         mtx->_21 = 0;
656         mtx->_23 = 0;
657         mtx->_33 = scaleW;
658         inv1 = FX_GetInvResultFx64c();
659     }
660     {
661         FX_InvAsyncImm(t - b);
662         if (scaleW != FX32_ONE)
663         {
664             inv1 = (inv1 * scaleW) / FX32_ONE;
665         }
666         mtx->_00 = FX_Mul32x64c(FX32_ONE * 2, inv1);
667         inv2 = FX_GetInvResultFx64c();
668     }
669     {
670         FX_InvAsyncImm(n - f);
671         if (scaleW != FX32_ONE)
672         {
673             inv2 = (inv2 * scaleW) / FX32_ONE;
674         }
675         mtx->_11 = FX_Mul32x64c(FX32_ONE * 2, inv2);
676         inv3 = FX_GetInvResultFx64c();
677     }
678 
679     if (scaleW != FX32_ONE)
680     {
681         inv3 = (inv3 * scaleW) / FX32_ONE;
682     }
683     mtx->_22 = FX_Mul32x64c(FX32_ONE * 2, inv3);
684     mtx->_30 = FX_Mul32x64c(-r - l, inv1);
685     mtx->_31 = FX_Mul32x64c(-t - b, inv2);
686     mtx->_32 = FX_Mul32x64c(f + n, inv3);
687 }
688 
689 #include <nitro/codereset.h>
690