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