1 /*---------------------------------------------------------------------------*
2   Project: matrix vector Library
3   File:    mtxvec.c
4 
5   Copyright 1998-2011 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  *---------------------------------------------------------------------------*/
14 
15 #include <math.h>
16 #include <stdio.h>
17 #include <cafe/mtx.h>
18 #include <cafe/mtx/mtx44.h>
19 #include "mtxAssert.h"
20 #include "mtx44Assert.h"
21 
22 /*---------------------------------------------------------------------*
23 
24                              VECTOR SECTION
25 
26  *---------------------------------------------------------------------*/
27 
28 //static const f32x2    c_zero  = {0.0F, 0.0F};
29 static const f32x2    c_half  = {0.5F, 0.5F};
30 static const f32x2    c_three = {3.0F, 3.0F};
31 
32 /*---------------------------------------------------------------------*
33 
34 Name:           VECAdd
35 
36 Description:    add two vectors.
37 
38 
39 Arguments:      a    first vector.
40 
41                 b    second vector.
42 
43                 ab   resultant vector (a + b).
44                      ok if ab == a or ab == b.
45 
46 
47 Return:         none.
48 
49  *---------------------------------------------------------------------*/
50 /*---------------------------------------------------------------------*
51     C version
52  *---------------------------------------------------------------------*/
C_VECAdd(const Vec * a,const Vec * b,Vec * ab)53 void C_VECAdd ( const Vec *a, const Vec *b, Vec *ab )
54 {
55 
56     ASSERTMSG( ( a    != 0), VEC_ADD_1 );
57     ASSERTMSG( ( b    != 0), VEC_ADD_2 );
58     ASSERTMSG( ( ab != 0),   VEC_ADD_3 );
59 
60 
61     ab->x = a->x + b->x;
62     ab->y = a->y + b->y;
63     ab->z = a->z + b->z;
64 
65 }
66 
67 #if !defined(WIN32) && !defined(WIN64)
68 /*---------------------------------------------------------------------*
69     Paired-Single intrinsics version
70  *---------------------------------------------------------------------*
71             Note that this performs NO error checking.
72  *---------------------------------------------------------------------*/
PSVECAdd(const Vec * a,const Vec * b,Vec * ab)73 void PSVECAdd ( const Vec *a, const Vec *b, Vec *ab )
74 {
75     f32x2 V1_XY;
76     f32x2 V2_XY;
77     f32x2 V1_Z;
78     f32x2 V2_Z;
79     f32x2 D1_XY;
80     f32x2 D1_Z;
81 
82     //load vectors XY
83     V1_XY = __PSQ_L(a, 0, 0);
84     V2_XY = __PSQ_L(b, 0, 0);
85 
86     //add vectors XY
87     D1_XY = __PS_ADD(V1_XY, V2_XY);
88 
89     //store result XY
90     __PSQ_ST(ab, D1_XY, 0, 0);
91 
92     //load vectors Z
93     V1_Z = __PSQ_LX(a, 8, 1, 0);
94     V2_Z = __PSQ_LX(b, 8, 1, 0);
95 
96     //add vectors Z
97     D1_Z = __PS_ADD(V1_Z, V2_Z);
98 
99     //store result YZ
100     __PSQ_STX(ab, 8, D1_Z, 1, 0);
101 }
102 #endif
103 
104 /*---------------------------------------------------------------------*
105 
106 Name:           VECSubtract
107 
108 Description:    subtract one vector from another.
109 
110 
111 Arguments:      a       first vector.
112 
113                 b       second vector.
114 
115                 a_b     resultant vector (a - b).
116                         ok if a_b == a or a_b == b.
117 
118 
119 Return:         none.
120 
121  *---------------------------------------------------------------------*/
122 /*---------------------------------------------------------------------*
123     C version
124  *---------------------------------------------------------------------*/
C_VECSubtract(const Vec * a,const Vec * b,Vec * a_b)125 void C_VECSubtract ( const Vec *a, const Vec *b, Vec *a_b )
126 {
127 
128     ASSERTMSG( ( a    != 0),    VEC_SUBTRACT_1     );
129     ASSERTMSG( ( b    != 0),    VEC_SUBTRACT_2     );
130     ASSERTMSG( ( a_b != 0),     VEC_SUBTRACT_3     );
131 
132 
133     a_b->x = a->x - b->x;
134     a_b->y = a->y - b->y;
135     a_b->z = a->z - b->z;
136 
137 }
138 
139 #if !defined(WIN32) && !defined(WIN64)
140 /*---------------------------------------------------------------------*
141     Paired-Single intrinsics version
142  *---------------------------------------------------------------------*
143             Note that this performs NO error checking.
144  *---------------------------------------------------------------------*/
PSVECSubtract(const Vec * a,const Vec * b,Vec * ab)145 void PSVECSubtract ( const Vec *a, const Vec *b, Vec *ab )
146 {
147     f32x2 V1_XY;
148     f32x2 V2_XY;
149     f32x2 V1_Z;
150     f32x2 V2_Z;
151     f32x2 D1_XY;
152     f32x2 D1_Z;
153 
154     //load vectors XY
155     V1_XY = __PSQ_L(a, 0, 0);
156     V2_XY = __PSQ_L(b, 0, 0);
157 
158     //sub vectors XY
159     D1_XY = __PS_SUB(V1_XY, V2_XY);
160 
161     //store result XY
162     __PSQ_ST(ab, D1_XY, 0, 0);
163 
164     //load vectors Z
165     V1_Z = __PSQ_LX(a, 8, 1, 0);
166     V2_Z = __PSQ_LX(b, 8, 1, 0);
167 
168     //sub vectors Z
169     D1_Z = __PS_SUB(V1_Z, V2_Z);
170 
171     //store result Z
172     __PSQ_STX(ab, 8, D1_Z, 1, 0);
173 }
174 #endif
175 
176 /*---------------------------------------------------------------------*
177 
178 Name:           VECScale
179 
180 Description:    multiply a vector by a scalar.
181 
182 
183 Arguments:      src     unscaled source vector.
184 
185                 dst     scaled resultant vector ( src * scale).
186                         ok if dst == src.
187 
188                 scale   scaling factor.
189 
190 
191 Return:         none.
192 
193  *---------------------------------------------------------------------*/
194 /*---------------------------------------------------------------------*
195     C version
196  *---------------------------------------------------------------------*/
C_VECScale(const Vec * src,Vec * dst,f32 scale)197 void C_VECScale ( const Vec *src, Vec *dst, f32 scale )
198 {
199 
200     ASSERTMSG( ( src  != 0),  VEC_SCALE_1  );
201     ASSERTMSG( ( dst  != 0),  VEC_SCALE_2  );
202 
203 
204     dst->x = src->x * scale;
205     dst->y = src->y * scale;
206     dst->z = src->z * scale;
207 
208 }
209 
210 #if !defined(WIN32) && !defined(WIN64)
211 /*---------------------------------------------------------------------*
212     Paired-Single intrinsics version
213  *---------------------------------------------------------------------*
214             Note that this performs NO error checking.
215  *---------------------------------------------------------------------*/
PSVECScale(const Vec * src,Vec * dst,f32 scale)216 void PSVECScale ( const Vec *src, Vec *dst, f32 scale )
217 {
218     f32x2 V1_XY;
219     f32x2 V1_Z;
220     f32x2 D1_XY;
221     f32x2 D1_Z;
222     f32x2 SCALE = {scale, scale};
223 
224     //load vectors XY
225     V1_XY = __PSQ_L(src, 0, 0);
226 
227     //load vectors Z
228     V1_Z = __PSQ_LX(src, 8, 1, 0);
229 
230     //muls vectors XY
231     D1_XY = __PS_MULS0(V1_XY, SCALE);
232 
233     //store result XY
234     __PSQ_ST(dst, D1_XY, 0, 1);
235 
236     //muls vectors Z
237     D1_Z = __PS_MULS0(V1_Z, SCALE);
238 
239     //store result YZ
240     __PSQ_STX(dst, 8, D1_Z, 1, 0);
241 }
242 #endif
243 
244 /*---------------------------------------------------------------------*
245 
246 Name:           VECNormalize
247 
248 Description:    normalize a vector.
249 
250 
251 Arguments:      src     non-unit source vector.
252 
253                 unit    resultant unit vector ( src / src magnitude ).
254                         ok if unit == src
255 
256 
257 Return:         none.
258 
259  *---------------------------------------------------------------------*/
260 /*---------------------------------------------------------------------*
261     C version
262  *---------------------------------------------------------------------*/
C_VECNormalize(const Vec * src,Vec * unit)263 void C_VECNormalize ( const Vec *src, Vec *unit )
264 {
265     f32 mag;
266 
267     ASSERTMSG( (src != 0 ),     VEC_NORMALIZE_1  );
268     ASSERTMSG( (unit != 0),     VEC_NORMALIZE_2  );
269 
270     mag = (src->x * src->x) + (src->y * src->y) + (src->z * src->z);
271 
272     ASSERTMSG( (mag != 0),      VEC_NORMALIZE_3  );
273 
274     mag = 1.0f / sqrtf(mag);
275 
276     unit->x = src->x * mag;
277     unit->y = src->y * mag;
278     unit->z = src->z * mag;
279 
280 }
281 
282 #if !defined(WIN32) && !defined(WIN64)
283 /*---------------------------------------------------------------------*
284     Paired-Single intrinsics version
285  *---------------------------------------------------------------------*
286             Note that this performs NO error checking.
287  *---------------------------------------------------------------------*/
PSVECNormalize(const Vec * vec1,Vec * dst)288 void PSVECNormalize ( const Vec *vec1, Vec *dst )
289 {
290     f32x2 v1_xy, v1_z;
291     f32x2 xx_zz, xx_yy;
292     f32x2 sqsum;
293     f32x2 rsqrt;
294     f32x2 nwork0, nwork1;
295 
296     // X | Y
297     //psq_l       v1_xy, 0(vec1), 0, 0;
298     v1_xy = __PSQ_L(vec1, 0, 0);
299 
300     // X*X | Y*Y
301     //ps_mul      xx_yy, v1_xy, v1_xy;
302     xx_yy = __PS_MUL(v1_xy, v1_xy);
303 
304     // Z | 1
305     //psq_l       v1_z, 8(vec1), 1, 0;
306     v1_z = __PSQ_LX(vec1, 8, 1, 0);
307 
308     // X*X+Z*Z | Y*Y+1
309     //ps_madd     xx_zz, v1_z, v1_z, xx_yy;
310     xx_zz = __PS_MADD(v1_z, v1_z, xx_yy);
311 
312     // X*X+Z*Z+Y*Y | Z
313     //ps_sum0     sqsum, xx_zz, v1_z, xx_yy;
314     sqsum = __PS_SUM0(xx_zz, v1_z, xx_yy);
315 
316     // 1.0/sqrt : estimation[E]
317     //frsqrte     rsqrt, sqsum;
318     rsqrt = __PS_RSQRTE(sqsum);
319 
320     // Newton's refinement x 1
321     // E' = (E/2)(3 - sqsum * E * E)
322     //fmuls       nwork0, rsqrt, rsqrt;
323     //fmuls       nwork1, rsqrt, c_half;
324     //fnmsubs     nwork0, nwork0, sqsum, c_three;
325     //fmuls       rsqrt, nwork0, nwork1;
326     nwork0 = __PS_MUL(rsqrt, rsqrt);
327     nwork1 = __PS_MUL(rsqrt, c_half);
328     nwork0 = __PS_NMSUB(nwork0, sqsum, c_three);
329     rsqrt = __PS_MUL(nwork0, nwork1);
330 
331     // X * mag | Y * mag
332     //ps_muls0    v1_xy, v1_xy, rsqrt;
333     v1_xy = __PS_MULS0(v1_xy, rsqrt);
334 
335     //psq_st      v1_xy, 0(dst), 0, 0;
336     __PSQ_ST(dst, v1_xy, 0, 0);
337 
338     // Z * mag
339     //ps_muls0    v1_z, v1_z, rsqrt;
340     v1_z = __PS_MULS0(v1_z, rsqrt);
341 
342     //psq_st      v1_z, 8(dst), 1, 0;
343     __PSQ_STX(dst, 8, v1_z, 1, 0);
344 }
345 #endif
346 
347 /*---------------------------------------------------------------------*
348 
349 Name:           VECSquareMag
350 
351 Description:    compute the square of the magnitude of a vector.
352 
353 
354 Arguments:      v    source vector.
355 
356 
357 Return:         square magnitude of the vector.
358 
359  *---------------------------------------------------------------------*/
360 /*---------------------------------------------------------------------*
361     C version
362  *---------------------------------------------------------------------*/
C_VECSquareMag(const Vec * v)363 f32 C_VECSquareMag ( const Vec *v )
364 {
365     f32 sqmag;
366 
367     ASSERTMSG( (v != 0),  VEC_MAG_1 );
368 
369     sqmag = (v->x * v->x) + (v->y * v->y) + (v->z * v->z);
370 
371     return sqmag;
372 }
373 
374 #if !defined(WIN32) && !defined(WIN64)
375 /*---------------------------------------------------------------------*
376     Paired-Single intrinsics version
377  *---------------------------------------------------------------------*
378             Note that this performs NO error checking.
379  *---------------------------------------------------------------------*/
380 
PSVECSquareMag(const Vec * v)381 f32 PSVECSquareMag ( const Vec *v )
382 {
383     f32x2    V1_XY, V1_ZZ, sqmag;
384 
385     // load X | Y
386     V1_XY = __PSQ_L(v, 0, 0);
387 
388     // XX | YY
389     V1_XY = __PS_MUL(V1_XY, V1_XY);
390 
391     // load Z | Z
392     V1_ZZ[0] = v->z;
393     V1_ZZ[1] = v->z;
394 
395     // XX + ZZ | YY + ZZ
396     sqmag = __PS_MADD(V1_ZZ, V1_ZZ, V1_XY);
397     sqmag = __PS_SUM0(sqmag, V1_XY, V1_XY);
398 
399     return (f32)sqmag[0];
400 }
401 #endif
402 
403 /*---------------------------------------------------------------------*
404 
405 Name:           VECMag
406 
407 Description:    compute the magnitude of a vector.
408 
409 
410 Arguments:      v    source vector.
411 
412 
413 Return:         magnitude of the vector.
414 
415  *---------------------------------------------------------------------*/
416 /*---------------------------------------------------------------------*
417     C version
418  *---------------------------------------------------------------------*/
C_VECMag(const Vec * v)419 f32 C_VECMag ( const Vec *v )
420 {
421     return sqrtf( C_VECSquareMag(v) );
422 }
423 
424 #if !defined(WIN32) && !defined(WIN64)
425 /*---------------------------------------------------------------------*
426     Paired-Single intrinsics version
427  *---------------------------------------------------------------------*/
PSVECMag(const Vec * v)428 f32 PSVECMag ( const Vec *v )
429 {
430     f32x2    vzz, vxy; //vyz,
431     f32x2    sqmag, rmag; //dyz, dxy,
432     f32x2    nwork0, nwork1;
433 
434     // Square mag calculation
435     //psq_l       vxy, 0(v), 0, 0
436     vxy = __PSQ_L(v, 0, 0);
437 
438     //ps_mul      vxy, vxy, vxy
439     vxy = __PS_MUL(vxy, vxy);
440     vzz = __PSQ_LX(v, 8, 0, 0);
441 
442     //ps_madd     sqmag, vzz, vzz, vxy
443     sqmag = __PS_MADD(vzz, vzz, vxy);
444 
445     // Square mag
446     //ps_sum0     sqmag, sqmag, vxy, vxy
447     sqmag = __PS_SUM0(sqmag, vxy, vxy);
448 
449     if (sqmag[0] != 0)
450     {
451         // 1.0/sqrt : estimation[E]
452         //frsqrte     rmag, sqmag
453         rmag = __PS_RSQRTE(sqmag);
454 
455         // Refinement x 1 : E' = (E/2)(3 - X*E*E)
456         //fmul        nwork0, rsqmag, rsqmag
457         nwork0 = __PS_MUL(rmag, rmag);
458 
459         //fmul        nwork1, rsqmag, c_half
460         nwork1 = __PS_MUL(rmag, c_half);
461 
462         //fnmsub      nwork0, nwork0, mag, c_three
463         nwork0 = __PS_NMSUB(nwork0, sqmag, c_three);
464 
465         //fmul        rsqmag, nwork0, nwork1
466         rmag = __PS_MUL(nwork0, nwork1);
467 
468         // 1/sqrt(X) * X = sqrt(X)
469         //fmuls       sqmag, sqmag, rmag
470         sqmag = __PS_MUL(sqmag, rmag);
471     }
472 
473     return (f32)sqmag[0];
474 }
475 #endif
476 
477 /*---------------------------------------------------------------------*
478 
479 Name:           VECDotProduct
480 
481 Description:    compute the dot product of two vectors.
482 
483 
484 Arguments:      a    first vector.
485 
486                 b    second vector.
487 
488                 note:  input vectors do not have to be normalized.
489                        input vectors are not normalized within the function.
490 
491                        if direct cosine computation of the angle
492                        between a and b is desired, a and b should be
493                        normalized prior to calling VECDotProduct.
494 
495 
496 Return:         dot product value.
497 
498  *---------------------------------------------------------------------*/
499 /*---------------------------------------------------------------------*
500     C version
501  *---------------------------------------------------------------------*/
C_VECDotProduct(const Vec * a,const Vec * b)502 f32 C_VECDotProduct ( const Vec *a, const Vec *b )
503 {
504     f32 dot;
505 
506     ASSERTMSG( (a != 0), VEC_DOTPRODUCT_1 );
507     ASSERTMSG( (b != 0), VEC_DOTPRODUCT_2 );
508 
509     dot = (a->x * b->x) + (a->y * b->y) + (a->z * b->z);
510 
511     return dot;
512 }
513 
514 #if !defined(WIN32) && !defined(WIN64)
515 /*---------------------------------------------------------------------*
516     Paired-Single intrinsics version
517  *---------------------------------------------------------------------*
518             Note that this performs NO error checking.
519  *---------------------------------------------------------------------*/
PSVECDotProduct(const Vec * vec1,const Vec * vec2)520 f32 PSVECDotProduct ( const Vec *vec1, const Vec *vec2 )
521 {
522     f32x2    fp1, fp2, fp3, fp4, fp5;
523 
524     //psq_l    fp2, 4(vec1), 0, 0;
525     fp2 = __PSQ_LX(vec1, 4, 0, 0);
526 
527     //psq_l    fp3, 4(vec2), 0, 0;
528     fp3 = __PSQ_LX(vec2, 4, 0, 0);
529 
530     //ps_mul   fp2, fp2, fp3;
531     fp2 = __PS_MUL(fp2, fp3);
532 
533     //psq_l    fp5, 0(vec1), 0, 0;
534     fp5 = __PSQ_L(vec1, 0, 0);
535 
536     //psq_l    fp4, 0(vec2), 0, 0;
537     fp4 = __PSQ_L(vec2, 0, 0);
538 
539     //ps_madd  fp3, fp5, fp4, fp2;
540     fp3 = __PS_MADD(fp5, fp4, fp2);
541 
542     //ps_sum0  fp1, fp3, fp2, fp2;
543     fp1 = __PS_SUM0(fp3, fp2, fp2);
544 
545     return (f32)fp1[0];
546 }
547 #endif
548 
549 /*---------------------------------------------------------------------*
550 
551 Name:           VECCrossProduct
552 
553 Description:    compute the cross product of two vectors.
554 
555 
556 Arguments:      a       first vector.
557 
558                 b       second vector.
559 
560                 note:  input vectors do not have to be normalized.
561 
562 
563                 axb     resultant vector.
564                         ok if axb == a or axb == b.
565 
566 
567 Return:         none.
568 
569  *---------------------------------------------------------------------*/
570 /*---------------------------------------------------------------------*
571     C version
572  *---------------------------------------------------------------------*/
C_VECCrossProduct(const Vec * a,const Vec * b,Vec * axb)573 void C_VECCrossProduct ( const Vec *a, const Vec *b, Vec *axb )
574 {
575     Vec vTmp;
576 
577 
578     ASSERTMSG( (a    != 0),   VEC_CROSSPRODUCT_1    );
579     ASSERTMSG( (b    != 0),   VEC_CROSSPRODUCT_2    );
580     ASSERTMSG( (axb != 0),    VEC_CROSSPRODUCT_3    );
581 
582 
583     vTmp.x =  ( a->y * b->z ) - ( a->z * b->y );
584     vTmp.y =  ( a->z * b->x ) - ( a->x * b->z );
585     vTmp.z =  ( a->x * b->y ) - ( a->y * b->x );
586 
587 
588     axb->x = vTmp.x;
589     axb->y = vTmp.y;
590     axb->z = vTmp.z;
591 
592 }
593 
594 #if !defined(WIN32) && !defined(WIN64)
595 /*---------------------------------------------------------------------*
596     Paired-Single intrinsics version
597  *---------------------------------------------------------------------*
598             Note that this performs NO error checking.
599  *---------------------------------------------------------------------*/
PSVECCrossProduct(const Vec * vec1,const Vec * vec2,Vec * dst)600 void PSVECCrossProduct
601 (
602     const Vec *vec1,
603     const Vec *vec2,
604     Vec *dst
605 )
606 {
607     f32x2 fp0, fp1;
608     f32x2 fp2 = {vec1->z, vec1->z};
609     f32x2 fp3 = {vec2->z, vec2->z};
610     f32x2 fp4, fp5, fp6, fp7, fp8, fp9, fp10;
611 
612     //x =   a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY];
613     //y =   a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ];
614     //z =   a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX];
615 
616     // BX | BY
617     fp1 = __PSQ_L(vec2, 0, 0);
618 
619     // AX | AY
620     fp0 = __PSQ_L(vec1, 0, 0);
621 
622     // BY | BX
623     fp6 = __PS_MERGE10(fp1, fp1);
624 
625     // BX*AZ | BY*AZ
626     fp4 = __PS_MUL(fp1, fp2);
627 
628     // BX*AX | BY*AX
629     fp7 = __PS_MULS0(fp1, fp0);
630 
631     // AX*BZ-BX*AZ | AY*BZ-BY*AZ
632     fp5 = __PS_MSUB(fp0, fp3, fp4);
633 
634     // AX*BY-BX*AX | AY*BX-BY*AX
635     fp8 = __PS_MSUB(fp0, fp6, fp7);
636 
637     // AY*BZ-AZ*BY | AY*BZ-AZ*BY
638     fp9 = __PS_MERGE11(fp5, fp5);
639 
640     // AX*BZ-AZ*BX | AY*BX-AX*BY
641     fp10 = __PS_MERGE01(fp5, fp8);
642 
643     //Store X
644     __PSQ_ST(dst, fp9, 1, 0);
645 
646     // AZ*BX-AX*BZ | AX*BY-AY*BX
647     fp10 = __PS_NEG(fp10);
648 
649     // store YZ
650     __PSQ_STX(dst, 4, fp10, 0, 0);
651 
652 }
653 #endif
654 
655 /*---------------------------------------------------------------------*
656 
657 Name:           VECHalfAngle
658 
659 Description:    compute the vector halfway between two vectors.
660                 intended for use in computing specular highlights
661 
662 
663 Arguments:      a     first vector.
664                       this must point FROM the light source (tail)
665                       TO the surface (head).
666 
667                 b     second vector.
668                       this must point FROM the viewer (tail)
669                       TO the surface (head).
670 
671                 note:     input vectors do not have to be normalized.
672 
673 
674                 half  resultant normalized 'half-angle' vector.
675                       ok if half == a or half == b
676 
677 
678 Return:         none.
679 
680  *---------------------------------------------------------------------*/
681 /*---------------------------------------------------------------------*
682     C version
683  *---------------------------------------------------------------------*/
C_VECHalfAngle(const Vec * a,const Vec * b,Vec * half)684 void C_VECHalfAngle ( const Vec *a, const Vec *b, Vec *half )
685 {
686     Vec aTmp, bTmp, hTmp;
687 
688 
689     ASSERTMSG( (a    != 0),    VEC_HALFANGLE_1  );
690     ASSERTMSG( (b    != 0),    VEC_HALFANGLE_2  );
691     ASSERTMSG( (half != 0),    VEC_HALFANGLE_3  );
692 
693 
694     aTmp.x = -a->x;
695     aTmp.y = -a->y;
696     aTmp.z = -a->z;
697 
698     bTmp.x = -b->x;
699     bTmp.y = -b->y;
700     bTmp.z = -b->z;
701 
702     C_VECNormalize( &aTmp, &aTmp );
703     C_VECNormalize( &bTmp, &bTmp );
704 
705     C_VECAdd( &aTmp, &bTmp, &hTmp );
706 
707     if ( C_VECDotProduct( &hTmp, &hTmp ) > 0.0F )
708     {
709         C_VECNormalize( &hTmp, half );
710     }
711     else    // The singular case returns zero vector
712     {
713         *half = hTmp;
714     }
715 
716 }
717 
718 /*---------------------------------------------------------------------*
719 
720 Name:           VECReflect
721 
722 Description:    reflect a vector about a normal to a surface.
723 
724 
725 Arguments:      src        incident vector.
726 
727                 normal     normal to surface.
728 
729                 dst        normalized reflected vector.
730                            ok if dst == src
731 
732 
733 Return:         none.
734 
735  *---------------------------------------------------------------------*/
736 /*---------------------------------------------------------------------*
737     C version
738  *---------------------------------------------------------------------*/
C_VECReflect(const Vec * src,const Vec * normal,Vec * dst)739 void C_VECReflect ( const Vec *src, const Vec *normal, Vec *dst )
740 {
741     f32 cosA;
742     Vec uI, uN;
743 
744 
745     ASSERTMSG( (src != 0),     VEC_REFLECT_1  );
746     ASSERTMSG( (normal != 0),  VEC_REFLECT_2  );
747     ASSERTMSG( (dst != 0),     VEC_REFLECT_3  );
748 
749 
750     // assume src is incident to a surface.
751     // reverse direction of src so that src and normal
752     // sit tail to tail.
753     uI.x = -( src->x );
754     uI.y = -( src->y );
755     uI.z = -( src->z );
756 
757 
758     // VECNormalize will catch any zero magnitude vectors
759     C_VECNormalize( &uI,    &uI);
760     C_VECNormalize( normal, &uN);
761 
762     // angle between the unit vectors
763     cosA = C_VECDotProduct( &uI, &uN);
764 
765 
766     // R = 2N(N.I) - I
767     dst->x = (2.0f * uN.x * cosA) - uI.x;
768     dst->y = (2.0f * uN.y * cosA) - uI.y;
769     dst->z = (2.0f * uN.z * cosA) - uI.z;
770 
771     C_VECNormalize( dst, dst );
772 
773 }
774 
775 /*---------------------------------------------------------------------*
776 
777 Name:           VECSquareDistance
778 
779 Description:    Returns the square of the distance between vectors
780                 a and b.  Distance can be calculated using the
781                 square root of the returned value.
782 
783 
784 Arguments:      a     first vector.
785 
786                 b     second vector.
787 
788 
789 Return:         square distance of between vectors.
790 
791  *---------------------------------------------------------------------*/
792 /*---------------------------------------------------------------------*
793     C version
794  *---------------------------------------------------------------------*/
C_VECSquareDistance(const Vec * a,const Vec * b)795 f32 C_VECSquareDistance( const Vec *a, const Vec *b )
796 {
797     Vec diff;
798 
799     diff.x = a->x - b->x;
800     diff.y = a->y - b->y;
801     diff.z = a->z - b->z;
802 
803     return (diff.x * diff.x) + (diff.y * diff.y) + (diff.z * diff.z);
804 }
805 
806 #if !defined(WIN32) && !defined(WIN64)
807 /*---------------------------------------------------------------------*
808     Paired-Single intrinsics version
809  *---------------------------------------------------------------------*/
810 
PSVECSquareDistance(const Vec * a,const Vec * b)811 f32 PSVECSquareDistance( const Vec *a, const Vec *b )
812 {
813     f32x2    v0yz, v1yz, v0xy, v1xy;
814     f32x2    dyz, dxy, sqdist;
815 
816     v0yz = __PSQ_LX(a, 4, 0, 0);
817     v1yz = __PSQ_LX(b, 4, 0, 0);
818 
819     dyz = __PS_SUB(v0yz, v1yz); // [Y0-Y1][Z0-Z1]
820 
821     v0xy = __PSQ_L(a, 0, 0);
822     v1xy = __PSQ_L(b, 0, 0);
823 
824     dyz = __PS_MUL(dyz, dyz);              // [dYdY][dZdZ]
825     dxy = __PS_SUB(v0xy, v1xy);            // [X0-X1][Y0-Y1]
826 
827     sqdist = __PS_MADD(dxy, dxy, dyz);      // [dXdX+dYdY][dYdY+dZdZ]
828     sqdist = __PS_SUM0(sqdist, dyz, dyz);   // [dXdX+dYdY+dZdZ][N/A]
829 
830     return (f32)sqdist[0];
831 }
832 #endif
833 
834 
835 /*---------------------------------------------------------------------*
836 
837 Name:           VECDistance
838 
839 Description:    Returns the distance between vectors a and b.
840 
841 
842 Arguments:      a     first vector.
843 
844                 b     second vector.
845 
846 
847 Return:         distance between the two vectors.
848 
849  *---------------------------------------------------------------------*/
850 /*---------------------------------------------------------------------*
851     C version
852  *---------------------------------------------------------------------*/
C_VECDistance(const Vec * a,const Vec * b)853 f32 C_VECDistance( const Vec *a, const Vec *b )
854 {
855     return sqrtf( C_VECSquareDistance( a, b ) );
856 }
857 
858 #if !defined(WIN32) && !defined(WIN64)
859 /*---------------------------------------------------------------------*
860     Paired-Single intrinsics version
861  *---------------------------------------------------------------------*/
PSVECDistance(const Vec * a,const Vec * b)862 f32 PSVECDistance( const Vec *a, const Vec *b )
863 {
864     f32x2    v0yz, v1yz, v0xy, v1xy;
865     f32x2    dyz, dxy, sqdist, rdist;
866     f32x2    nwork0, nwork1;
867 
868     //psq_l       v0yz, 4(a), 0, 0           // [Y0][Z0]
869     v0yz = __PSQ_LX(a, 4, 0, 0);
870 
871     //psq_l       v1yz, 4(b), 0, 0           // [Y1][Z1]
872     v1yz = __PSQ_LX(b, 4, 0, 0);
873 
874     //ps_sub      dyz, v0yz, v1yz            // [Y0-Y1][Z0-Z1]
875     dyz = __PS_SUB(v0yz, v1yz);
876 
877     //psq_l       v0xy, 0(a), 0, 0           // [X0][Y0]
878     v0xy = __PSQ_L(a, 0, 0);
879 
880     //psq_l       v1xy, 0(b), 0, 0           // [X1][Y1]
881     v1xy = __PSQ_L(b, 0, 0);
882 
883     //ps_mul      dyz, dyz, dyz              // [dYdY][dZdZ]
884     dyz = __PS_MUL(dyz, dyz);
885 
886     //ps_sub      dxy, v0xy, v1xy            // [X0-X1][Y0-Y1]
887     dxy = __PS_SUB(v0xy, v1xy);
888 
889     //ps_madd     sqdist, dxy, dxy, dyz      // [dXdX+dYdY][dYdY+dZdZ]
890     sqdist = __PS_MADD(dxy, dxy, dyz);
891 
892     //ps_sum0     sqdist, sqdist, dyz, dyz   // [dXdX+dYdY+dZdZ][N/A]
893     sqdist = __PS_SUM0(sqdist, dyz, dyz);
894 
895     if (sqdist[0] != 0)
896     {
897         // 1.0/sqrt : estimation[E]
898         //frsqrte     rdist, sqdist
899         rdist = __PS_RSQRTE(sqdist);
900 
901         // Refinement x 1 : E' = (E/2)(3 - X*E*E)
902         //fmul        nwork0, rsqmag, rsqmag
903         nwork0 = __PS_MUL(rdist, rdist);
904 
905         //fmul        nwork1, rsqmag, c_half
906         nwork1 = __PS_MUL(rdist, c_half);
907 
908         //fnmsub      nwork0, nwork0, mag, c_three
909         nwork0 = __PS_NMSUB(nwork0, sqdist, c_three);
910 
911         //fmul        rsqmag, nwork0, nwork1
912         rdist = __PS_MUL(nwork0, nwork1);
913 
914         // 1/sqrt(X) * X = sqrt(X)
915         //fmuls       sqdist, sqdist, rdist
916         sqdist = __PS_MUL(sqdist, rdist);
917     }
918 
919     return (f32)sqdist[0];
920 }
921 #endif
922 
923 
924 /*---------------------------------------------------------------------*
925 
926 Name:           MTXMultVec
927 
928 Description:    multiplies a vector by a matrix.
929                 m x src = dst.
930 
931 
932 Arguments:      m         matrix.
933                 src       source vector for multiply.
934                 dst       resultant vector from multiply.
935 
936                 note:      ok if src == dst.
937 
938 
939 Return:         none
940 
941 *---------------------------------------------------------------------*/
942 /*---------------------------------------------------------------------*
943     C version
944  *---------------------------------------------------------------------*/
C_MTXMultVec(MTX_CONST Mtx m,const Vec * src,Vec * dst)945 void C_MTXMultVec ( MTX_CONST Mtx m, const Vec *src, Vec *dst )
946 {
947     Vec vTmp;
948 
949     ASSERTMSG( (m   != 0), MTX_MULTVEC_1 );
950     ASSERTMSG( (src != 0), MTX_MULTVEC_2 );
951     ASSERTMSG( (dst != 0), MTX_MULTVEC_3 );
952 
953     // a Vec has a 4th implicit 'w' coordinate of 1
954     vTmp.x = m[0][0]*src->x + m[0][1]*src->y + m[0][2]*src->z + m[0][3];
955     vTmp.y = m[1][0]*src->x + m[1][1]*src->y + m[1][2]*src->z + m[1][3];
956     vTmp.z = m[2][0]*src->x + m[2][1]*src->y + m[2][2]*src->z + m[2][3];
957 
958     // copy back
959     dst->x = vTmp.x;
960     dst->y = vTmp.y;
961     dst->z = vTmp.z;
962 }
963 
964 #if !defined(WIN32) && !defined(WIN64)
965 /*---------------------------------------------------------------------*
966     Paired-Single intrinsics version
967  *---------------------------------------------------------------------*
968                 Note that NO error checking is performed.
969  *---------------------------------------------------------------------*/
970 
PSMTXMultVec(MTX_CONST Mtx m,const Vec * src,Vec * dst)971 void PSMTXMultVec ( MTX_CONST Mtx m, const Vec *src, Vec *dst )
972 {
973     f32x2 fp0, fp1, fp2, fp3, fp4, fp5, fp6, fp8, fp9, fp10, fp11, fp12; // fp7,
974     const f32x2 zero = {0.0, 0.0};
975 
976     // load v[0], v[1]
977     fp0 = __PSQ_L(src, 0, 0);
978 
979     // load m[0][0], m[0][1]
980     fp2 = __PSQ_L(m, 0, 0);
981 
982     // load v[2], 1
983     //fp1[0]=src->z;
984     //fp1[1]=1.0F;
985     fp1 = __PSQ_LX(src, 8, 1, 0);
986 
987     // m[0][0]*v[0], m[0][1]*v[1]
988     fp4 = __PS_MUL(fp2, fp0);
989 
990     // load m[0][2], m[0][3]
991     fp3 = __PSQ_LX(m, 8, 0, 0);
992 
993     // m[0][0]*v[0]+m[0][2]*v[2], m[0][1]*v[1]+m[0][3]
994     fp5 = __PS_MADD(fp3, fp1, fp4);
995 
996     // load m[1][0], m[1][1]
997     fp8 = __PSQ_LX(m, 16, 0, 0);
998     fp6 = zero;
999 
1000     // m[0][0]*v[0]+m[0][2]*v[2]+m[0][1]*v[1]+m[0][3], ???
1001     fp6 = __PS_SUM0(fp5, fp6, fp5);
1002 
1003     // load m[1][2], m[1][3]
1004     fp9 = __PSQ_LX(m, 24, 0, 0);
1005 
1006     // m[1][0]*v[0], m[1][1]*v[1]
1007     fp10 = __PS_MUL(fp8, fp0);
1008 
1009     // store dst[0]
1010     __PSQ_ST(dst, fp6, 1, 0);
1011 
1012     // m[1][0]*v[0]+m[1][2]*v[2], m[1][1]*v[1]+m[1][3]
1013     fp11 = __PS_MADD(fp9, fp1, fp10);
1014 
1015     // load m[2][0], m[2][1]
1016     fp2 = __PSQ_LX(m, 32, 0, 0);
1017     fp12 = zero;
1018 
1019     // m[1][0]*v[0]+m[1][2]*v[2]+m[2][1]*v[1]+m[1][3], ???
1020     fp12 = __PS_SUM0(fp11, fp12, fp11);
1021 
1022     // load m[2][2], m[2][3]
1023     fp3 = __PSQ_LX(m, 40, 0, 0);
1024 
1025     // m[0][0]*v[0], m[0][1]*v[1]
1026     fp4 = __PS_MUL(fp2, fp0);
1027 
1028     // store dst[1]
1029     __PSQ_STX(dst, 4, fp12, 1, 0);
1030 
1031     // m[0][0]*v[0]+m[0][2]*v[2], m[0][1]*v[1]+m[0][3]
1032     fp5 = __PS_MADD(fp3, fp1, fp4);
1033     fp6 = zero;
1034 
1035     // m[0][0]*v[0]+m[0][2]*v[2]+m[0][1]*v[1]+m[0][3], ???
1036     fp6 = __PS_SUM0(fp5, fp6, fp5);
1037 
1038     // store dst[2]
1039     __PSQ_STX(dst, 8, fp6, 1, 0);
1040 }
1041 #endif
1042 
1043 /*---------------------------------------------------------------------*
1044 
1045 Name:           MTXMultVecArray
1046 
1047 Description:    multiplies an array of vectors by a matrix.
1048 
1049 
1050 Arguments:      m         matrix.
1051                 srcBase   start of source vector array.
1052                 dstBase   start of resultant vector array.
1053 
1054                 note:     ok if srcBase == dstBase.
1055 
1056                 count     number of vectors in srcBase, dstBase arrays
1057                           note:      cannot check for array overflow
1058 
1059 Return:         none
1060 
1061 *---------------------------------------------------------------------*/
1062 /*---------------------------------------------------------------------*
1063     C version
1064  *---------------------------------------------------------------------*/
C_MTXMultVecArray(MTX_CONST Mtx m,const Vec * srcBase,Vec * dstBase,u32 count)1065 void C_MTXMultVecArray ( MTX_CONST Mtx m, const Vec *srcBase, Vec *dstBase, u32 count )
1066 {
1067     u32 i;
1068     Vec vTmp;
1069 
1070     ASSERTMSG( (m       != 0), MTX_MULTVECARRAY_1 );
1071     ASSERTMSG( (srcBase != 0), MTX_MULTVECARRAY_2 );
1072     ASSERTMSG( (dstBase != 0), MTX_MULTVECARRAY_3 );
1073     ASSERTMSG( (count > 1),    MTX_MULTVECARRAY_4 );
1074 
1075     for(i=0; i< count; i++)
1076     {
1077         // Vec has a 4th implicit 'w' coordinate of 1
1078         vTmp.x = m[0][0]*srcBase->x + m[0][1]*srcBase->y + m[0][2]*srcBase->z + m[0][3];
1079         vTmp.y = m[1][0]*srcBase->x + m[1][1]*srcBase->y + m[1][2]*srcBase->z + m[1][3];
1080         vTmp.z = m[2][0]*srcBase->x + m[2][1]*srcBase->y + m[2][2]*srcBase->z + m[2][3];
1081 
1082         // copy back
1083         dstBase->x = vTmp.x;
1084         dstBase->y = vTmp.y;
1085         dstBase->z = vTmp.z;
1086 
1087         srcBase++;
1088         dstBase++;
1089     }
1090 }
1091 
1092 #if !defined(WIN32) && !defined(WIN64)
1093 /*---------------------------------------------------------------------*
1094     Paired-Single intrinsics version
1095  *---------------------------------------------------------------------*
1096                 Note that NO error checking is performed.
1097 
1098                 The count should be greater than 1.
1099  *---------------------------------------------------------------------*/
1100 
PSMTXMultVecArray(MTX_CONST Mtx m,const Vec * srcBase,Vec * dstBase,u32 count)1101 void PSMTXMultVecArray ( MTX_CONST Mtx m, const Vec *srcBase, Vec *dstBase, u32 count )
1102 {
1103     u32 i;
1104 
1105     for ( i = 0 ; i < count ; i++ )
1106     {
1107         PSMTXMultVec(m, srcBase, dstBase);
1108 
1109         srcBase++;
1110         dstBase++;
1111     }
1112 }
1113 #endif
1114 
1115 /*---------------------------------------------------------------------*
1116 
1117 Name:         MTXMultVecSR
1118 
1119 Description:  multiplies a vector by a matrix 3x3 (Scaling and Rotation)
1120               component.
1121 
1122               m x src = dst.
1123 
1124 Arguments:    m       matrix.
1125               src     source vector for multiply.
1126               dst     resultant vector from multiply.
1127 
1128               note:   ok if src == dst.
1129 
1130 Return:       none
1131 
1132 *---------------------------------------------------------------------*/
1133 /*---------------------------------------------------------------------*
1134     C version
1135  *---------------------------------------------------------------------*/
C_MTXMultVecSR(MTX_CONST Mtx m,const Vec * src,Vec * dst)1136 void C_MTXMultVecSR ( MTX_CONST Mtx m, const Vec *src, Vec *dst )
1137 {
1138     Vec vTmp;
1139 
1140     ASSERTMSG( (m   != 0), MTX_MULTVECSR_1 );
1141     ASSERTMSG( (src != 0), MTX_MULTVECSR_2 );
1142     ASSERTMSG( (dst != 0), MTX_MULTVECSR_3 );
1143 
1144     // a Vec has a 4th implicit 'w' coordinate of 1
1145     vTmp.x = m[0][0]*src->x + m[0][1]*src->y + m[0][2]*src->z;
1146     vTmp.y = m[1][0]*src->x + m[1][1]*src->y + m[1][2]*src->z;
1147     vTmp.z = m[2][0]*src->x + m[2][1]*src->y + m[2][2]*src->z;
1148 
1149     // copy back
1150     dst->x = vTmp.x;
1151     dst->y = vTmp.y;
1152     dst->z = vTmp.z;
1153 }
1154 
1155 #if !defined(WIN32) && !defined(WIN64)
1156 /*---------------------------------------------------------------------*
1157     Paired-Single intrinsics version
1158  *---------------------------------------------------------------------*
1159                 Note that this performs NO error checking.
1160  *---------------------------------------------------------------------*/
1161 
PSMTXMultVecSR(MTX_CONST Mtx m,const Vec * src,Vec * dst)1162 void PSMTXMultVecSR ( MTX_CONST Mtx m, const Vec *src, Vec *dst )
1163 {
1164     f32x2 fp0, fp1, fp2, fp3, fp4, fp5, fp6, fp7, fp8, fp9, fp10, fp11, fp12, fp13;
1165 
1166     // m[0][0], m[0][1]
1167     fp0 = __PSQ_L(m, 0, 0);
1168 
1169     // fp6 - x y
1170     fp6 = __PSQ_L(src, 0, 0);
1171 
1172     // m[1][0], m[1][1]
1173     fp2 = __PSQ_LX(m, 16, 0, 0);
1174 
1175     // fp8 = m00x m01y // next X
1176     fp8 = __PS_MUL(fp0, fp6);
1177 
1178     // m[2][0], m[2][1]
1179     fp4 = __PSQ_LX(m, 32, 0, 0);
1180 
1181     // fp10 = m10x m11y // next Y
1182     fp10 = __PS_MUL(fp2, fp6);
1183 
1184     // fp7 - z,1.0
1185     //fp7[0] = src->z;
1186     //fp7[1] = 1.0F;
1187     fp7 = __PSQ_LX(src, 8, 1, 0);
1188 
1189     // fp12 = m20x m21y // next Z
1190     fp12 = __PS_MUL(fp4, fp6);
1191 
1192     // m[1][2], m[1][3]
1193     fp3 = __PSQ_LX(m, 24, 0, 0);
1194 
1195     fp8 = __PS_SUM0(fp8, fp8, fp8);
1196 
1197     // m[2][2], m[2][3]
1198     fp5 = __PSQ_LX(m, 40, 0, 0);
1199 
1200     fp10 = __PS_SUM0(fp10, fp10, fp10);
1201 
1202     // m[0][2], m[0][3]
1203     fp1 = __PSQ_LX(m, 8, 0, 0);
1204 
1205     fp12 = __PS_SUM0(fp12, fp12, fp12);
1206     fp9 = __PS_MADD(fp1, fp7, fp8);
1207 
1208     // store X
1209     __PSQ_ST(dst, fp9, 1, 0);
1210 
1211     fp11 = __PS_MADD(fp3, fp7, fp10);
1212 
1213     // store Y
1214     __PSQ_STX(dst, 4, fp11, 1, 0);
1215 
1216     fp13 = __PS_MADD(fp5, fp7, fp12);
1217 
1218     //  store Z
1219     __PSQ_STX(dst, 8, fp13, 1, 0);
1220 }
1221 #endif
1222 
1223 /*---------------------------------------------------------------------*
1224 
1225 Name:           MTXMultVecArraySR
1226 
1227 Description:    multiplies an array of vectors by a matrix 3x3
1228                 (Scaling and Rotation) component.
1229 
1230 Arguments:      m        matrix.
1231                 srcBase  start of source vector array.
1232                 dstBase  start of resultant vector array.
1233 
1234                 note:    ok if srcBase == dstBase.
1235 
1236                 count    number of vectors in srcBase, dstBase arrays
1237                 note:    cannot check for array overflow
1238 
1239 Return:         none
1240 
1241 *---------------------------------------------------------------------*/
1242 /*---------------------------------------------------------------------*
1243     C version
1244  *---------------------------------------------------------------------*/
C_MTXMultVecArraySR(MTX_CONST Mtx m,const Vec * srcBase,Vec * dstBase,u32 count)1245 void C_MTXMultVecArraySR ( MTX_CONST Mtx m, const Vec *srcBase, Vec *dstBase, u32 count )
1246 {
1247     u32 i;
1248     Vec vTmp;
1249 
1250     ASSERTMSG( (m       != 0), MTX_MULTVECARRAYSR_1 );
1251     ASSERTMSG( (srcBase != 0), MTX_MULTVECARRAYSR_2 );
1252     ASSERTMSG( (dstBase != 0), MTX_MULTVECARRAYSR_3 );
1253     ASSERTMSG( (count > 1),    MTX_MULTVECARRAYSR_4 );
1254 
1255     for ( i = 0; i < count; i ++ )
1256     {
1257         // Vec has a 4th implicit 'w' coordinate of 1
1258         vTmp.x = m[0][0]*srcBase->x + m[0][1]*srcBase->y + m[0][2]*srcBase->z;
1259         vTmp.y = m[1][0]*srcBase->x + m[1][1]*srcBase->y + m[1][2]*srcBase->z;
1260         vTmp.z = m[2][0]*srcBase->x + m[2][1]*srcBase->y + m[2][2]*srcBase->z;
1261 
1262         // copy back
1263         dstBase->x = vTmp.x;
1264         dstBase->y = vTmp.y;
1265         dstBase->z = vTmp.z;
1266 
1267         srcBase++;
1268         dstBase++;
1269     }
1270 }
1271 
1272 #if !defined(WIN32) && !defined(WIN64)
1273 /*---------------------------------------------------------------------*
1274     Paired-Single intrinsics version
1275  *---------------------------------------------------------------------*
1276                 Note that NO error checking is performed.
1277  *---------------------------------------------------------------------*/
1278 
PSMTXMultVecArraySR(MTX_CONST Mtx m,const Vec * srcBase,Vec * dstBase,u32 count)1279 void PSMTXMultVecArraySR ( MTX_CONST Mtx m, const Vec *srcBase, Vec *dstBase, u32 count )
1280 {
1281     u32 i;
1282 
1283     for ( i = 0 ; i < count ; i++ )
1284     {
1285         PSMTXMultVecSR(m, srcBase, dstBase);
1286 
1287         srcBase++;
1288         dstBase++;
1289     }
1290 }
1291 #endif
1292 
1293 
1294 /*---------------------------------------------------------------------*
1295 
1296 Name:           MTXROMultVecArray
1297 
1298 Description:    Multiplies an array of vectors by a reordered matrix,
1299                 using paired single operations.
1300                 OK if source = destination.
1301                 NOTE: number of vertices transformed cannot be less than
1302                 2.
1303 
1304                 Note that NO error checking is performed.
1305 
1306 Arguments:      m         reordered matrix.
1307                 srcBase   start of source vector array.
1308                 dstBase   start of resultant vector array.
1309                 count     number of vectors in srcBase, dstBase arrays
1310                           COUNT MUST BE GREATER THAN 2.
1311 
1312 
1313 Return:         none
1314 
1315 *---------------------------------------------------------------------*/
1316 /*---------------------------------------------------------------------*
1317     C version
1318  *---------------------------------------------------------------------*/
C_MTXROMultVecArray(MTX_CONST ROMtx m,const Vec * srcBase,Vec * dstBase,u32 count)1319 void C_MTXROMultVecArray
1320 (
1321     MTX_CONST ROMtx  m,      // r3
1322     const Vec   *srcBase,// r4
1323     Vec   *dstBase,// r5
1324     u32    count   // r6
1325 )
1326 {
1327     u32 i;
1328     Vec vTmp;
1329 
1330     ASSERTMSG( (m       != 0), MTX_MULTVECARRAY_1 );
1331     ASSERTMSG( (srcBase != 0), MTX_MULTVECARRAY_2 );
1332     ASSERTMSG( (dstBase != 0), MTX_MULTVECARRAY_3 );
1333     ASSERTMSG( (count > 1),    MTX_MULTVECARRAY_4 );
1334 
1335     for(i=0; i< count; i++)
1336     {
1337         // Vec has a 4th implicit 'w' coordinate of 1
1338         vTmp.x = m[0][0]*srcBase->x + m[1][0]*srcBase->y + m[2][0]*srcBase->z + m[3][0];
1339         vTmp.y = m[0][1]*srcBase->x + m[1][1]*srcBase->y + m[2][1]*srcBase->z + m[3][1];
1340         vTmp.z = m[0][2]*srcBase->x + m[1][2]*srcBase->y + m[2][2]*srcBase->z + m[3][2];
1341 
1342         // copy back
1343         dstBase->x = vTmp.x;
1344         dstBase->y = vTmp.y;
1345         dstBase->z = vTmp.z;
1346 
1347         srcBase++;
1348         dstBase++;
1349     }
1350 }
1351 /*===========================================================================*/
1352