3 // Copyright (C) 1998-2007 Marti Maria
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the Software
10 // is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
17 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Vector & Matrix stuff
28 void cdecl VEC3init(LPVEC3 r
, double x
, double y
, double z
);
29 void cdecl VEC3initF(LPWVEC3 r
, double x
, double y
, double z
);
30 void cdecl VEC3toFix(LPWVEC3 r
, LPVEC3 v
);
31 void cdecl VEC3toFloat(LPFVEC3 r
, LPVEC3 v
);
32 void cdecl VEC3scaleFix(LPWORD r
, LPWVEC3 Scale
);
33 void cdecl VEC3swap(LPVEC3 a
, LPVEC3 b
);
34 void cdecl VEC3divK(LPVEC3 r
, LPVEC3 v
, double d
);
35 void cdecl VEC3perK(LPVEC3 r
, LPVEC3 v
, double d
);
36 void cdecl VEC3perComp(LPVEC3 r
, LPVEC3 a
, LPVEC3 b
);
37 void cdecl VEC3minus(LPVEC3 r
, LPVEC3 a
, LPVEC3 b
);
38 void cdecl VEC3scaleAndCut(LPWVEC3 r
, LPVEC3 v
, double d
);
39 void cdecl VEC3cross(LPVEC3 r
, LPVEC3 u
, LPVEC3 v
);
40 void cdecl VEC3saturate(LPVEC3 v
);
42 double cdecl VEC3length(LPVEC3 a
);
43 double cdecl VEC3distance(LPVEC3 a
, LPVEC3 b
);
46 void cdecl MAT3identity(LPMAT3 a
);
47 void cdecl MAT3per(LPMAT3 r
, LPMAT3 a
, LPMAT3 b
);
48 int cdecl MAT3inverse(LPMAT3 a
, LPMAT3 b
);
49 LCMSBOOL
cdecl MAT3solve(LPVEC3 x
, LPMAT3 a
, LPVEC3 b
);
50 double cdecl MAT3det(LPMAT3 m
);
51 void cdecl MAT3eval(LPVEC3 r
, LPMAT3 a
, LPVEC3 v
);
52 void cdecl MAT3toFix(LPWMAT3 r
, LPMAT3 v
);
53 void cdecl MAT3toFloat(LPFMAT3 r
, LPMAT3 v
);
54 void cdecl MAT3toFloatTranspose(LPFMAT3 r
, LPMAT3 v
);
55 void cdecl MAT3evalW(LPWVEC3 r
, LPWMAT3 a
, LPWVEC3 v
);
56 void cdecl MAT3perK(LPMAT3 r
, LPMAT3 v
, double d
);
57 void cdecl MAT3scaleAndCut(LPWMAT3 r
, LPMAT3 v
, double d
);
59 // --------------------- Implementation ----------------------------
61 #define DSWAP(x, y) {double tmp = (x); (x)=(y); (y)=tmp;}
69 #pragma warning(disable : 4033)
70 #pragma warning(disable : 4035)
75 Fixed32
FixedMul(Fixed32 a
, Fixed32 b
)
94 Fixed32
FixedSquare(Fixed32 a
)
115 // Linear intERPolation
116 // a * (h - l) >> 16 + l
118 Fixed32
FixedLERP(Fixed32 a
, Fixed32 l
, Fixed32 h
)
121 mov eax
, dword ptr ss
:h
122 mov edx
, dword ptr ss
:l
124 mov ecx
, dword ptr ss
:a
138 // a as word is scaled by s as float
140 WORD
FixedScale(WORD a
, Fixed32 s
)
145 mov ax
, ss
:a
// This is faster that movzx eax, ss:a
158 #pragma warning(default : 4033)
159 #pragma warning(default : 4035)
165 // These are floating point versions for compilers that doesn't
166 // support asm at all. Use with care, since this will slow down
170 Fixed32
FixedMul(Fixed32 a
, Fixed32 b
)
173 LCMSULONGLONG l
= (LCMSULONGLONG
) (LCMSSLONGLONG
) a
* (LCMSULONGLONG
) (LCMSSLONGLONG
) b
+ (LCMSULONGLONG
) 0x8000;
177 return DOUBLE_TO_FIXED(FIXED_TO_DOUBLE(a
) * FIXED_TO_DOUBLE(b
));
181 Fixed32
FixedSquare(Fixed32 a
)
183 return FixedMul(a
, a
);
187 Fixed32
FixedLERP(Fixed32 a
, Fixed32 l
, Fixed32 h
)
191 LCMSULONGLONG dif
= (LCMSULONGLONG
) (h
- l
) * a
+ 0x8000;
192 dif
= (dif
>> 16) + l
;
193 return (Fixed32
) (dif
);
201 return (Fixed32
) (dif
+ 0.5);
207 WORD
FixedScale(WORD a
, Fixed32 s
)
209 return (WORD
) (a
* FIXED_TO_DOUBLE(s
));
217 Fixed32
ToFixedDomain(int a
)
219 return a
+ ((a
+ 0x7fff) / 0xffff);
223 int FromFixedDomain(Fixed32 a
)
225 return a
- ((a
+ 0x7fff) >> 16);
229 Float
ToFloatDomain(int a
)
231 return ((float) a
)/65536f
;
234 int FromFloatDomain(Float a
)
236 return (int) (a
* 65536f
);
242 // Helper function to set up the alignment for LPFMAT3A
243 void FMAT3ASetup(LPFMAT3A m
)
245 m
-> F
= (LPFMAT3
) (m
-> _Buffer
+ (16 - (((unsigned) m
-> _Buffer
) % 16)));
249 // Initiate a vector (double version)
252 void VEC3init(LPVEC3 r
, double x
, double y
, double z
)
259 // Init a vector (fixed version)
261 void VEC3initF(LPWVEC3 r
, double x
, double y
, double z
)
263 r
-> n
[VX
] = DOUBLE_TO_FIXED(x
);
264 r
-> n
[VY
] = DOUBLE_TO_FIXED(y
);
265 r
-> n
[VZ
] = DOUBLE_TO_FIXED(z
);
269 // Convert to fixed point encoding is 1.0 = 0xFFFF
271 void VEC3toFix(LPWVEC3 r
, LPVEC3 v
)
273 r
-> n
[VX
] = DOUBLE_TO_FIXED(v
-> n
[VX
]);
274 r
-> n
[VY
] = DOUBLE_TO_FIXED(v
-> n
[VY
]);
275 r
-> n
[VZ
] = DOUBLE_TO_FIXED(v
-> n
[VZ
]);
280 void VEC3toFloat(LPFVEC3 r
, LPVEC3 v
)
282 r
-> n
[VX
] = DOUBLE_TO_FLOAT(v
-> n
[VX
]);
283 r
-> n
[VY
] = DOUBLE_TO_FLOAT(v
-> n
[VY
]);
284 r
-> n
[VZ
] = DOUBLE_TO_FLOAT(v
-> n
[VZ
]);
287 // Convert from fixed point
289 void VEC3fromFix(LPVEC3 r
, LPWVEC3 v
)
291 r
-> n
[VX
] = FIXED_TO_DOUBLE(v
-> n
[VX
]);
292 r
-> n
[VY
] = FIXED_TO_DOUBLE(v
-> n
[VY
]);
293 r
-> n
[VZ
] = FIXED_TO_DOUBLE(v
-> n
[VZ
]);
297 // Swap two double vectors
299 void VEC3swap(LPVEC3 a
, LPVEC3 b
)
301 DSWAP(a
-> n
[VX
], b
-> n
[VX
]);
302 DSWAP(a
-> n
[VY
], b
-> n
[VY
]);
303 DSWAP(a
-> n
[VZ
], b
-> n
[VZ
]);
306 // Divide a vector by a constant
308 void VEC3divK(LPVEC3 r
, LPVEC3 v
, double d
)
312 r
-> n
[VX
] = v
-> n
[VX
] * d_inv
;
313 r
-> n
[VY
] = v
-> n
[VY
] * d_inv
;
314 r
-> n
[VZ
] = v
-> n
[VZ
] * d_inv
;
317 // Multiply by a constant
319 void VEC3perK(LPVEC3 r
, LPVEC3 v
, double d
)
321 r
-> n
[VX
] = v
-> n
[VX
] * d
;
322 r
-> n
[VY
] = v
-> n
[VY
] * d
;
323 r
-> n
[VZ
] = v
-> n
[VZ
] * d
;
327 void VEC3perComp(LPVEC3 r
, LPVEC3 a
, LPVEC3 b
)
329 r
-> n
[VX
] = a
->n
[VX
]*b
->n
[VX
];
330 r
-> n
[VY
] = a
->n
[VY
]*b
->n
[VY
];
331 r
-> n
[VZ
] = a
->n
[VZ
]*b
->n
[VZ
];
337 void VEC3minus(LPVEC3 r
, LPVEC3 a
, LPVEC3 b
)
339 r
-> n
[VX
] = a
-> n
[VX
] - b
-> n
[VX
];
340 r
-> n
[VY
] = a
-> n
[VY
] - b
-> n
[VY
];
341 r
-> n
[VZ
] = a
-> n
[VZ
] - b
-> n
[VZ
];
345 // Check id two vectors are the same, allowing tolerance
348 LCMSBOOL
RangeCheck(double l
, double h
, double v
)
350 return (v
>= l
&& v
<= h
);
354 LCMSBOOL
VEC3equal(LPWVEC3 a
, LPWVEC3 b
, double Tolerance
)
359 for (i
=0; i
< 3; i
++)
361 c
= FIXED_TO_DOUBLE(a
-> n
[i
]);
362 if (!RangeCheck(c
- Tolerance
,
364 FIXED_TO_DOUBLE(b
->n
[i
]))) return FALSE
;
370 LCMSBOOL
VEC3equalF(LPVEC3 a
, LPVEC3 b
, double Tolerance
)
375 for (i
=0; i
< 3; i
++)
378 if (!RangeCheck(c
- Tolerance
,
380 b
->n
[i
])) return FALSE
;
386 LCMSBOOL
FVEC3equal(LPFVEC3 a
, LPFVEC3 b
, float Tolerance
)
391 for (i
=0; i
< 3; i
++)
394 if (!RangeCheck(c
- Tolerance
,
396 b
->n
[i
])) return FALSE
;
403 void VEC3scaleFix(LPWORD r
, LPWVEC3 Scale
)
405 if (Scale
-> n
[VX
] == 0x00010000L
&&
406 Scale
-> n
[VY
] == 0x00010000L
&&
407 Scale
-> n
[VZ
] == 0x00010000L
) return;
409 r
[0] = (WORD
) FixedScale(r
[0], Scale
-> n
[VX
]);
410 r
[1] = (WORD
) FixedScale(r
[1], Scale
-> n
[VY
]);
411 r
[2] = (WORD
) FixedScale(r
[2], Scale
-> n
[VZ
]);
417 // Vector cross product
419 void VEC3cross(LPVEC3 r
, LPVEC3 u
, LPVEC3 v
)
422 r
->n
[VX
] = u
->n
[VY
] * v
->n
[VZ
] - v
->n
[VY
] * u
->n
[VZ
];
423 r
->n
[VY
] = u
->n
[VZ
] * v
->n
[VX
] - v
->n
[VZ
] * u
->n
[VX
];
424 r
->n
[VZ
] = u
->n
[VX
] * v
->n
[VY
] - v
->n
[VX
] * u
->n
[VY
];
431 double VEC3length(LPVEC3 a
)
433 return sqrt(a
->n
[VX
] * a
->n
[VX
] +
434 a
->n
[VY
] * a
->n
[VY
] +
435 a
->n
[VZ
] * a
->n
[VZ
]);
439 // Saturate a vector into 0..1.0 range
441 void VEC3saturate(LPVEC3 v
)
444 for (i
=0; i
< 3; i
++) {
454 // Euclidean distance
456 double VEC3distance(LPVEC3 a
, LPVEC3 b
)
458 double d1
= a
->n
[VX
] - b
->n
[VX
];
459 double d2
= a
->n
[VY
] - b
->n
[VY
];
460 double d3
= a
->n
[VZ
] - b
->n
[VZ
];
462 return sqrt(d1
*d1
+ d2
*d2
+ d3
*d3
);
469 void MAT3identity(LPMAT3 a
)
471 VEC3init(&a
-> v
[0], 1.0, 0.0, 0.0);
472 VEC3init(&a
-> v
[1], 0.0, 1.0, 0.0);
473 VEC3init(&a
-> v
[2], 0.0, 0.0, 1.0);
479 // Check if matrix is Identity. Allow a tolerance as %
481 LCMSBOOL
MAT3isIdentity(LPWMAT3 a
, double Tolerance
)
488 MAT3toFix(&Idf
, &Idd
);
490 for (i
=0; i
< 3; i
++)
491 if (!VEC3equal(&a
-> v
[i
], &Idf
.v
[i
], Tolerance
)) return FALSE
;
497 // Floating point version of the above.
499 LCMSBOOL
FMAT3isIdentity(LPFMAT3 a
, float Tolerance
)
506 MAT3toFloat(&Idf
, &Idd
);
508 for (i
=0; i
< 3; i
++)
509 if (!FVEC3equal(&a
-> v
[i
], &Idf
.v
[i
], Tolerance
)) return FALSE
;
514 // Multiply two matrices
517 void MAT3per(LPMAT3 r
, LPMAT3 a
, LPMAT3 b
)
519 #define ROWCOL(i, j) \
520 a->v[i].n[0]*b->v[0].n[j] + a->v[i].n[1]*b->v[1].n[j] + a->v[i].n[2]*b->v[2].n[j]
522 VEC3init(&r
-> v
[0], ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2));
523 VEC3init(&r
-> v
[1], ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2));
524 VEC3init(&r
-> v
[2], ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2));
526 #undef ROWCOL //(i, j)
531 // Inverse of a matrix b = a^(-1)
532 // Gauss-Jordan elimination with partial pivoting
534 int MAT3inverse(LPMAT3 a
, LPMAT3 b
)
536 register int i
, j
, max
;
540 // Loop over cols of a from left to right, eliminating above and below diag
541 for (j
=0; j
<3; j
++) { // Find largest pivot in column j among rows j..2
543 max
= j
; // Row with largest pivot candidate
544 for (i
=j
+1; i
<3; i
++)
545 if (fabs(a
-> v
[i
].n
[j
]) > fabs(a
-> v
[max
].n
[j
]))
548 // Swap rows max and j in a and b to put pivot on diagonal
550 VEC3swap(&a
-> v
[max
], &a
-> v
[j
]);
551 VEC3swap(&b
-> v
[max
], &b
-> v
[j
]);
553 // Scale row j to have a unit diagonal
555 if (a
-> v
[j
].n
[j
]==0.)
556 return -1; // singular matrix; can't invert
558 VEC3divK(&b
-> v
[j
], &b
-> v
[j
], a
->v
[j
].n
[j
]);
559 VEC3divK(&a
-> v
[j
], &a
-> v
[j
], a
->v
[j
].n
[j
]);
561 // Eliminate off-diagonal elems in col j of a, doing identical ops to b
567 VEC3perK(&temp
, &b
-> v
[j
], a
-> v
[i
].n
[j
]);
568 VEC3minus(&b
-> v
[i
], &b
-> v
[i
], &temp
);
570 VEC3perK(&temp
, &a
-> v
[j
], a
-> v
[i
].n
[j
]);
571 VEC3minus(&a
-> v
[i
], &a
-> v
[i
], &temp
);
579 // Solve a system in the form Ax = b
581 LCMSBOOL
MAT3solve(LPVEC3 x
, LPMAT3 a
, LPVEC3 b
)
585 CopyMemory(&m
, a
, sizeof(MAT3
));
587 if (!MAT3inverse(&m
, &a_1
)) return FALSE
; // Singular matrix
589 MAT3eval(x
, &a_1
, b
);
596 double MAT3det(LPMAT3 m
)
599 double a1
= m
->v
[VX
].n
[VX
];
600 double a2
= m
->v
[VX
].n
[VY
];
601 double a3
= m
->v
[VX
].n
[VZ
];
602 double b1
= m
->v
[VY
].n
[VX
];
603 double b2
= m
->v
[VY
].n
[VY
];
604 double b3
= m
->v
[VY
].n
[VZ
];
605 double c1
= m
->v
[VZ
].n
[VX
];
606 double c2
= m
->v
[VZ
].n
[VY
];
607 double c3
= m
->v
[VZ
].n
[VZ
];
610 return a1
*b2
*c3
- a1
*b3
*c2
+ a2
*b3
*c1
- a2
*b1
*c3
- a3
*b1
*c2
- a3
*b2
*c1
;
617 void MAT3eval(LPVEC3 r
, LPMAT3 a
, LPVEC3 v
)
619 r
->n
[VX
] = a
->v
[0].n
[VX
]*v
->n
[VX
] + a
->v
[0].n
[VY
]*v
->n
[VY
] + a
->v
[0].n
[VZ
]*v
->n
[VZ
];
620 r
->n
[VY
] = a
->v
[1].n
[VX
]*v
->n
[VX
] + a
->v
[1].n
[VY
]*v
->n
[VY
] + a
->v
[1].n
[VZ
]*v
->n
[VZ
];
621 r
->n
[VZ
] = a
->v
[2].n
[VX
]*v
->n
[VX
] + a
->v
[2].n
[VY
]*v
->n
[VY
] + a
->v
[2].n
[VZ
]*v
->n
[VZ
];
624 void MAT3evalF(LPFVEC3 r
, LPFMAT3 a
, LPFVEC3 v
)
626 r
->n
[VX
] = a
->v
[0].n
[VX
]*v
->n
[VX
] + a
->v
[0].n
[VY
]*v
->n
[VY
] + a
->v
[0].n
[VZ
]*v
->n
[VZ
];
627 r
->n
[VY
] = a
->v
[1].n
[VX
]*v
->n
[VX
] + a
->v
[1].n
[VY
]*v
->n
[VY
] + a
->v
[1].n
[VZ
]*v
->n
[VZ
];
628 r
->n
[VZ
] = a
->v
[2].n
[VX
]*v
->n
[VX
] + a
->v
[2].n
[VY
]*v
->n
[VY
] + a
->v
[2].n
[VZ
]*v
->n
[VZ
];
632 // Ok, this is another bottleneck of performance.
637 // ecx:ebx is result in 64 bits format
638 // edi points to matrix, esi points to input vector
639 // since only 3 accesses are in output, this is a stack variable
642 void MAT3evalW(LPWVEC3 r_
, LPWMAT3 a_
, LPWVEC3 v_
)
648 mov esi
, dword ptr ss
:v_
649 mov edi
, dword ptr ss
:a_
651 // r->n[VX] = FixedMul(a->v[0].n[0], v->n[0]) +
653 mov eax
,dword ptr
[esi
]
654 mov edx
,dword ptr
[edi
]
659 // FixedMul(a->v[0].n[1], v->n[1]) +
661 mov eax
,dword ptr
[esi
+4]
662 mov edx
,dword ptr
[edi
+4]
667 // FixedMul(a->v[0].n[2], v->n[2]);
669 mov eax
,dword ptr
[esi
+8]
670 mov edx
,dword ptr
[edi
+8]
675 // Back to Fixed 15.16
682 mov edi
, dword ptr ss
:r_
683 mov dword ptr
[edi
], ecx
// r -> n[VX]
688 // 2nd row ***************************
690 // FixedMul(a->v[1].n[0], v->n[0])
692 mov eax
,dword ptr
[esi
]
693 mov edx
,dword ptr
[edi
+12]
698 // FixedMul(a->v[1].n[1], v->n[1]) +
700 mov eax
,dword ptr
[esi
+4]
701 mov edx
,dword ptr
[edi
+16]
706 // FixedMul(a->v[1].n[2], v->n[2]);
708 mov eax
,dword ptr
[esi
+8]
709 mov edx
,dword ptr
[edi
+20]
719 mov edi
, dword ptr ss
:r_
720 mov dword ptr
[edi
+4], ecx
// r -> n[VY]
723 // 3d row **************************
725 // r->n[VZ] = FixedMul(a->v[2].n[0], v->n[0]) +
727 mov eax
,dword ptr
[esi
]
728 mov edx
,dword ptr
[edi
+24]
733 // FixedMul(a->v[2].n[1], v->n[1]) +
735 mov eax
,dword ptr
[esi
+4]
736 mov edx
,dword ptr
[edi
+28]
741 // FixedMul(a->v[2].n[2], v->n[2]);
743 mov eax
,dword ptr
[esi
+8]
744 mov edx
,dword ptr
[edi
+32]
753 mov edi
, dword ptr ss
:r_
754 mov dword ptr
[edi
+8], ecx
// r -> n[VZ]
764 void MAT3evalW(LPWVEC3 r
, LPWMAT3 a
, LPWVEC3 v
)
766 r
->n
[VX
] = DOUBLE_TO_FIXED(
767 FIXED_TO_DOUBLE(a
->v
[0].n
[0]) * FIXED_TO_DOUBLE(v
->n
[0]) +
768 FIXED_TO_DOUBLE(a
->v
[0].n
[1]) * FIXED_TO_DOUBLE(v
->n
[1]) +
769 FIXED_TO_DOUBLE(a
->v
[0].n
[2]) * FIXED_TO_DOUBLE(v
->n
[2])
772 r
->n
[VY
] = DOUBLE_TO_FIXED(
773 FIXED_TO_DOUBLE(a
->v
[1].n
[0]) * FIXED_TO_DOUBLE(v
->n
[0]) +
774 FIXED_TO_DOUBLE(a
->v
[1].n
[1]) * FIXED_TO_DOUBLE(v
->n
[1]) +
775 FIXED_TO_DOUBLE(a
->v
[1].n
[2]) * FIXED_TO_DOUBLE(v
->n
[2])
778 r
->n
[VZ
] = DOUBLE_TO_FIXED(
779 FIXED_TO_DOUBLE(a
->v
[2].n
[0]) * FIXED_TO_DOUBLE(v
->n
[0]) +
780 FIXED_TO_DOUBLE(a
->v
[2].n
[1]) * FIXED_TO_DOUBLE(v
->n
[1]) +
781 FIXED_TO_DOUBLE(a
->v
[2].n
[2]) * FIXED_TO_DOUBLE(v
->n
[2])
788 void MAT3evalW(LPWVEC3 r
, LPWMAT3 a
, LPWVEC3 v
)
793 LCMSULONGLONG l1
= (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[0].n
[0] *
794 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[0] +
795 (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[0].n
[1] *
796 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[1] +
797 (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[0].n
[2] *
798 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[2] + (LCMSULONGLONG
) 0x8000;
800 LCMSULONGLONG l2
= (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[1].n
[0] *
801 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[0] +
802 (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[1].n
[1] *
803 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[1] +
804 (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[1].n
[2] *
805 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[2] + (LCMSULONGLONG
) 0x8000;
807 LCMSULONGLONG l3
= (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[2].n
[0] *
808 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[0] +
809 (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[2].n
[1] *
810 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[1] +
811 (LCMSULONGLONG
) (LCMSSLONGLONG
) a
->v
[2].n
[2] *
812 (LCMSULONGLONG
) (LCMSSLONGLONG
) v
->n
[2] + (LCMSULONGLONG
) 0x8000;
817 r
->n
[VX
] = (Fixed32
) l1
;
818 r
->n
[VY
] = (Fixed32
) l2
;
819 r
->n
[VZ
] = (Fixed32
) l3
;
823 // FIXME: Rounding should be done at very last stage. There is 1-Contone rounding error!
825 r
->n
[VX
] = FixedMul(a
->v
[0].n
[0], v
->n
[0]) +
826 FixedMul(a
->v
[0].n
[1], v
->n
[1]) +
827 FixedMul(a
->v
[0].n
[2], v
->n
[2]);
829 r
->n
[VY
] = FixedMul(a
->v
[1].n
[0], v
->n
[0]) +
830 FixedMul(a
->v
[1].n
[1], v
->n
[1]) +
831 FixedMul(a
->v
[1].n
[2], v
->n
[2]);
833 r
->n
[VZ
] = FixedMul(a
->v
[2].n
[0], v
->n
[0]) +
834 FixedMul(a
->v
[2].n
[1], v
->n
[1]) +
835 FixedMul(a
->v
[2].n
[2], v
->n
[2]);
843 void MAT3perK(LPMAT3 r
, LPMAT3 v
, double d
)
845 VEC3perK(&r
-> v
[0], &v
-> v
[0], d
);
846 VEC3perK(&r
-> v
[1], &v
-> v
[1], d
);
847 VEC3perK(&r
-> v
[2], &v
-> v
[2], d
);
851 void MAT3toFix(LPWMAT3 r
, LPMAT3 v
)
853 VEC3toFix(&r
-> v
[0], &v
-> v
[0]);
854 VEC3toFix(&r
-> v
[1], &v
-> v
[1]);
855 VEC3toFix(&r
-> v
[2], &v
-> v
[2]);
858 void MAT3toFloat(LPFMAT3 r
, LPMAT3 v
)
860 VEC3toFloat(&r
-> v
[0], &v
-> v
[0]);
861 VEC3toFloat(&r
-> v
[1], &v
-> v
[1]);
862 VEC3toFloat(&r
-> v
[2], &v
-> v
[2]);
865 void MAT3toFloatTranspose(LPFMAT3 r
, LPMAT3 v
)
869 /* for each row of the source. */
870 for (i
= 0; i
< 3; ++i
)
872 /* For element in the row. */
873 for (j
= 0; j
< 3; ++j
)
875 /* Col=>Row, Row=>Col. */
876 r
-> v
[j
].n
[i
] = DOUBLE_TO_FLOAT(v
-> v
[i
].n
[j
]);
879 void MAT3fromFix(LPMAT3 r
, LPWMAT3 v
)
881 VEC3fromFix(&r
-> v
[0], &v
-> v
[0]);
882 VEC3fromFix(&r
-> v
[1], &v
-> v
[1]);
883 VEC3fromFix(&r
-> v
[2], &v
-> v
[2]);
888 // Scale v by d and store it in r giving INTEGER
890 void VEC3scaleAndCut(LPWVEC3 r
, LPVEC3 v
, double d
)
892 r
-> n
[VX
] = (int) floor(v
-> n
[VX
] * d
+ .5);
893 r
-> n
[VY
] = (int) floor(v
-> n
[VY
] * d
+ .5);
894 r
-> n
[VZ
] = (int) floor(v
-> n
[VZ
] * d
+ .5);
897 void MAT3scaleAndCut(LPWMAT3 r
, LPMAT3 v
, double d
)
899 VEC3scaleAndCut(&r
-> v
[0], &v
-> v
[0], d
);
900 VEC3scaleAndCut(&r
-> v
[1], &v
-> v
[1], d
);
901 VEC3scaleAndCut(&r
-> v
[2], &v
-> v
[2], d
);