1use crate::*;
2use std::mem;
3
4#[inline]
18pub fn XMMatrixIsNaN(
19 M: FXMMATRIX,
20) -> bool
21{
22 #[cfg(_XM_NO_INTRINSICS_)]
23 unsafe {
24 let pWork: &[u32; 16] = mem::transmute(&M.m[0][0]);
25 for mut uTest in pWork.iter().cloned() {
26 uTest &= 0x7FFFFFFFu32;
28 uTest = uTest.wrapping_sub(0x7F800001u32);
30 if (uTest < 0x007FFFFFu32) {
31 return true;
32 }
33 }
34 false
35 }
36
37 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
38 {
39 unimplemented!()
40 }
41
42 #[cfg(_XM_SSE_INTRINSICS_)]
43 unsafe {
44 let mut vX: XMVECTOR = M.r[0];
46 let mut vY: XMVECTOR = M.r[1];
47 let mut vZ: XMVECTOR = M.r[2];
48 let mut vW: XMVECTOR = M.r[3];
49 vX = _mm_cmpneq_ps(vX, vX);
51 vY = _mm_cmpneq_ps(vY, vY);
52 vZ = _mm_cmpneq_ps(vZ, vZ);
53 vW = _mm_cmpneq_ps(vW, vW);
54 vX = _mm_or_ps(vX, vZ);
56 vY = _mm_or_ps(vY, vW);
57 vX = _mm_or_ps(vX, vY);
58 return (_mm_movemask_ps(vX) != 0);
60 }
61}
62
63#[test]
64fn test_XMMatrixIsNan() {
65 let m = XMMATRIX {
66 r: [*g_XMZero, *g_XMZero, *g_XMZero, *g_XMZero],
67 };
68 assert_eq!(false, XMMatrixIsNaN(m));
69
70 let m = XMMATRIX {
71 r: [*g_XMInfinity, *g_XMInfinity, *g_XMInfinity, *g_XMInfinity],
72 };
73 assert_eq!(false, XMMatrixIsNaN(m));
74
75 let m = XMMATRIX {
76 r: [*g_XMZero, *g_XMZero, *g_XMZero, *g_XMNegQNaN],
77 };
78 assert_eq!(true, XMMatrixIsNaN(m));
79
80 let m = XMMATRIX {
81 r: [XMVectorReplicate(std::f32::NAN), *g_XMZero, *g_XMZero, *g_XMZero],
82 };
83 assert_eq!(true, XMMatrixIsNaN(m));
84}
85
86#[inline]
100pub fn XMMatrixIsInfinite(
101 M: FXMMATRIX,
102) -> bool
103{
104 #[cfg(_XM_NO_INTRINSICS_)]
105 unsafe {
106 let pWork: &[u32; 16] = mem::transmute(&M.m[0][0]);
107 for mut uTest in pWork.iter().cloned() {
108 uTest &= 0x7FFFFFFFu32;
110 if (uTest == 0x7F800000u32) {
112 return true;
113 }
114 }
115 false
116 }
117
118 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
119 {
120 unimplemented!()
121 }
122
123 #[cfg(_XM_SSE_INTRINSICS_)]
124 unsafe {
125 let mut vTemp1: XMVECTOR = _mm_and_ps(M.r[0], *g_XMAbsMask);
127 let mut vTemp2: XMVECTOR = _mm_and_ps(M.r[1], *g_XMAbsMask);
128 let mut vTemp3: XMVECTOR = _mm_and_ps(M.r[2], *g_XMAbsMask);
129 let mut vTemp4: XMVECTOR = _mm_and_ps(M.r[3], *g_XMAbsMask);
130 vTemp1 = _mm_cmpeq_ps(vTemp1, *g_XMInfinity);
132 vTemp2 = _mm_cmpeq_ps(vTemp2, *g_XMInfinity);
133 vTemp3 = _mm_cmpeq_ps(vTemp3, *g_XMInfinity);
134 vTemp4 = _mm_cmpeq_ps(vTemp4, *g_XMInfinity);
135 vTemp1 = _mm_or_ps(vTemp1, vTemp2);
137 vTemp3 = _mm_or_ps(vTemp3, vTemp4);
138 vTemp1 = _mm_or_ps(vTemp1, vTemp3);
139 return (_mm_movemask_ps(vTemp1) != 0);
141 }
142}
143
144#[test]
145fn test_XMMatrixIsInfinite() {
146 let m = XMMATRIX {
147 r: [*g_XMZero, *g_XMZero, *g_XMZero, *g_XMZero],
148 };
149 assert_eq!(false, XMMatrixIsInfinite(m));
150
151 let m = XMMATRIX {
152 r: [*g_XMQNaN, *g_XMQNaN, *g_XMQNaN, *g_XMQNaN],
153 };
154 assert_eq!(false, XMMatrixIsInfinite(m));
155
156 let m = XMMATRIX {
157 r: [*g_XMZero, *g_XMZero, *g_XMZero, *g_XMNegInfinity],
158 };
159 assert_eq!(true, XMMatrixIsInfinite(m));
160
161 let m = XMMATRIX {
162 r: [*g_XMZero, *g_XMZero, *g_XMZero, *g_XMInfinity],
163 };
164 assert_eq!(true, XMMatrixIsInfinite(m));
165}
166
167#[inline]
181pub fn XMMatrixIsIdentity(
182 M: FXMMATRIX,
183) -> bool
184{
185 #[cfg(_XM_NO_INTRINSICS_)]
186 unsafe {
187 let pWork: &[u32; 16] = mem::transmute(&M.m[0][0]);
189 let mut uOne: u32 = pWork[0] ^ 0x3F800000u32;
191 let mut uZero: u32 = pWork[1];
193 uZero |= pWork[2];
194 uZero |= pWork[3];
195 uZero |= pWork[4];
197 uOne |= pWork[5] ^ 0x3F800000u32;
198 uZero |= pWork[6];
199 uZero |= pWork[7];
200 uZero |= pWork[8];
202 uZero |= pWork[9];
203 uOne |= pWork[10] ^ 0x3F800000u32;
204 uZero |= pWork[11];
205 uZero |= pWork[12];
207 uZero |= pWork[13];
208 uZero |= pWork[14];
209 uOne |= pWork[15] ^ 0x3F800000u32;
210 uZero &= 0x7FFFFFFF; uOne |= uZero;
214 return (uOne == 0);
215 }
216
217 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
218 {
219 unimplemented!()
220 }
221
222 #[cfg(_XM_SSE_INTRINSICS_)]
223 unsafe {
224 let mut vTemp1: XMVECTOR = _mm_cmpeq_ps(M.r[0], *g_XMIdentityR0);
225 let vTemp2: XMVECTOR = _mm_cmpeq_ps(M.r[1], *g_XMIdentityR1);
226 let mut vTemp3: XMVECTOR = _mm_cmpeq_ps(M.r[2], *g_XMIdentityR2);
227 let vTemp4: XMVECTOR = _mm_cmpeq_ps(M.r[3], *g_XMIdentityR3);
228 vTemp1 = _mm_and_ps(vTemp1, vTemp2);
229 vTemp3 = _mm_and_ps(vTemp3, vTemp4);
230 vTemp1 = _mm_and_ps(vTemp1, vTemp3);
231 return (_mm_movemask_ps(vTemp1) == 0x0f);
232 }
233}
234
235#[inline]
251pub fn XMMatrixMultiply(
252 M1: FXMMATRIX,
253 M2: CXMMATRIX,
254) -> XMMATRIX
255{
256 #[cfg(_XM_NO_INTRINSICS_)]
257 unsafe {
258 let mut mResult: XMMATRIX = crate::undefined();
259 let mut x: f32 = M1.m[0][0];
261 let mut y: f32 = M1.m[0][1];
262 let mut z: f32 = M1.m[0][2];
263 let mut w: f32 = M1.m[0][3];
264 mResult.m[0][0] = (M2.m[0][0] * x) + (M2.m[1][0] * y) + (M2.m[2][0] * z) + (M2.m[3][0] * w);
266 mResult.m[0][1] = (M2.m[0][1] * x) + (M2.m[1][1] * y) + (M2.m[2][1] * z) + (M2.m[3][1] * w);
267 mResult.m[0][2] = (M2.m[0][2] * x) + (M2.m[1][2] * y) + (M2.m[2][2] * z) + (M2.m[3][2] * w);
268 mResult.m[0][3] = (M2.m[0][3] * x) + (M2.m[1][3] * y) + (M2.m[2][3] * z) + (M2.m[3][3] * w);
269 x = M1.m[1][0];
271 y = M1.m[1][1];
272 z = M1.m[1][2];
273 w = M1.m[1][3];
274 mResult.m[1][0] = (M2.m[0][0] * x) + (M2.m[1][0] * y) + (M2.m[2][0] * z) + (M2.m[3][0] * w);
275 mResult.m[1][1] = (M2.m[0][1] * x) + (M2.m[1][1] * y) + (M2.m[2][1] * z) + (M2.m[3][1] * w);
276 mResult.m[1][2] = (M2.m[0][2] * x) + (M2.m[1][2] * y) + (M2.m[2][2] * z) + (M2.m[3][2] * w);
277 mResult.m[1][3] = (M2.m[0][3] * x) + (M2.m[1][3] * y) + (M2.m[2][3] * z) + (M2.m[3][3] * w);
278 x = M1.m[2][0];
279 y = M1.m[2][1];
280 z = M1.m[2][2];
281 w = M1.m[2][3];
282 mResult.m[2][0] = (M2.m[0][0] * x) + (M2.m[1][0] * y) + (M2.m[2][0] * z) + (M2.m[3][0] * w);
283 mResult.m[2][1] = (M2.m[0][1] * x) + (M2.m[1][1] * y) + (M2.m[2][1] * z) + (M2.m[3][1] * w);
284 mResult.m[2][2] = (M2.m[0][2] * x) + (M2.m[1][2] * y) + (M2.m[2][2] * z) + (M2.m[3][2] * w);
285 mResult.m[2][3] = (M2.m[0][3] * x) + (M2.m[1][3] * y) + (M2.m[2][3] * z) + (M2.m[3][3] * w);
286 x = M1.m[3][0];
287 y = M1.m[3][1];
288 z = M1.m[3][2];
289 w = M1.m[3][3];
290 mResult.m[3][0] = (M2.m[0][0] * x) + (M2.m[1][0] * y) + (M2.m[2][0] * z) + (M2.m[3][0] * w);
291 mResult.m[3][1] = (M2.m[0][1] * x) + (M2.m[1][1] * y) + (M2.m[2][1] * z) + (M2.m[3][1] * w);
292 mResult.m[3][2] = (M2.m[0][2] * x) + (M2.m[1][2] * y) + (M2.m[2][2] * z) + (M2.m[3][2] * w);
293 mResult.m[3][3] = (M2.m[0][3] * x) + (M2.m[1][3] * y) + (M2.m[2][3] * z) + (M2.m[3][3] * w);
294 return mResult;
295 }
296
297 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
298 {
299 unimplemented!()
300 }
301
302 #[cfg(_XM_AVX2_INTRINSICS_)]
303 unsafe {
304 let mut t0: __m256 = _mm256_castps128_ps256(M1.r[0]);
305 t0 = _mm256_insertf128_ps(t0, M1.r[1], 1);
306 let mut t1: __m256 = _mm256_castps128_ps256(M1.r[2]);
307 t1 = _mm256_insertf128_ps(t1, M1.r[3], 1);
308
309 let mut u0: __m256 = _mm256_castps128_ps256(M2.r[0]);
310 u0 = _mm256_insertf128_ps(u0, M2.r[1], 1);
311 let mut u1: __m256 = _mm256_castps128_ps256(M2.r[2]);
312 u1 = _mm256_insertf128_ps(u1, M2.r[3], 1);
313
314 let mut a0: __m256 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(0, 0, 0, 0));
315 let mut a1: __m256 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(0, 0, 0, 0));
316 let mut b0: __m256 = _mm256_permute2f128_ps(u0, u0, 0x00);
317 let c0: __m256 = _mm256_mul_ps(a0, b0);
318 let c1: __m256 = _mm256_mul_ps(a1, b0);
319
320 a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(1, 1, 1, 1));
321 a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(1, 1, 1, 1));
322 b0 = _mm256_permute2f128_ps(u0, u0, 0x11);
323 let c2: __m256 = _mm256_fmadd_ps(a0, b0, c0);
324 let c3: __m256 = _mm256_fmadd_ps(a1, b0, c1);
325
326 a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(2, 2, 2, 2));
327 a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(2, 2, 2, 2));
328 let mut b1: __m256 = _mm256_permute2f128_ps(u1, u1, 0x00);
329 let c4: __m256 = _mm256_mul_ps(a0, b1);
330 let c5: __m256 = _mm256_mul_ps(a1, b1);
331
332 a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(3, 3, 3, 3));
333 a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(3, 3, 3, 3));
334 b1 = _mm256_permute2f128_ps(u1, u1, 0x11);
335 let c6: __m256 = _mm256_fmadd_ps(a0, b1, c4);
336 let c7: __m256 = _mm256_fmadd_ps(a1, b1, c5);
337
338 t0 = _mm256_add_ps(c2, c6);
339 t1 = _mm256_add_ps(c3, c7);
340
341 let mut mResult: XMMATRIX = crate::undefined();
342 mResult.r[0] = _mm256_castps256_ps128(t0);
343 mResult.r[1] = _mm256_extractf128_ps(t0, 1);
344 mResult.r[2] = _mm256_castps256_ps128(t1);
345 mResult.r[3] = _mm256_extractf128_ps(t1, 1);
346 return mResult;
347 }
348
349 #[cfg(all(_XM_AVX_INTRINSICS_, not(_XM_AVX2_INTRINSICS_)))]
350 unsafe {
351 let mut mResult: XMMATRIX = crate::undefined();
352
353 let mut vX: XMVECTOR = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[0])[0])));
355 let mut vY: XMVECTOR = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[0])[1])));
356 let mut vZ: XMVECTOR = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[0])[2])));
357 let mut vW: XMVECTOR = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[0])[3])));
358
359 vX = _mm_mul_ps(vX, M2.r[0]);
361 vY = _mm_mul_ps(vY, M2.r[1]);
362 vZ = _mm_mul_ps(vZ, M2.r[2]);
363 vW = _mm_mul_ps(vW, M2.r[3]);
364 vX = _mm_add_ps(vX, vZ);
366 vY = _mm_add_ps(vY, vW);
367 vX = _mm_add_ps(vX, vY);
368 mResult.r[0] = vX;
369
370 vX = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[1])[0])));
372 vY = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[1])[1])));
373 vZ = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[1])[2])));
374 vW = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[1])[3])));
375
376 vX = _mm_mul_ps(vX, M2.r[0]);
377 vY = _mm_mul_ps(vY, M2.r[1]);
378 vZ = _mm_mul_ps(vZ, M2.r[2]);
379 vW = _mm_mul_ps(vW, M2.r[3]);
380
381 vX = _mm_add_ps(vX, vZ);
382 vY = _mm_add_ps(vY, vW);
383 vX = _mm_add_ps(vX, vY);
384 mResult.r[1] = vX;
385
386 vX = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[2])[0])));
387 vY = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[2])[1])));
388 vZ = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[2])[2])));
389 vW = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[2])[3])));
390
391 vX = _mm_mul_ps(vX, M2.r[0]);
392 vY = _mm_mul_ps(vY, M2.r[1]);
393 vZ = _mm_mul_ps(vZ, M2.r[2]);
394 vW = _mm_mul_ps(vW, M2.r[3]);
395
396 vX = _mm_add_ps(vX, vZ);
397 vY = _mm_add_ps(vY, vW);
398 vX = _mm_add_ps(vX, vY);
399 mResult.r[2] = vX;
400
401 vX = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[3])[0])));
402 vY = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[3])[1])));
403 vZ = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[3])[2])));
404 vW = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[3])[3])));
405
406 vX = _mm_mul_ps(vX, M2.r[0]);
407 vY = _mm_mul_ps(vY, M2.r[1]);
408 vZ = _mm_mul_ps(vZ, M2.r[2]);
409 vW = _mm_mul_ps(vW, M2.r[3]);
410
411 vX = _mm_add_ps(vX, vZ);
412 vY = _mm_add_ps(vY, vW);
413 vX = _mm_add_ps(vX, vY);
414 mResult.r[3] = vX;
415 return mResult;
416 }
417
418 #[cfg(all(_XM_SSE_INTRINSICS_, not(_XM_AVX_INTRINSICS_), not(_XM_AVX2_INTRINSICS_)))]
419 unsafe {
420 let mut mResult: XMMATRIX = crate::undefined();
421
422 let mut vW: XMVECTOR = M1.r[0];
424 let mut vX: XMVECTOR = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(0, 0, 0, 0));
425 let mut vY: XMVECTOR = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(1, 1, 1, 1));
426 let mut vZ: XMVECTOR = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(2, 2, 2, 2));
427 vW = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(3, 3, 3, 3));
428
429 vX = _mm_mul_ps(vX, M2.r[0]);
431 vY = _mm_mul_ps(vY, M2.r[1]);
432 vZ = _mm_mul_ps(vZ, M2.r[2]);
433 vW = _mm_mul_ps(vW, M2.r[3]);
434 vX = _mm_add_ps(vX, vZ);
436 vY = _mm_add_ps(vY, vW);
437 vX = _mm_add_ps(vX, vY);
438 mResult.r[0] = vX;
439 vW = M1.r[1];
442 vX = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(0, 0, 0, 0));
443 vY = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(1, 1, 1, 1));
444 vZ = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(2, 2, 2, 2));
445 vW = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(3, 3, 3, 3));
446
447 vX = _mm_mul_ps(vX, M2.r[0]);
448 vY = _mm_mul_ps(vY, M2.r[1]);
449 vZ = _mm_mul_ps(vZ, M2.r[2]);
450 vW = _mm_mul_ps(vW, M2.r[3]);
451 vX = _mm_add_ps(vX, vZ);
452 vY = _mm_add_ps(vY, vW);
453 vX = _mm_add_ps(vX, vY);
454 mResult.r[1] = vX;
455
456 vW = M1.r[2];
457 vX = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(0, 0, 0, 0));
458 vY = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(1, 1, 1, 1));
459 vZ = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(2, 2, 2, 2));
460 vW = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(3, 3, 3, 3));
461
462 vX = _mm_mul_ps(vX, M2.r[0]);
463 vY = _mm_mul_ps(vY, M2.r[1]);
464 vZ = _mm_mul_ps(vZ, M2.r[2]);
465 vW = _mm_mul_ps(vW, M2.r[3]);
466 vX = _mm_add_ps(vX, vZ);
467 vY = _mm_add_ps(vY, vW);
468 vX = _mm_add_ps(vX, vY);
469 mResult.r[2] = vX;
470
471 vW = M1.r[3];
472 vX = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(0, 0, 0, 0));
473 vY = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(1, 1, 1, 1));
474 vZ = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(2, 2, 2, 2));
475 vW = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(3, 3, 3, 3));
476
477 vX = _mm_mul_ps(vX, M2.r[0]);
478 vY = _mm_mul_ps(vY, M2.r[1]);
479 vZ = _mm_mul_ps(vZ, M2.r[2]);
480 vW = _mm_mul_ps(vW, M2.r[3]);
481 vX = _mm_add_ps(vX, vZ);
482 vY = _mm_add_ps(vY, vW);
483 vX = _mm_add_ps(vX, vY);
484 mResult.r[3] = vX;
485 return mResult;
486 }
487}
488
489#[test]
490fn test_XMMatrixMultiply() {
491 let a = XMMATRIX {
492 r: [
493 XMVectorSet( 1.0, 2.0, 3.0, 4.0),
494 XMVectorSet( 5.0, 6.0, 7.0, 8.0),
495 XMVectorSet( 9.0, 10.0, 11.0, 12.0),
496 XMVectorSet(13.0, 14.0, 15.0, 16.0),
497 ]
498 };
499 let b = XMMATRIX {
500 r: [
501 XMVectorSet(13.0, 14.0, 15.0, 16.0),
502 XMVectorSet( 9.0, 10.0, 11.0, 12.0),
503 XMVectorSet( 5.0, 6.0, 7.0, 8.0),
504 XMVectorSet( 1.0, 2.0, 3.0, 4.0),
505 ]
506 };
507
508 let c = XMMatrixMultiply(a, &b);
509
510 let d = XMMATRIX {
511 r: [
512 XMVectorSet( 50.0, 60.0, 70.0, 80.0),
513 XMVectorSet(162.0, 188.0, 214.0, 240.0),
514 XMVectorSet(274.0, 316.0, 358.0, 400.0),
515 XMVectorSet(386.0, 444.0, 502.0, 560.0),
516 ]
517 };
518
519 unsafe {
520 let mut cr = 0;
521 XMVectorEqualR(&mut cr, c.r[0], d.r[0]);
522 assert!(XMComparisonAllTrue(cr));
523
524 XMVectorEqualR(&mut cr, c.r[1], d.r[1]);
525 assert!(XMComparisonAllTrue(cr));
526
527 XMVectorEqualR(&mut cr, c.r[2], d.r[2]);
528 assert!(XMComparisonAllTrue(cr));
529
530 XMVectorEqualR(&mut cr, c.r[3], d.r[3]);
531 assert!(XMComparisonAllTrue(cr));
532 }
533}
534
535#[inline]
551pub fn XMMatrixMultiplyTranspose(
552 M1: FXMMATRIX,
553 M2: CXMMATRIX,
554) -> XMMATRIX
555{
556 #[cfg(_XM_NO_INTRINSICS_)]
557 unsafe {
558 let mut mResult: XMMATRIX = crate::undefined();
559 let mut x: f32 = M2.m[0][0];
561 let mut y: f32 = M2.m[1][0];
562 let mut z: f32 = M2.m[2][0];
563 let mut w: f32 = M2.m[3][0];
564 mResult.m[0][0] = (M1.m[0][0] * x) + (M1.m[0][1] * y) + (M1.m[0][2] * z) + (M1.m[0][3] * w);
566 mResult.m[0][1] = (M1.m[1][0] * x) + (M1.m[1][1] * y) + (M1.m[1][2] * z) + (M1.m[1][3] * w);
567 mResult.m[0][2] = (M1.m[2][0] * x) + (M1.m[2][1] * y) + (M1.m[2][2] * z) + (M1.m[2][3] * w);
568 mResult.m[0][3] = (M1.m[3][0] * x) + (M1.m[3][1] * y) + (M1.m[3][2] * z) + (M1.m[3][3] * w);
569 x = M2.m[0][1];
571 y = M2.m[1][1];
572 z = M2.m[2][1];
573 w = M2.m[3][1];
574 mResult.m[1][0] = (M1.m[0][0] * x) + (M1.m[0][1] * y) + (M1.m[0][2] * z) + (M1.m[0][3] * w);
575 mResult.m[1][1] = (M1.m[1][0] * x) + (M1.m[1][1] * y) + (M1.m[1][2] * z) + (M1.m[1][3] * w);
576 mResult.m[1][2] = (M1.m[2][0] * x) + (M1.m[2][1] * y) + (M1.m[2][2] * z) + (M1.m[2][3] * w);
577 mResult.m[1][3] = (M1.m[3][0] * x) + (M1.m[3][1] * y) + (M1.m[3][2] * z) + (M1.m[3][3] * w);
578 x = M2.m[0][2];
579 y = M2.m[1][2];
580 z = M2.m[2][2];
581 w = M2.m[3][2];
582 mResult.m[2][0] = (M1.m[0][0] * x) + (M1.m[0][1] * y) + (M1.m[0][2] * z) + (M1.m[0][3] * w);
583 mResult.m[2][1] = (M1.m[1][0] * x) + (M1.m[1][1] * y) + (M1.m[1][2] * z) + (M1.m[1][3] * w);
584 mResult.m[2][2] = (M1.m[2][0] * x) + (M1.m[2][1] * y) + (M1.m[2][2] * z) + (M1.m[2][3] * w);
585 mResult.m[2][3] = (M1.m[3][0] * x) + (M1.m[3][1] * y) + (M1.m[3][2] * z) + (M1.m[3][3] * w);
586 x = M2.m[0][3];
587 y = M2.m[1][3];
588 z = M2.m[2][3];
589 w = M2.m[3][3];
590 mResult.m[3][0] = (M1.m[0][0] * x) + (M1.m[0][1] * y) + (M1.m[0][2] * z) + (M1.m[0][3] * w);
591 mResult.m[3][1] = (M1.m[1][0] * x) + (M1.m[1][1] * y) + (M1.m[1][2] * z) + (M1.m[1][3] * w);
592 mResult.m[3][2] = (M1.m[2][0] * x) + (M1.m[2][1] * y) + (M1.m[2][2] * z) + (M1.m[2][3] * w);
593 mResult.m[3][3] = (M1.m[3][0] * x) + (M1.m[3][1] * y) + (M1.m[3][2] * z) + (M1.m[3][3] * w);
594 return mResult;
595 }
596
597 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
598 {
599 unimplemented!()
600 }
601
602 #[cfg(_XM_AVX2_INTRINSICS_)]
603 unsafe {
604 let mut t0: __m256 = _mm256_castps128_ps256(M1.r[0]);
605 t0 = _mm256_insertf128_ps(t0, M1.r[1], 1);
606 let mut t1: __m256 = _mm256_castps128_ps256(M1.r[2]);
607 t1 = _mm256_insertf128_ps(t1, M1.r[3], 1);
608
609 let mut u0: __m256 = _mm256_castps128_ps256(M2.r[0]);
610 u0 = _mm256_insertf128_ps(u0, M2.r[1], 1);
611 let mut u1: __m256 = _mm256_castps128_ps256(M2.r[2]);
612 u1 = _mm256_insertf128_ps(u1, M2.r[3], 1);
613
614 let mut a0: __m256 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(0, 0, 0, 0));
615 let mut a1: __m256 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(0, 0, 0, 0));
616 let mut b0: __m256 = _mm256_permute2f128_ps(u0, u0, 0x00);
617 let c0: __m256 = _mm256_mul_ps(a0, b0);
618 let c1: __m256 = _mm256_mul_ps(a1, b0);
619
620 a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(1, 1, 1, 1));
621 a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(1, 1, 1, 1));
622 b0 = _mm256_permute2f128_ps(u0, u0, 0x11);
623 let c2: __m256 = _mm256_fmadd_ps(a0, b0, c0);
624 let c3: __m256 = _mm256_fmadd_ps(a1, b0, c1);
625
626 a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(2, 2, 2, 2));
627 a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(2, 2, 2, 2));
628 let mut b1: __m256 = _mm256_permute2f128_ps(u1, u1, 0x00);
629 let c4: __m256 = _mm256_mul_ps(a0, b1);
630 let c5: __m256 = _mm256_mul_ps(a1, b1);
631
632 a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(3, 3, 3, 3));
633 a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(3, 3, 3, 3));
634 b1 = _mm256_permute2f128_ps(u1, u1, 0x11);
635 let c6: __m256 = _mm256_fmadd_ps(a0, b1, c4);
636 let c7: __m256 = _mm256_fmadd_ps(a1, b1, c5);
637
638 t0 = _mm256_add_ps(c2, c6);
639 t1 = _mm256_add_ps(c3, c7);
640
641 let mut vTemp: __m256 = _mm256_unpacklo_ps(t0, t1);
643 let mut vTemp2: __m256 = _mm256_unpackhi_ps(t0, t1);
644 let vTemp3: __m256 = _mm256_permute2f128_ps(vTemp, vTemp2, 0x20);
645 let vTemp4: __m256 = _mm256_permute2f128_ps(vTemp, vTemp2, 0x31);
646 vTemp = _mm256_unpacklo_ps(vTemp3, vTemp4);
647 vTemp2 = _mm256_unpackhi_ps(vTemp3, vTemp4);
648 t0 = _mm256_permute2f128_ps(vTemp, vTemp2, 0x20);
649 t1 = _mm256_permute2f128_ps(vTemp, vTemp2, 0x31);
650
651 let mut mResult: XMMATRIX = crate::undefined();
652 mResult.r[0] = _mm256_castps256_ps128(t0);
653 mResult.r[1] = _mm256_extractf128_ps(t0, 1);
654 mResult.r[2] = _mm256_castps256_ps128(t1);
655 mResult.r[3] = _mm256_extractf128_ps(t1, 1);
656 return mResult;
657 }
658
659 #[cfg(all(_XM_AVX_INTRINSICS_, not(_XM_AVX2_INTRINSICS_)))]
660 unsafe {
661 let mut vX: XMVECTOR = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[0])[0])));
663 let mut vY: XMVECTOR = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[0])[1])));
664 let mut vZ: XMVECTOR = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[0])[2])));
665 let mut vW: XMVECTOR = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[0])[3])));
666
667 vX = _mm_mul_ps(vX, M2.r[0]);
669 vY = _mm_mul_ps(vY, M2.r[1]);
670 vZ = _mm_mul_ps(vZ, M2.r[2]);
671 vW = _mm_mul_ps(vW, M2.r[3]);
672 vX = _mm_add_ps(vX, vZ);
674 vY = _mm_add_ps(vY, vW);
675 vX = _mm_add_ps(vX, vY);
676 let r0: XMVECTOR = vX;
677
678 vX = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[1])[0])));
680 vY = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[1])[1])));
681 vZ = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[1])[2])));
682 vW = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[1])[3])));
683
684 vX = _mm_mul_ps(vX, M2.r[0]);
685 vY = _mm_mul_ps(vY, M2.r[1]);
686 vZ = _mm_mul_ps(vZ, M2.r[2]);
687 vW = _mm_mul_ps(vW, M2.r[3]);
688
689 vX = _mm_add_ps(vX, vZ);
690 vY = _mm_add_ps(vY, vW);
691 vX = _mm_add_ps(vX, vY);
692 let r1: XMVECTOR = vX;
693
694 vX = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[2])[0])));
695 vY = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[2])[1])));
696 vZ = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[2])[2])));
697 vW = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[2])[3])));
698
699 vX = _mm_mul_ps(vX, M2.r[0]);
700 vY = _mm_mul_ps(vY, M2.r[1]);
701 vZ = _mm_mul_ps(vZ, M2.r[2]);
702 vW = _mm_mul_ps(vW, M2.r[3]);
703
704 vX = _mm_add_ps(vX, vZ);
705 vY = _mm_add_ps(vY, vW);
706 vX = _mm_add_ps(vX, vY);
707 let r2: XMVECTOR = vX;
708
709 vX = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[3])[0])));
710 vY = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[3])[1])));
711 vZ = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[3])[2])));
712 vW = _mm_broadcast_ss(&*mem::transmute::<_, *const f32>(&idx!(f32x4(M1.r[3])[3])));
713
714 vX = _mm_mul_ps(vX, M2.r[0]);
715 vY = _mm_mul_ps(vY, M2.r[1]);
716 vZ = _mm_mul_ps(vZ, M2.r[2]);
717 vW = _mm_mul_ps(vW, M2.r[3]);
718
719 vX = _mm_add_ps(vX, vZ);
720 vY = _mm_add_ps(vY, vW);
721 vX = _mm_add_ps(vX, vY);
722 let r3: XMVECTOR = vX;
723
724 let vTemp1: XMVECTOR = _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(1, 0, 1, 0));
727 let vTemp3: XMVECTOR = _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(3, 2, 3, 2));
729 let vTemp2: XMVECTOR = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(1, 0, 1, 0));
731 let vTemp4: XMVECTOR = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(3, 2, 3, 2));
733
734 let mut mResult: XMMATRIX = crate::undefined();
735 mResult.r[0] = _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(2, 0, 2, 0));
737 mResult.r[1] = _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(3, 1, 3, 1));
739 mResult.r[2] = _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(2, 0, 2, 0));
741 mResult.r[3] = _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(3, 1, 3, 1));
743 return mResult;
744 }
745
746 #[cfg(all(_XM_SSE_INTRINSICS_, not(_XM_AVX_INTRINSICS_), not(_XM_AVX2_INTRINSICS_)))]
747 unsafe {
748 let mut vW: XMVECTOR = M1.r[0];
750 let mut vX: XMVECTOR = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(0, 0, 0, 0));
751 let mut vY: XMVECTOR = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(1, 1, 1, 1));
752 let mut vZ: XMVECTOR = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(2, 2, 2, 2));
753 vW = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(3, 3, 3, 3));
754
755 vX = _mm_mul_ps(vX, M2.r[0]);
757 vY = _mm_mul_ps(vY, M2.r[1]);
758 vZ = _mm_mul_ps(vZ, M2.r[2]);
759 vW = _mm_mul_ps(vW, M2.r[3]);
760 vX = _mm_add_ps(vX, vZ);
762 vY = _mm_add_ps(vY, vW);
763 vX = _mm_add_ps(vX, vY);
764 let r0: XMVECTOR = vX;
765 vW = M1.r[1];
768 vX = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(0, 0, 0, 0));
769 vY = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(1, 1, 1, 1));
770 vZ = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(2, 2, 2, 2));
771 vW = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(3, 3, 3, 3));
772
773 vX = _mm_mul_ps(vX, M2.r[0]);
774 vY = _mm_mul_ps(vY, M2.r[1]);
775 vZ = _mm_mul_ps(vZ, M2.r[2]);
776 vW = _mm_mul_ps(vW, M2.r[3]);
777 vX = _mm_add_ps(vX, vZ);
778 vY = _mm_add_ps(vY, vW);
779 vX = _mm_add_ps(vX, vY);
780 let r1: XMVECTOR = vX;
781
782 vW = M1.r[2];
783 vX = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(0, 0, 0, 0));
784 vY = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(1, 1, 1, 1));
785 vZ = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(2, 2, 2, 2));
786 vW = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(3, 3, 3, 3));
787
788 vX = _mm_mul_ps(vX, M2.r[0]);
789 vY = _mm_mul_ps(vY, M2.r[1]);
790 vZ = _mm_mul_ps(vZ, M2.r[2]);
791 vW = _mm_mul_ps(vW, M2.r[3]);
792 vX = _mm_add_ps(vX, vZ);
793 vY = _mm_add_ps(vY, vW);
794 vX = _mm_add_ps(vX, vY);
795 let r2: XMVECTOR = vX;
796
797 vW = M1.r[3];
798 vX = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(0, 0, 0, 0));
799 vY = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(1, 1, 1, 1));
800 vZ = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(2, 2, 2, 2));
801 vW = XM_PERMUTE_PS!(vW, _MM_SHUFFLE(3, 3, 3, 3));
802
803 vX = _mm_mul_ps(vX, M2.r[0]);
804 vY = _mm_mul_ps(vY, M2.r[1]);
805 vZ = _mm_mul_ps(vZ, M2.r[2]);
806 vW = _mm_mul_ps(vW, M2.r[3]);
807 vX = _mm_add_ps(vX, vZ);
808 vY = _mm_add_ps(vY, vW);
809 vX = _mm_add_ps(vX, vY);
810 let r3: XMVECTOR = vX;
811
812 let vTemp1: XMVECTOR = _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(1, 0, 1, 0));
815 let vTemp3: XMVECTOR = _mm_shuffle_ps(r0, r1, _MM_SHUFFLE(3, 2, 3, 2));
817 let vTemp2: XMVECTOR = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(1, 0, 1, 0));
819 let vTemp4: XMVECTOR = _mm_shuffle_ps(r2, r3, _MM_SHUFFLE(3, 2, 3, 2));
821
822 let mut mResult: XMMATRIX = crate::undefined();
823 mResult.r[0] = _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(2, 0, 2, 0));
825 mResult.r[1] = _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(3, 1, 3, 1));
827 mResult.r[2] = _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(2, 0, 2, 0));
829 mResult.r[3] = _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(3, 1, 3, 1));
831 return mResult;
832 }
833}
834
835#[test]
836fn test_XMMatrixMultiplyTranspose() {
837 let a = XMMATRIX {
838 r: [
839 XMVectorSet( 1.0, 2.0, 3.0, 4.0),
840 XMVectorSet( 5.0, 6.0, 7.0, 8.0),
841 XMVectorSet( 9.0, 10.0, 11.0, 12.0),
842 XMVectorSet(13.0, 14.0, 15.0, 16.0),
843 ]
844 };
845 let b = XMMATRIX {
846 r: [
847 XMVectorSet(13.0, 14.0, 15.0, 16.0),
848 XMVectorSet( 9.0, 10.0, 11.0, 12.0),
849 XMVectorSet( 5.0, 6.0, 7.0, 8.0),
850 XMVectorSet( 1.0, 2.0, 3.0, 4.0),
851 ]
852 };
853
854 let c = XMMatrixMultiplyTranspose(a, &b);
855
856 let d = XMMATRIX {
857 r: [
858 XMVectorSet( 50.0, 60.0, 70.0, 80.0),
859 XMVectorSet(162.0, 188.0, 214.0, 240.0),
860 XMVectorSet(274.0, 316.0, 358.0, 400.0),
861 XMVectorSet(386.0, 444.0, 502.0, 560.0),
862 ]
863 };
864
865 let d = XMMatrixTranspose(d);
866
867 unsafe {
868 let mut cr = 0;
869 XMVectorEqualR(&mut cr, c.r[0], d.r[0]);
870 assert!(XMComparisonAllTrue(cr));
871
872 XMVectorEqualR(&mut cr, c.r[1], d.r[1]);
873 assert!(XMComparisonAllTrue(cr));
874
875 XMVectorEqualR(&mut cr, c.r[2], d.r[2]);
876 assert!(XMComparisonAllTrue(cr));
877
878 XMVectorEqualR(&mut cr, c.r[3], d.r[3]);
879 assert!(XMComparisonAllTrue(cr));
880 }
881}
882
883#[inline]
897pub fn XMMatrixTranspose(
898 M: FXMMATRIX,
899) -> XMMATRIX
900{
901 #[cfg(_XM_NO_INTRINSICS_)]
902 unsafe {
903 let mut P: XMMATRIX = crate::undefined();
911 P.r[0] = XMVectorMergeXY(M.r[0], M.r[2]); P.r[1] = XMVectorMergeXY(M.r[1], M.r[3]); P.r[2] = XMVectorMergeZW(M.r[0], M.r[2]); P.r[3] = XMVectorMergeZW(M.r[1], M.r[3]); let mut MT: XMMATRIX = crate::undefined();
917 MT.r[0] = XMVectorMergeXY(P.r[0], P.r[1]); MT.r[1] = XMVectorMergeZW(P.r[0], P.r[1]); MT.r[2] = XMVectorMergeXY(P.r[2], P.r[3]); MT.r[3] = XMVectorMergeZW(P.r[2], P.r[3]); return MT;
922 }
923
924 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
925 {
926 unimplemented!()
927 }
928
929 #[cfg(_XM_AVX2_INTRINSICS_)]
930 unsafe {
931 let mut t0: __m256 = _mm256_castps128_ps256(M.r[0]);
932 t0 = _mm256_insertf128_ps(t0, M.r[1], 1);
933 let mut t1: __m256 = _mm256_castps128_ps256(M.r[2]);
934 t1 = _mm256_insertf128_ps(t1, M.r[3], 1);
935
936 let mut vTemp: __m256 = _mm256_unpacklo_ps(t0, t1);
937 let mut vTemp2: __m256 = _mm256_unpackhi_ps(t0, t1);
938 let vTemp3: __m256 = _mm256_permute2f128_ps(vTemp, vTemp2, 0x20);
939 let vTemp4: __m256 = _mm256_permute2f128_ps(vTemp, vTemp2, 0x31);
940 vTemp = _mm256_unpacklo_ps(vTemp3, vTemp4);
941 vTemp2 = _mm256_unpackhi_ps(vTemp3, vTemp4);
942 t0 = _mm256_permute2f128_ps(vTemp, vTemp2, 0x20);
943 t1 = _mm256_permute2f128_ps(vTemp, vTemp2, 0x31);
944
945 let mut mResult: XMMATRIX = crate::undefined();
946 mResult.r[0] = _mm256_castps256_ps128(t0);
947 mResult.r[1] = _mm256_extractf128_ps(t0, 1);
948 mResult.r[2] = _mm256_castps256_ps128(t1);
949 mResult.r[3] = _mm256_extractf128_ps(t1, 1);
950 return mResult;
951 }
952
953 #[cfg(all(_XM_SSE_INTRINSICS_, not(_XM_AVX2_INTRINSICS_)))]
954 unsafe {
955 let vTemp1: XMVECTOR = _mm_shuffle_ps(M.r[0], M.r[1], _MM_SHUFFLE(1, 0, 1, 0));
957 let vTemp3: XMVECTOR = _mm_shuffle_ps(M.r[0], M.r[1], _MM_SHUFFLE(3, 2, 3, 2));
959 let vTemp2: XMVECTOR = _mm_shuffle_ps(M.r[2], M.r[3], _MM_SHUFFLE(1, 0, 1, 0));
961 let vTemp4: XMVECTOR = _mm_shuffle_ps(M.r[2], M.r[3], _MM_SHUFFLE(3, 2, 3, 2));
963
964 let mut mResult: XMMATRIX = crate::undefined();
965 mResult.r[0] = _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(2, 0, 2, 0));
967 mResult.r[1] = _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(3, 1, 3, 1));
969 mResult.r[2] = _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(2, 0, 2, 0));
971 mResult.r[3] = _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(3, 1, 3, 1));
973 return mResult;
974 }
975}
976
977#[inline]
995pub fn XMMatrixInverse(
996 pDeterminant: Option<&mut XMVECTOR>,
997 M: FXMMATRIX,
998) -> XMMATRIX
999{
1000 #[cfg(any(_XM_NO_INTRINSICS_, _XM_ARM_NEON_INTRINSICS_))]
1001 unsafe {
1002 let MT: XMMATRIX = XMMatrixTranspose(M);
1003
1004 let mut V0: [XMVECTOR; 4] = crate::undefined();
1005 let mut V1: [XMVECTOR; 4] = crate::undefined();
1006 V0[0] = <(XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(MT.r[2]);
1007 V1[0] = <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_W)>::XMVectorSwizzle(MT.r[3]);
1008 V0[1] = <(XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(MT.r[0]);
1009 V1[1] = <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_W)>::XMVectorSwizzle(MT.r[1]);
1010 V1[2] = <(XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_1Y, XM_PERMUTE_1W)>::XMVectorPermute(MT.r[3], MT.r[1]);
1011 V0[2] = <(XM_PERMUTE_0X, XM_PERMUTE_0Z, XM_PERMUTE_1X, XM_PERMUTE_1Z)>::XMVectorPermute(MT.r[2], MT.r[0]);
1012
1013 let mut D0: XMVECTOR = XMVectorMultiply(V0[0], V1[0]);
1014 let mut D1: XMVECTOR = XMVectorMultiply(V0[1], V1[1]);
1015 let mut D2: XMVECTOR = XMVectorMultiply(V0[2], V1[2]);
1016
1017 V0[0] = <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_W)>::XMVectorSwizzle(MT.r[2]);
1018 V1[0] = <(XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(MT.r[3]);
1019 V0[1] = <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_W)>::XMVectorSwizzle(MT.r[0]);
1020 V1[1] = <(XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(MT.r[1]);
1021 V0[2] = <(XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_1Y, XM_PERMUTE_1W)>::XMVectorPermute(MT.r[2], MT.r[0]);
1022 V1[2] = <(XM_PERMUTE_0X, XM_PERMUTE_0Z, XM_PERMUTE_1X, XM_PERMUTE_1Z)>::XMVectorPermute(MT.r[3], MT.r[1]);
1023
1024 D0 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], D0);
1025 D1 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], D1);
1026 D2 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], D2);
1027
1028 V0[0] = <(XM_SWIZZLE_Y, XM_SWIZZLE_Z, XM_SWIZZLE_X, XM_SWIZZLE_Y)>::XMVectorSwizzle(MT.r[1]);
1029 V1[0] = <(XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_0X)>::XMVectorPermute(D0, D2);
1030 V0[1] = <(XM_SWIZZLE_Z, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_X)>::XMVectorSwizzle(MT.r[0]);
1031 V1[1] = <(XM_PERMUTE_0W, XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_0Z)>::XMVectorPermute(D0, D2);
1032 V0[2] = <(XM_SWIZZLE_Y, XM_SWIZZLE_Z, XM_SWIZZLE_X, XM_SWIZZLE_Y)>::XMVectorSwizzle(MT.r[3]);
1033 V1[2] = <(XM_PERMUTE_1W, XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_0X)>::XMVectorPermute(D1, D2);
1034 V0[3] = <(XM_SWIZZLE_Z, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_X)>::XMVectorSwizzle(MT.r[2]);
1035 V1[3] = <(XM_PERMUTE_0W, XM_PERMUTE_1W, XM_PERMUTE_0Y, XM_PERMUTE_0Z)>::XMVectorPermute(D1, D2);
1036
1037 let mut C0: XMVECTOR = XMVectorMultiply(V0[0], V1[0]);
1038 let mut C2: XMVECTOR = XMVectorMultiply(V0[1], V1[1]);
1039 let mut C4: XMVECTOR = XMVectorMultiply(V0[2], V1[2]);
1040 let mut C6: XMVECTOR = XMVectorMultiply(V0[3], V1[3]);
1041
1042 V0[0] = <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_Y, XM_SWIZZLE_Z)>::XMVectorSwizzle(MT.r[1]);
1043 V1[0] = <(XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_1X)>::XMVectorPermute(D0, D2);
1044 V0[1] = <(XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_Y)>::XMVectorSwizzle(MT.r[0]);
1045 V1[1] = <(XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_0X)>::XMVectorPermute(D0, D2);
1046 V0[2] = <(XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_Y, XM_SWIZZLE_Z)>::XMVectorSwizzle(MT.r[3]);
1047 V1[2] = <(XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_1Z)>::XMVectorPermute(D1, D2);
1048 V0[3] = <(XM_SWIZZLE_W, XM_SWIZZLE_Z, XM_SWIZZLE_W, XM_SWIZZLE_Y)>::XMVectorSwizzle(MT.r[2]);
1049 V1[3] = <(XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1Z, XM_PERMUTE_0X)>::XMVectorPermute(D1, D2);
1050
1051 C0 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], C0);
1052 C2 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], C2);
1053 C4 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], C4);
1054 C6 = XMVectorNegativeMultiplySubtract(V0[3], V1[3], C6);
1055
1056 V0[0] = <(XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_W, XM_SWIZZLE_X)>::XMVectorSwizzle(MT.r[1]);
1057 V1[0] = <(XM_PERMUTE_0Z, XM_PERMUTE_1Y, XM_PERMUTE_1X, XM_PERMUTE_0Z)>::XMVectorPermute(D0, D2);
1058 V0[1] = <(XM_SWIZZLE_Y, XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_Z)>::XMVectorSwizzle(MT.r[0]);
1059 V1[1] = <(XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_1X)>::XMVectorPermute(D0, D2);
1060 V0[2] = <(XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_W, XM_SWIZZLE_X)>::XMVectorSwizzle(MT.r[3]);
1061 V1[2] = <(XM_PERMUTE_0Z, XM_PERMUTE_1W, XM_PERMUTE_1Z, XM_PERMUTE_0Z)>::XMVectorPermute(D1, D2);
1062 V0[3] = <(XM_SWIZZLE_Y, XM_SWIZZLE_W, XM_SWIZZLE_X, XM_SWIZZLE_Z)>::XMVectorSwizzle(MT.r[2]);
1063 V1[3] = <(XM_PERMUTE_1W, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_1Z)>::XMVectorPermute(D1, D2);
1064
1065 let C1: XMVECTOR = XMVectorNegativeMultiplySubtract(V0[0], V1[0], C0);
1066 C0 = XMVectorMultiplyAdd(V0[0], V1[0], C0);
1067 let C3: XMVECTOR = XMVectorMultiplyAdd(V0[1], V1[1], C2);
1068 C2 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], C2);
1069 let C5: XMVECTOR = XMVectorNegativeMultiplySubtract(V0[2], V1[2], C4);
1070 C4 = XMVectorMultiplyAdd(V0[2], V1[2], C4);
1071 let C7: XMVECTOR = XMVectorMultiplyAdd(V0[3], V1[3], C6);
1072 C6 = XMVectorNegativeMultiplySubtract(V0[3], V1[3], C6);
1073
1074 let mut R: XMMATRIX = crate::undefined();
1075 R.r[0] = XMVectorSelect(C0, C1, g_XMSelect0101.v);
1076 R.r[1] = XMVectorSelect(C2, C3, g_XMSelect0101.v);
1077 R.r[2] = XMVectorSelect(C4, C5, g_XMSelect0101.v);
1078 R.r[3] = XMVectorSelect(C6, C7, g_XMSelect0101.v);
1079
1080 let Determinant: XMVECTOR = XMVector4Dot(R.r[0], MT.r[0]);
1081
1082 match pDeterminant {
1083 Some(determinant) => *determinant = Determinant,
1084 None => ()
1085 };
1086
1087 let Reciprocal: XMVECTOR = XMVectorReciprocal(Determinant);
1088
1089 let mut Result: XMMATRIX = crate::undefined();
1090 Result.r[0] = XMVectorMultiply(R.r[0], Reciprocal);
1091 Result.r[1] = XMVectorMultiply(R.r[1], Reciprocal);
1092 Result.r[2] = XMVectorMultiply(R.r[2], Reciprocal);
1093 Result.r[3] = XMVectorMultiply(R.r[3], Reciprocal);
1094 return Result;
1095 }
1096
1097 #[cfg(_XM_SSE_INTRINSICS_)]
1098 unsafe {
1099 let vTemp1: XMVECTOR = _mm_shuffle_ps(M.r[0], M.r[1], _MM_SHUFFLE(1, 0, 1, 0));
1101 let vTemp3: XMVECTOR = _mm_shuffle_ps(M.r[0], M.r[1], _MM_SHUFFLE(3, 2, 3, 2));
1102 let vTemp2: XMVECTOR = _mm_shuffle_ps(M.r[2], M.r[3], _MM_SHUFFLE(1, 0, 1, 0));
1103 let vTemp4: XMVECTOR = _mm_shuffle_ps(M.r[2], M.r[3], _MM_SHUFFLE(3, 2, 3, 2));
1104
1105 let mut MT: XMMATRIX = crate::undefined();
1106 MT.r[0] = _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(2, 0, 2, 0));
1107 MT.r[1] = _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(3, 1, 3, 1));
1108 MT.r[2] = _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(2, 0, 2, 0));
1109 MT.r[3] = _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(3, 1, 3, 1));
1110
1111 let mut V00: XMVECTOR = XM_PERMUTE_PS!(MT.r[2], _MM_SHUFFLE(1, 1, 0, 0));
1112 let mut V10: XMVECTOR = XM_PERMUTE_PS!(MT.r[3], _MM_SHUFFLE(3, 2, 3, 2));
1113 let mut V01: XMVECTOR = XM_PERMUTE_PS!(MT.r[0], _MM_SHUFFLE(1, 1, 0, 0));
1114 let mut V11: XMVECTOR = XM_PERMUTE_PS!(MT.r[1], _MM_SHUFFLE(3, 2, 3, 2));
1115 let mut V02: XMVECTOR = _mm_shuffle_ps(MT.r[2], MT.r[0], _MM_SHUFFLE(2, 0, 2, 0));
1116 let mut V12: XMVECTOR = _mm_shuffle_ps(MT.r[3], MT.r[1], _MM_SHUFFLE(3, 1, 3, 1));
1117
1118 let mut D0: XMVECTOR = _mm_mul_ps(V00, V10);
1119 let mut D1: XMVECTOR = _mm_mul_ps(V01, V11);
1120 let mut D2: XMVECTOR = _mm_mul_ps(V02, V12);
1121
1122 V00 = XM_PERMUTE_PS!(MT.r[2], _MM_SHUFFLE(3, 2, 3, 2));
1123 V10 = XM_PERMUTE_PS!(MT.r[3], _MM_SHUFFLE(1, 1, 0, 0));
1124 V01 = XM_PERMUTE_PS!(MT.r[0], _MM_SHUFFLE(3, 2, 3, 2));
1125 V11 = XM_PERMUTE_PS!(MT.r[1], _MM_SHUFFLE(1, 1, 0, 0));
1126 V02 = _mm_shuffle_ps(MT.r[2], MT.r[0], _MM_SHUFFLE(3, 1, 3, 1));
1127 V12 = _mm_shuffle_ps(MT.r[3], MT.r[1], _MM_SHUFFLE(2, 0, 2, 0));
1128
1129 D0 = XM_FNMADD_PS!(V00, V10, D0);
1130 D1 = XM_FNMADD_PS!(V01, V11, D1);
1131 D2 = XM_FNMADD_PS!(V02, V12, D2);
1132 V11 = _mm_shuffle_ps(D0, D2, _MM_SHUFFLE(1, 1, 3, 1));
1134 V00 = XM_PERMUTE_PS!(MT.r[1], _MM_SHUFFLE(1, 0, 2, 1));
1135 V10 = _mm_shuffle_ps(V11, D0, _MM_SHUFFLE(0, 3, 0, 2));
1136 V01 = XM_PERMUTE_PS!(MT.r[0], _MM_SHUFFLE(0, 1, 0, 2));
1137 V11 = _mm_shuffle_ps(V11, D0, _MM_SHUFFLE(2, 1, 2, 1));
1138 let mut V13: XMVECTOR = _mm_shuffle_ps(D1, D2, _MM_SHUFFLE(3, 3, 3, 1));
1140 V02 = XM_PERMUTE_PS!(MT.r[3], _MM_SHUFFLE(1, 0, 2, 1));
1141 V12 = _mm_shuffle_ps(V13, D1, _MM_SHUFFLE(0, 3, 0, 2));
1142 let mut V03: XMVECTOR = XM_PERMUTE_PS!(MT.r[2], _MM_SHUFFLE(0, 1, 0, 2));
1143 V13 = _mm_shuffle_ps(V13, D1, _MM_SHUFFLE(2, 1, 2, 1));
1144
1145 let mut C0: XMVECTOR = _mm_mul_ps(V00, V10);
1146 let mut C2: XMVECTOR = _mm_mul_ps(V01, V11);
1147 let mut C4: XMVECTOR = _mm_mul_ps(V02, V12);
1148 let mut C6: XMVECTOR = _mm_mul_ps(V03, V13);
1149
1150 V11 = _mm_shuffle_ps(D0, D2, _MM_SHUFFLE(0, 0, 1, 0));
1152 V00 = XM_PERMUTE_PS!(MT.r[1], _MM_SHUFFLE(2, 1, 3, 2));
1153 V10 = _mm_shuffle_ps(D0, V11, _MM_SHUFFLE(2, 1, 0, 3));
1154 V01 = XM_PERMUTE_PS!(MT.r[0], _MM_SHUFFLE(1, 3, 2, 3));
1155 V11 = _mm_shuffle_ps(D0, V11, _MM_SHUFFLE(0, 2, 1, 2));
1156 V13 = _mm_shuffle_ps(D1, D2, _MM_SHUFFLE(2, 2, 1, 0));
1158 V02 = XM_PERMUTE_PS!(MT.r[3], _MM_SHUFFLE(2, 1, 3, 2));
1159 V12 = _mm_shuffle_ps(D1, V13, _MM_SHUFFLE(2, 1, 0, 3));
1160 V03 = XM_PERMUTE_PS!(MT.r[2], _MM_SHUFFLE(1, 3, 2, 3));
1161 V13 = _mm_shuffle_ps(D1, V13, _MM_SHUFFLE(0, 2, 1, 2));
1162
1163 C0 = XM_FNMADD_PS!(V00, V10, C0);
1164 C2 = XM_FNMADD_PS!(V01, V11, C2);
1165 C4 = XM_FNMADD_PS!(V02, V12, C4);
1166 C6 = XM_FNMADD_PS!(V03, V13, C6);
1167
1168 V00 = XM_PERMUTE_PS!(MT.r[1], _MM_SHUFFLE(0, 3, 0, 3));
1169 V10 = _mm_shuffle_ps(D0, D2, _MM_SHUFFLE(1, 0, 2, 2));
1171 V10 = XM_PERMUTE_PS!(V10, _MM_SHUFFLE(0, 2, 3, 0));
1172 V01 = XM_PERMUTE_PS!(MT.r[0], _MM_SHUFFLE(2, 0, 3, 1));
1173 V11 = _mm_shuffle_ps(D0, D2, _MM_SHUFFLE(1, 0, 3, 0));
1175 V11 = XM_PERMUTE_PS!(V11, _MM_SHUFFLE(2, 1, 0, 3));
1176 V02 = XM_PERMUTE_PS!(MT.r[3], _MM_SHUFFLE(0, 3, 0, 3));
1177 V12 = _mm_shuffle_ps(D1, D2, _MM_SHUFFLE(3, 2, 2, 2));
1179 V12 = XM_PERMUTE_PS!(V12, _MM_SHUFFLE(0, 2, 3, 0));
1180 V03 = XM_PERMUTE_PS!(MT.r[2], _MM_SHUFFLE(2, 0, 3, 1));
1181 V13 = _mm_shuffle_ps(D1, D2, _MM_SHUFFLE(3, 2, 3, 0));
1183 V13 = XM_PERMUTE_PS!(V13, _MM_SHUFFLE(2, 1, 0, 3));
1184
1185 V00 = _mm_mul_ps(V00, V10);
1186 V01 = _mm_mul_ps(V01, V11);
1187 V02 = _mm_mul_ps(V02, V12);
1188 V03 = _mm_mul_ps(V03, V13);
1189 let C1: XMVECTOR = _mm_sub_ps(C0, V00);
1190 C0 = _mm_add_ps(C0, V00);
1191 let C3: XMVECTOR = _mm_add_ps(C2, V01);
1192 C2 = _mm_sub_ps(C2, V01);
1193 let C5: XMVECTOR = _mm_sub_ps(C4, V02);
1194 C4 = _mm_add_ps(C4, V02);
1195 let C7: XMVECTOR = _mm_add_ps(C6, V03);
1196 C6 = _mm_sub_ps(C6, V03);
1197
1198 C0 = _mm_shuffle_ps(C0, C1, _MM_SHUFFLE(3, 1, 2, 0));
1199 C2 = _mm_shuffle_ps(C2, C3, _MM_SHUFFLE(3, 1, 2, 0));
1200 C4 = _mm_shuffle_ps(C4, C5, _MM_SHUFFLE(3, 1, 2, 0));
1201 C6 = _mm_shuffle_ps(C6, C7, _MM_SHUFFLE(3, 1, 2, 0));
1202 C0 = XM_PERMUTE_PS!(C0, _MM_SHUFFLE(3, 1, 2, 0));
1203 C2 = XM_PERMUTE_PS!(C2, _MM_SHUFFLE(3, 1, 2, 0));
1204 C4 = XM_PERMUTE_PS!(C4, _MM_SHUFFLE(3, 1, 2, 0));
1205 C6 = XM_PERMUTE_PS!(C6, _MM_SHUFFLE(3, 1, 2, 0));
1206 let mut vTemp: XMVECTOR = XMVector4Dot(C0, MT.r[0]);
1208
1209 if let Some(determinant) = pDeterminant {
1210 *determinant = vTemp;
1211 }
1212
1213 vTemp = _mm_div_ps(g_XMOne.v, vTemp);
1214 let mut mResult: XMMATRIX = crate::undefined();
1215 mResult.r[0] = _mm_mul_ps(C0, vTemp);
1216 mResult.r[1] = _mm_mul_ps(C2, vTemp);
1217 mResult.r[2] = _mm_mul_ps(C4, vTemp);
1218 mResult.r[3] = _mm_mul_ps(C6, vTemp);
1219 return mResult;
1220 }
1221}
1222
1223#[inline]
1227pub fn XMMatrixVectorTensorProduct(
1228 V1: FXMVECTOR,
1229 V2: FXMVECTOR
1230) -> XMMATRIX
1231{
1232 unsafe {
1233 let mut mResult: XMMATRIX = crate::undefined();
1234 type _0 = XM_SWIZZLE_X;
1235 type _1 = XM_SWIZZLE_Y;
1236 type _2 = XM_SWIZZLE_Z;
1237 type _3 = XM_SWIZZLE_W;
1238 mResult.r[0] = XMVectorMultiply(<(_0, _0, _0, _0)>::XMVectorSwizzle(V1), V2);
1239 mResult.r[1] = XMVectorMultiply(<(_1, _1, _1, _1)>::XMVectorSwizzle(V1), V2);
1240 mResult.r[2] = XMVectorMultiply(<(_2, _2, _2, _2)>::XMVectorSwizzle(V1), V2);
1241 mResult.r[3] = XMVectorMultiply(<(_3, _3, _3, _3)>::XMVectorSwizzle(V1), V2);
1242 return mResult;
1243 }
1244}
1245
1246#[inline]
1260pub fn XMMatrixDeterminant(
1261 M: FXMMATRIX,
1262) -> FXMVECTOR
1263{
1264 unsafe {
1265 const Sign: XMVECTORF32 = XMVECTORF32 { f: [ 1.0, -1.0, 1.0, -1.0 ] };
1266
1267 let mut V0: XMVECTOR = <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_X)>::XMVectorSwizzle(M.r[2]);
1268 let mut V1: XMVECTOR = <(XM_SWIZZLE_Z, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(M.r[3]);
1269 let mut V2: XMVECTOR = <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_X)>::XMVectorSwizzle(M.r[2]);
1270 let mut V3: XMVECTOR = <(XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(M.r[3]);
1271 let mut V4: XMVECTOR = <(XM_SWIZZLE_Z, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(M.r[2]);
1272 let mut V5: XMVECTOR = <(XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(M.r[3]);
1273
1274 let mut P0: XMVECTOR = XMVectorMultiply(V0, V1);
1275 let mut P1: XMVECTOR = XMVectorMultiply(V2, V3);
1276 let mut P2: XMVECTOR = XMVectorMultiply(V4, V5);
1277
1278 V0 = <(XM_SWIZZLE_Z, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(M.r[2]);
1279 V1 = <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_X)>::XMVectorSwizzle(M.r[3]);
1280 V2 = <(XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(M.r[2]);
1281 V3 = <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_X)>::XMVectorSwizzle(M.r[3]);
1282 V4 = <(XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(M.r[2]);
1283 V5 = <(XM_SWIZZLE_Z, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(M.r[3]);
1284
1285 P0 = XMVectorNegativeMultiplySubtract(V0, V1, P0);
1286 P1 = XMVectorNegativeMultiplySubtract(V2, V3, P1);
1287 P2 = XMVectorNegativeMultiplySubtract(V4, V5, P2);
1288
1289 V0 = <(XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_W, XM_SWIZZLE_Z)>::XMVectorSwizzle(M.r[1]);
1290 V1 = <(XM_SWIZZLE_Z, XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_Y)>::XMVectorSwizzle(M.r[1]);
1291 V2 = <(XM_SWIZZLE_Y, XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_X)>::XMVectorSwizzle(M.r[1]);
1292
1293 let S: XMVECTOR = XMVectorMultiply(M.r[0], Sign.v);
1294 let mut R: XMVECTOR = XMVectorMultiply(V0, P0);
1295 R = XMVectorNegativeMultiplySubtract(V1, P1, R);
1296 R = XMVectorMultiplyAdd(V2, P2, R);
1297
1298 return XMVector4Dot(S, R);
1299 }
1300}
1301
1302#[inline]
1322pub fn XMMatrixDecompose(
1323 outScale: &mut XMVECTOR,
1324 outRotQuat: &mut XMVECTOR,
1325 outTrans: &mut XMVECTOR,
1326 M: FXMMATRIX,
1327) -> bool
1328{
1329 macro_rules! XM3RANKDECOMPOSE {
1330 ($a:expr, $b:expr, $c:expr, $x:expr, $y:expr, $z:expr) => {
1331 if $x < $y {
1332 if $y < $z {
1333 $a = 2;
1334 $b = 1;
1335 $c = 0;
1336 } else {
1337 $a = 1;
1338
1339 if $x < $z {
1340 $b = 2;
1341 $c = 0;
1342 } else {
1343 $b = 0;
1344 $c = 2;
1345 }
1346 }
1347 } else {
1348 if $x < $z {
1349 $a = 2;
1350 $b = 0;
1351 $c = 1;
1352 } else {
1353 $a = 0;
1354
1355 if $y < $z {
1356 $b = 2;
1357 $c = 1;
1358 } else {
1359 $b = 1;
1360 $c = 2;
1361 }
1362 }
1363 }
1364 }
1365 }
1366
1367 const XM3_DECOMP_EPSILON: f32 = 0.0001;
1368
1369 unsafe {
1370 static pvCanonicalBasis: [&XMVECTOR; 3] = unsafe {[
1372 &g_XMIdentityR0.v,
1373 &g_XMIdentityR2.v,
1374 &g_XMIdentityR3.v,
1375 ]};
1376
1377 *outTrans = M.r[3];
1379
1380 let mut ppvBasis: [*mut XMVECTOR; 3] = [std::ptr::null_mut(); 3];
1381 let mut matTemp: XMMATRIX = crate::undefined();
1382 ppvBasis[0] = &mut matTemp.r[0];
1383 ppvBasis[1] = &mut matTemp.r[1];
1384 ppvBasis[2] = &mut matTemp.r[2];
1385
1386 matTemp.r[0] = M.r[0];
1387 matTemp.r[1] = M.r[1];
1388 matTemp.r[2] = M.r[2];
1389 matTemp.r[3] = g_XMIdentityR3.v;
1390
1391 let pfScales = mem::transmute::<_, *mut f32>(outScale);
1392 XMVectorGetXPtr(&mut *pfScales.add(0), XMVector3Length(*ppvBasis[0]));
1393 XMVectorGetXPtr(&mut *pfScales.add(1), XMVector3Length(*ppvBasis[1]));
1394 XMVectorGetXPtr(&mut *pfScales.add(2), XMVector3Length(*ppvBasis[2]));
1395 *pfScales.add(3) = 0.0;
1396
1397 let a: usize;
1398 let b: usize;
1399 let c: usize;
1400
1401 let x = *pfScales.add(0);
1402 let y = *pfScales.add(1);
1403 let z = *pfScales.add(2);
1404 XM3RANKDECOMPOSE!(a, b, c, x, y, z);
1405
1406 if (*pfScales.add(a) < XM3_DECOMP_EPSILON)
1407 {
1408 *ppvBasis[a] = *pvCanonicalBasis[a];
1409 }
1410
1411 *ppvBasis[a] = XMVector3Normalize(*ppvBasis[a]);
1412
1413 if (*pfScales.add(b) < XM3_DECOMP_EPSILON)
1414 {
1415 let _aa: usize;
1416 let _bb: usize;
1417 let cc: usize;
1418
1419 let fAbsX = fabsf(XMVectorGetX(*ppvBasis[a]));
1420 let fAbsY = fabsf(XMVectorGetY(*ppvBasis[a]));
1421 let fAbsZ = fabsf(XMVectorGetZ(*ppvBasis[a]));
1422
1423 XM3RANKDECOMPOSE!(_aa, _bb, cc, fAbsX, fAbsY, fAbsZ);
1424
1425 *ppvBasis[b] = XMVector3Cross(*ppvBasis[a], *pvCanonicalBasis[cc]);
1426 }
1427
1428 *ppvBasis[b] = XMVector3Normalize(*ppvBasis[b]);
1429
1430 if (*pfScales.add(c) < XM3_DECOMP_EPSILON)
1431 {
1432 *ppvBasis[c] = XMVector3Cross(*ppvBasis[a], *ppvBasis[b]);
1433 }
1434
1435 *ppvBasis[c] = XMVector3Normalize(*ppvBasis[c]);
1436
1437 let mut fDet: f32 = XMVectorGetX(XMMatrixDeterminant(matTemp));
1438
1439 if (fDet < 0.0)
1441 {
1442 *pfScales.add(a) = -(*pfScales.add(a));
1444 *ppvBasis[a] = XMVectorNegate(*ppvBasis[a]);
1445
1446 fDet = -fDet;
1447 }
1448
1449 fDet -= 1.0;
1450 fDet *= fDet;
1451
1452 if (XM3_DECOMP_EPSILON < fDet)
1453 {
1454 return false;
1456 }
1457
1458 *outRotQuat = XMQuaternionRotationMatrix(matTemp);
1460 return true;
1461 }
1462}
1463
1464#[test]
1465fn test_XMMatrixDecompose() {
1466 let scaling_origin = XMVectorSet(0.0, 0.0, 0.0, 0.0);
1467 let scaling_orientation_quaternion = XMQuaternionRotationRollPitchYaw(0.1 ,0.2, 0.3);
1468 let scaling = XMVectorSet(1.1, 1.2, 1.3, 0.0);
1469 let rotation_origin = XMVectorSet(0.0, 0.0, 0.0, 0.0);
1470 let rotation_quaternion = XMQuaternionRotationRollPitchYaw(0.4 ,0.5, 0.6);
1471 let translation = XMVectorSet(7.0, 8.0, 9.0, 0.0);
1472
1473 let transform = XMMatrixTransformation(
1474 scaling_origin,
1475 scaling_orientation_quaternion,
1476 scaling,
1477 rotation_origin,
1478 rotation_quaternion,
1479 translation
1480 );
1481
1482 let mut out_scale = XMVectorZero();
1483 let mut out_rot_quat = XMVectorZero();
1484 let mut out_trans = XMVectorZero();
1485
1486 assert!(XMMatrixDecompose(&mut out_scale, &mut out_rot_quat, &mut out_trans, transform));
1487
1488 let epsilon = XMVectorReplicate(1.0e-1);
1489
1490 assert!(XMVector3NearEqual(out_scale, scaling, epsilon));
1491 assert!(XMVector4NearEqual(out_rot_quat, rotation_quaternion, epsilon));
1492 assert!(XMVector3NearEqual(out_trans, translation, epsilon));
1493}
1494
1495#[inline]
1509pub fn XMMatrixIdentity() -> XMMATRIX
1510{
1511 unsafe {
1512 let mut M: XMMATRIX = crate::undefined();
1513 M.r[0] = g_XMIdentityR0.v;
1514 M.r[1] = g_XMIdentityR1.v;
1515 M.r[2] = g_XMIdentityR2.v;
1516 M.r[3] = g_XMIdentityR3.v;
1517 return M;
1518 }
1519}
1520
1521#[inline]
1565pub fn XMMatrixSet(
1566 m00: f32, m01: f32, m02: f32, m03: f32,
1567 m10: f32, m11: f32, m12: f32, m13: f32,
1568 m20: f32, m21: f32, m22: f32, m23: f32,
1569 m30: f32, m31: f32, m32: f32, m33: f32
1570) -> XMMATRIX
1571{
1572 let mut M: XMMATRIX = unsafe { crate::undefined() };
1573
1574 #[cfg(_XM_NO_INTRINSICS_)]
1575 unsafe {
1576 M.m[0][0] = m00; M.m[0][1] = m01; M.m[0][2] = m02; M.m[0][3] = m03;
1577 M.m[1][0] = m10; M.m[1][1] = m11; M.m[1][2] = m12; M.m[1][3] = m13;
1578 M.m[2][0] = m20; M.m[2][1] = m21; M.m[2][2] = m22; M.m[2][3] = m23;
1579 M.m[3][0] = m30; M.m[3][1] = m31; M.m[3][2] = m32; M.m[3][3] = m33;
1580 }
1581
1582 #[cfg(not(_XM_NO_INTRINSICS_))]
1583 unsafe {
1584 M.r[0] = XMVectorSet(m00, m01, m02, m03);
1585 M.r[1] = XMVectorSet(m10, m11, m12, m13);
1586 M.r[2] = XMVectorSet(m20, m21, m22, m23);
1587 M.r[3] = XMVectorSet(m30, m31, m32, m33);
1588 }
1589
1590 return M;
1591}
1592
1593#[inline]
1611pub fn XMMatrixTranslation(
1612 OffsetX: f32,
1613 OffsetY: f32,
1614 OffsetZ: f32,
1615) -> XMMATRIX
1616{
1617 let mut M: XMMATRIX = unsafe { crate::undefined() };
1618
1619 #[cfg(_XM_NO_INTRINSICS_)]
1620 unsafe {
1621 M.m[0][0] = 1.0;
1622 M.m[0][1] = 0.0;
1623 M.m[0][2] = 0.0;
1624 M.m[0][3] = 0.0;
1625
1626 M.m[1][0] = 0.0;
1627 M.m[1][1] = 1.0;
1628 M.m[1][2] = 0.0;
1629 M.m[1][3] = 0.0;
1630
1631 M.m[2][0] = 0.0;
1632 M.m[2][1] = 0.0;
1633 M.m[2][2] = 1.0;
1634 M.m[2][3] = 0.0;
1635
1636 M.m[3][0] = OffsetX;
1637 M.m[3][1] = OffsetY;
1638 M.m[3][2] = OffsetZ;
1639 M.m[3][3] = 1.0;
1640 }
1641
1642 #[cfg(any(_XM_SSE_INTRINSICS_, _XM_ARM_NEON_INTRINSICS_))]
1643 unsafe {
1644 M.r[0] = g_XMIdentityR0.v;
1645 M.r[1] = g_XMIdentityR1.v;
1646 M.r[2] = g_XMIdentityR2.v;
1647 M.r[3] = XMVectorSet(OffsetX, OffsetY, OffsetZ, 1.0);
1648 }
1649
1650 return M;
1651}
1652
1653#[inline]
1667pub fn XMMatrixTranslationFromVector(
1668 Offset: XMVECTOR,
1669) -> XMMATRIX
1670{
1671 #[cfg(_XM_NO_INTRINSICS_)]
1672 unsafe {
1673 let mut M: XMMATRIX = crate::undefined();
1674 M.m[0][0] = 1.0;
1675 M.m[0][1] = 0.0;
1676 M.m[0][2] = 0.0;
1677 M.m[0][3] = 0.0;
1678
1679 M.m[1][0] = 0.0;
1680 M.m[1][1] = 1.0;
1681 M.m[1][2] = 0.0;
1682 M.m[1][3] = 0.0;
1683
1684 M.m[2][0] = 0.0;
1685 M.m[2][1] = 0.0;
1686 M.m[2][2] = 1.0;
1687 M.m[2][3] = 0.0;
1688
1689 M.m[3][0] = Offset.vector4_f32[0];
1690 M.m[3][1] = Offset.vector4_f32[1];
1691 M.m[3][2] = Offset.vector4_f32[2];
1692 M.m[3][3] = 1.0;
1693 return M;
1694 }
1695
1696 #[cfg(any(_XM_SSE_INTRINSICS_, _XM_ARM_NEON_INTRINSICS_))]
1697 unsafe {
1698 let mut M: XMMATRIX = crate::undefined();
1699 M.r[0] = g_XMIdentityR0.v;
1700 M.r[1] = g_XMIdentityR1.v;
1701 M.r[2] = g_XMIdentityR2.v;
1702 M.r[3] = XMVectorSelect(g_XMIdentityR3.v, Offset, g_XMSelect1110.v);
1703 return M;
1704 }
1705}
1706
1707#[inline]
1725pub fn XMMatrixScaling(
1726 ScaleX: f32,
1727 ScaleY: f32,
1728 ScaleZ: f32,
1729) -> XMMATRIX
1730{
1731 #[cfg(_XM_NO_INTRINSICS_)]
1732 unsafe {
1733 let mut M: XMMATRIX = crate::undefined();
1734 M.m[0][0] = ScaleX;
1735 M.m[0][1] = 0.0;
1736 M.m[0][2] = 0.0;
1737 M.m[0][3] = 0.0;
1738
1739 M.m[1][0] = 0.0;
1740 M.m[1][1] = ScaleY;
1741 M.m[1][2] = 0.0;
1742 M.m[1][3] = 0.0;
1743
1744 M.m[2][0] = 0.0;
1745 M.m[2][1] = 0.0;
1746 M.m[2][2] = ScaleZ;
1747 M.m[2][3] = 0.0;
1748
1749 M.m[3][0] = 0.0;
1750 M.m[3][1] = 0.0;
1751 M.m[3][2] = 0.0;
1752 M.m[3][3] = 1.0;
1753 return M;
1754 }
1755
1756 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
1757 unsafe {
1758 unimplemented!()
1759 }
1760
1761 #[cfg(_XM_SSE_INTRINSICS_)]
1762 unsafe {
1763 let mut M: XMMATRIX = crate::undefined();
1764 M.r[0] = _mm_set_ps(0.0, 0.0, 0.0, ScaleX);
1765 M.r[1] = _mm_set_ps(0.0, 0.0, ScaleY, 0.0);
1766 M.r[2] = _mm_set_ps(0.0, ScaleZ, 0.0, 0.0);
1767 M.r[3] = g_XMIdentityR3.v;
1768 return M;
1769 }
1770}
1771
1772#[inline]
1786pub fn XMMatrixScalingFromVector(
1787 Scale: XMVECTOR,
1788) -> XMMATRIX
1789{
1790 #[cfg(_XM_NO_INTRINSICS_)]
1791 unsafe {
1792 let mut M: XMMATRIX = crate::undefined();
1793 M.m[0][0] = Scale.vector4_f32[0];
1794 M.m[0][1] = 0.0;
1795 M.m[0][2] = 0.0;
1796 M.m[0][3] = 0.0;
1797
1798 M.m[1][0] = 0.0;
1799 M.m[1][1] = Scale.vector4_f32[1];
1800 M.m[1][2] = 0.0;
1801 M.m[1][3] = 0.0;
1802
1803 M.m[2][0] = 0.0;
1804 M.m[2][1] = 0.0;
1805 M.m[2][2] = Scale.vector4_f32[2];
1806 M.m[2][3] = 0.0;
1807
1808 M.m[3][0] = 0.0;
1809 M.m[3][1] = 0.0;
1810 M.m[3][2] = 0.0;
1811 M.m[3][3] = 1.0;
1812 return M;
1813 }
1814
1815 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
1816 unsafe {
1817 unimplemented!()
1818 }
1819
1820 #[cfg(_XM_SSE_INTRINSICS_)]
1821 unsafe {
1822 let mut M: XMMATRIX = crate::undefined();
1823 M.r[0] = _mm_and_ps(Scale, *g_XMMaskX);
1824 M.r[1] = _mm_and_ps(Scale, *g_XMMaskY);
1825 M.r[2] = _mm_and_ps(Scale, *g_XMMaskZ);
1826 M.r[3] = g_XMIdentityR3.v;
1827 return M;
1828 }
1829}
1830
1831#[inline]
1846pub fn XMMatrixRotationX(
1847 Angle: f32,
1848) -> XMMATRIX
1849{
1850 #[cfg(_XM_NO_INTRINSICS_)]
1851 unsafe {
1852 let mut fSinAngle: f32 = 0.0;
1853 let mut fCosAngle: f32 = 0.0;
1854 XMScalarSinCos(&mut fSinAngle, &mut fCosAngle, Angle);
1855
1856 let mut M: XMMATRIX = crate::undefined();
1857 M.m[0][0] = 1.0;
1858 M.m[0][1] = 0.0;
1859 M.m[0][2] = 0.0;
1860 M.m[0][3] = 0.0;
1861
1862 M.m[1][0] = 0.0;
1863 M.m[1][1] = fCosAngle;
1864 M.m[1][2] = fSinAngle;
1865 M.m[1][3] = 0.0;
1866
1867 M.m[2][0] = 0.0;
1868 M.m[2][1] = -fSinAngle;
1869 M.m[2][2] = fCosAngle;
1870 M.m[2][3] = 0.0;
1871
1872 M.m[3][0] = 0.0;
1873 M.m[3][1] = 0.0;
1874 M.m[3][2] = 0.0;
1875 M.m[3][3] = 1.0;
1876 return M;
1877 }
1878
1879 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
1880 {
1881 unimplemented!()
1882 }
1883
1884 #[cfg(_XM_SSE_INTRINSICS_)]
1885 unsafe {
1886 let mut SinAngle: f32 = 0.0;
1887 let mut CosAngle: f32 = 0.0;
1888 XMScalarSinCos(&mut SinAngle, &mut CosAngle, Angle);
1889
1890 let vSin: XMVECTOR = _mm_set_ss(SinAngle);
1891 let mut vCos: XMVECTOR = _mm_set_ss(CosAngle);
1892 vCos = _mm_shuffle_ps(vCos, vSin, _MM_SHUFFLE(3, 0, 0, 3));
1894 let mut M: XMMATRIX = undefined();
1895 M.r[0] = g_XMIdentityR0.v;
1896 M.r[1] = vCos;
1897 vCos = XM_PERMUTE_PS!(vCos, _MM_SHUFFLE(3, 1, 2, 0));
1899 vCos = _mm_mul_ps(vCos, g_XMNegateY.v);
1901 M.r[2] = vCos;
1902 M.r[3] = g_XMIdentityR3.v;
1903 return M;
1904 }
1905}
1906
1907#[inline]
1922pub fn XMMatrixRotationY(
1923 Angle: f32,
1924) -> XMMATRIX
1925{
1926 #[cfg(_XM_NO_INTRINSICS_)]
1927 unsafe {
1928 let mut fSinAngle: f32 = 0.0;
1929 let mut fCosAngle: f32 = 0.0;
1930 XMScalarSinCos(&mut fSinAngle, &mut fCosAngle, Angle);
1931
1932 let mut M: XMMATRIX = crate::undefined();
1933 M.m[0][0] = fCosAngle;
1934 M.m[0][1] = 0.0;
1935 M.m[0][2] = -fSinAngle;
1936 M.m[0][3] = 0.0;
1937
1938 M.m[1][0] = 0.0;
1939 M.m[1][1] = 1.0;
1940 M.m[1][2] = 0.0;
1941 M.m[1][3] = 0.0;
1942
1943 M.m[2][0] = fSinAngle;
1944 M.m[2][1] = 0.0;
1945 M.m[2][2] = fCosAngle;
1946 M.m[2][3] = 0.0;
1947
1948 M.m[3][0] = 0.0;
1949 M.m[3][1] = 0.0;
1950 M.m[3][2] = 0.0;
1951 M.m[3][3] = 1.0;
1952 return M;
1953 }
1954
1955 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
1956 {
1957 unimplemented!()
1958 }
1959
1960 #[cfg(_XM_SSE_INTRINSICS_)]
1961 unsafe {
1962 let mut SinAngle: f32 = 0.0;
1963 let mut CosAngle: f32 = 0.0;
1964 XMScalarSinCos(&mut SinAngle, &mut CosAngle, Angle);
1965
1966 let mut vSin: XMVECTOR = _mm_set_ss(SinAngle);
1967 let vCos: XMVECTOR = _mm_set_ss(CosAngle);
1968 vSin = _mm_shuffle_ps(vSin, vCos, _MM_SHUFFLE(3, 0, 3, 0));
1970 let mut M: XMMATRIX = undefined();
1971 M.r[2] = vSin;
1972 M.r[1] = g_XMIdentityR1.v;
1973 vSin = XM_PERMUTE_PS!(vSin, _MM_SHUFFLE(3, 0, 1, 2));
1975 vSin = _mm_mul_ps(vSin, g_XMNegateZ.v);
1977 M.r[0] = vSin;
1978 M.r[3] = g_XMIdentityR3.v;
1979 return M;
1980 }
1981}
1982
1983#[inline]
1998pub fn XMMatrixRotationZ(
1999 Angle: f32,
2000) -> XMMATRIX
2001{
2002 #[cfg(_XM_NO_INTRINSICS_)]
2003 unsafe {
2004 let mut fSinAngle: f32 = 0.0;
2005 let mut fCosAngle: f32 = 0.0;
2006 XMScalarSinCos(&mut fSinAngle, &mut fCosAngle, Angle);
2007
2008 let mut M: XMMATRIX = crate::undefined();
2009 M.m[0][0] = fCosAngle;
2010 M.m[0][1] = fSinAngle;
2011 M.m[0][2] = 0.0;
2012 M.m[0][3] = 0.0;
2013
2014 M.m[1][0] = -fSinAngle;
2015 M.m[1][1] = fCosAngle;
2016 M.m[1][2] = 0.0;
2017 M.m[1][3] = 0.0;
2018
2019 M.m[2][0] = 0.0;
2020 M.m[2][1] = 0.0;
2021 M.m[2][2] = 1.0;
2022 M.m[2][3] = 0.0;
2023
2024 M.m[3][0] = 0.0;
2025 M.m[3][1] = 0.0;
2026 M.m[3][2] = 0.0;
2027 M.m[3][3] = 1.0;
2028 return M;
2029 }
2030
2031 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
2032 {
2033 unimplemented!()
2034 }
2035
2036 #[cfg(_XM_SSE_INTRINSICS_)]
2037 unsafe {
2038 let mut SinAngle: f32 = 0.0;
2039 let mut CosAngle: f32 = 0.0;
2040 XMScalarSinCos(&mut SinAngle, &mut CosAngle, Angle);
2041
2042 let vSin: XMVECTOR = _mm_set_ss(SinAngle);
2043 let mut vCos: XMVECTOR = _mm_set_ss(CosAngle);
2044 vCos = _mm_unpacklo_ps(vCos, vSin);
2046 let mut M: XMMATRIX = undefined();
2047 M.r[0] = vCos;
2048 vCos = XM_PERMUTE_PS!(vCos, _MM_SHUFFLE(3, 2, 0, 1));
2050 vCos = _mm_mul_ps(vCos, g_XMNegateX.v);
2052 M.r[1] = vCos;
2053 M.r[2] = g_XMIdentityR2.v;
2054 M.r[3] = g_XMIdentityR3.v;
2055 return M;
2056 }
2057}
2058
2059#[inline]
2085pub fn XMMatrixRotationRollPitchYaw(
2086 Pitch: f32,
2087 Yaw: f32,
2088 Roll: f32,
2089) -> XMMATRIX
2090{
2091 let Angles: XMVECTOR = XMVectorSet(Pitch, Yaw, Roll, 0.0);
2092 return XMMatrixRotationRollPitchYawFromVector(Angles);
2093}
2094
2095#[inline]
2117pub fn XMMatrixRotationRollPitchYawFromVector(
2118 Angles: FXMVECTOR,
2119) -> XMMATRIX
2120{
2121 let Q: XMVECTOR = XMQuaternionRotationRollPitchYawFromVector(Angles);
2122 return XMMatrixRotationQuaternion(Q);
2123}
2124
2125#[inline]
2142pub fn XMMatrixRotationNormal(
2143 NormalAxis: FXMVECTOR,
2144 Angle: f32,
2145) -> XMMATRIX
2146{
2147 #[cfg(any(_XM_NO_INTRINSICS_, _XM_ARM_NEON_INTRINSICS_))]
2148 unsafe {
2149 let mut fSinAngle: f32 = 0.0;
2150 let mut fCosAngle: f32 = 0.0;
2151 XMScalarSinCos(&mut fSinAngle, &mut fCosAngle, Angle);
2152
2153 let A: XMVECTOR = XMVectorSet(fSinAngle, fCosAngle, 1.0 - fCosAngle, 0.0);
2154
2155 let C2: XMVECTOR = XMVectorSplatZ(A);
2156 let C1: XMVECTOR = XMVectorSplatY(A);
2157 let C0: XMVECTOR = XMVectorSplatX(A);
2158
2159 let N0: XMVECTOR = <(XM_SWIZZLE_Y, XM_SWIZZLE_Z, XM_SWIZZLE_X, XM_SWIZZLE_W)>::XMVectorSwizzle(NormalAxis);
2160 let N1: XMVECTOR = <(XM_SWIZZLE_Z, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_W)>::XMVectorSwizzle(NormalAxis);
2161
2162 let mut V0: XMVECTOR = XMVectorMultiply(C2, N0);
2163 V0 = XMVectorMultiply(V0, N1);
2164
2165 let mut R0: XMVECTOR = XMVectorMultiply(C2, NormalAxis);
2166 R0 = XMVectorMultiplyAdd(R0, NormalAxis, C1);
2167
2168 let R1: XMVECTOR = XMVectorMultiplyAdd(C0, NormalAxis, V0);
2169 let R2: XMVECTOR = XMVectorNegativeMultiplySubtract(C0, NormalAxis, V0);
2170
2171 V0 = XMVectorSelect(A, R0, g_XMSelect1110.v);
2172 let V1: XMVECTOR = <(XM_PERMUTE_0Z, XM_PERMUTE_1Y, XM_PERMUTE_1Z, XM_PERMUTE_0X)>::XMVectorPermute(R1, R2);
2173 let V2: XMVECTOR = <(XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_0Y, XM_PERMUTE_1X)>::XMVectorPermute(R1, R2);
2174
2175 let mut M: XMMATRIX = crate::undefined();
2176 M.r[0] = <(XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0W)>::XMVectorPermute(V0, V1);
2177 M.r[1] = <(XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_1W, XM_PERMUTE_0W)>::XMVectorPermute(V0, V1);
2178 M.r[2] = <(XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z, XM_PERMUTE_0W)>::XMVectorPermute(V0, V2);
2179 M.r[3] = g_XMIdentityR3.v;
2180 return M;
2181 }
2182
2183 #[cfg(_XM_SSE_INTRINSICS_)]
2184 unsafe {
2185 let mut fSinAngle: f32 = 0.0;
2186 let mut fCosAngle: f32 = 0.0;
2187 XMScalarSinCos(&mut fSinAngle, &mut fCosAngle, Angle);
2188
2189 let C2: XMVECTOR = _mm_set_ps1(1.0 - fCosAngle);
2190 let C1: XMVECTOR = _mm_set_ps1(fCosAngle);
2191 let C0: XMVECTOR = _mm_set_ps1(fSinAngle);
2192
2193 let N0: XMVECTOR = XM_PERMUTE_PS!(NormalAxis, _MM_SHUFFLE(3, 0, 2, 1));
2194 let N1: XMVECTOR = XM_PERMUTE_PS!(NormalAxis, _MM_SHUFFLE(3, 1, 0, 2));
2195
2196 let mut V0: XMVECTOR = _mm_mul_ps(C2, N0);
2197 V0 = _mm_mul_ps(V0, N1);
2198
2199 let mut R0: XMVECTOR = _mm_mul_ps(C2, NormalAxis);
2200 R0 = _mm_mul_ps(R0, NormalAxis);
2201 R0 = _mm_add_ps(R0, C1);
2202
2203 let mut R1: XMVECTOR = _mm_mul_ps(C0, NormalAxis);
2204 R1 = _mm_add_ps(R1, V0);
2205 let mut R2: XMVECTOR = _mm_mul_ps(C0, NormalAxis);
2206 R2 = _mm_sub_ps(V0, R2);
2207
2208 V0 = _mm_and_ps(R0, g_XMMask3.v);
2209 let mut V1: XMVECTOR = _mm_shuffle_ps(R1, R2, _MM_SHUFFLE(2, 1, 2, 0));
2210 V1 = XM_PERMUTE_PS!(V1, _MM_SHUFFLE(0, 3, 2, 1));
2211 let mut V2: XMVECTOR = _mm_shuffle_ps(R1, R2, _MM_SHUFFLE(0, 0, 1, 1));
2212 V2 = XM_PERMUTE_PS!(V2, _MM_SHUFFLE(2, 0, 2, 0));
2213
2214 R2 = _mm_shuffle_ps(V0, V1, _MM_SHUFFLE(1, 0, 3, 0));
2215 R2 = XM_PERMUTE_PS!(R2, _MM_SHUFFLE(1, 3, 2, 0));
2216
2217 let mut M: XMMATRIX = undefined();
2218 M.r[0] = R2;
2219
2220 R2 = _mm_shuffle_ps(V0, V1, _MM_SHUFFLE(3, 2, 3, 1));
2221 R2 = XM_PERMUTE_PS!(R2, _MM_SHUFFLE(1, 3, 0, 2));
2222 M.r[1] = R2;
2223
2224 V2 = _mm_shuffle_ps(V2, V0, _MM_SHUFFLE(3, 2, 1, 0));
2225 M.r[2] = V2;
2226 M.r[3] = g_XMIdentityR3.v;
2227 return M;
2228 }
2229}
2230
2231#[inline]
2255pub fn XMMatrixRotationAxis(
2256 Axis: FXMVECTOR,
2257 Angle: f32,
2258) -> XMMATRIX
2259{
2260 debug_assert!(!XMVector3Equal(Axis, XMVectorZero()));
2261 debug_assert!(!XMVector3IsInfinite(Axis));
2262
2263 let Normal: XMVECTOR = XMVector3Normalize(Axis);
2264 return XMMatrixRotationNormal(Normal, Angle);
2265}
2266
2267#[inline]
2281pub fn XMMatrixRotationQuaternion(
2282 Quaternion: FXMVECTOR ,
2283) -> XMMATRIX
2284{
2285 #[cfg(any(_XM_NO_INTRINSICS_, _XM_ARM_NEON_INTRINSICS_))]
2286 unsafe {
2287 const Constant1110: XMVECTORF32 = XMVECTORF32 { f: [ 1.0, 1.0, 1.0, 0.0 ] };
2289
2290 let Q0: XMVECTOR = XMVectorAdd(Quaternion, Quaternion);
2291 let Q1: XMVECTOR = XMVectorMultiply(Quaternion, Q0);
2292
2293 let mut V0: XMVECTOR = <(XM_PERMUTE_0Y, XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_1W)>::XMVectorPermute(Q1, Constant1110.v);
2294 let mut V1: XMVECTOR = <(XM_PERMUTE_0Z, XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1W)>::XMVectorPermute(Q1, Constant1110.v);
2295 let mut R0: XMVECTOR = XMVectorSubtract(*Constant1110, V0);
2296 R0 = XMVectorSubtract(R0, V1);
2297
2298 V0 = <(XM_SWIZZLE_X, XM_SWIZZLE_X, XM_SWIZZLE_Y, XM_SWIZZLE_W)>::XMVectorSwizzle(Quaternion);
2299 V1 = <(XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_Z, XM_SWIZZLE_W)>::XMVectorSwizzle(Q0);
2300 V0 = XMVectorMultiply(V0, V1);
2301
2302 V1 = XMVectorSplatW(Quaternion);
2303 let V2: XMVECTOR = <(XM_SWIZZLE_Y, XM_SWIZZLE_Z, XM_SWIZZLE_X, XM_SWIZZLE_W)>::XMVectorSwizzle(Q0);
2304 V1 = XMVectorMultiply(V1, V2);
2305
2306 let R1: XMVECTOR = XMVectorAdd(V0, V1);
2307 let R2: XMVECTOR = XMVectorSubtract(V0, V1);
2308
2309 V0 = <(XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z)>::XMVectorPermute(R1, R2);
2310 V1 = <(XM_PERMUTE_0X, XM_PERMUTE_1Z, XM_PERMUTE_0X, XM_PERMUTE_1Z)>::XMVectorPermute(R1, R2);
2311
2312 let mut M: XMMATRIX = crate::undefined();
2313 M.r[0] = <(XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0W)>::XMVectorPermute(R0, V0);
2314 M.r[1] = <(XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_1W, XM_PERMUTE_0W)>::XMVectorPermute(R0, V0);
2315 M.r[2] = <(XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z, XM_PERMUTE_0W)>::XMVectorPermute(R0, V1);
2316 M.r[3] = g_XMIdentityR3.v;
2317 return M;
2318 }
2319
2320 #[cfg(_XM_SSE_INTRINSICS_)]
2321 unsafe {
2322 const Constant1110: XMVECTORF32 = XMVECTORF32 { f: [ 1.0, 1.0, 1.0, 0.0 ] };
2324
2325 let Q0: XMVECTOR = _mm_add_ps(Quaternion, Quaternion);
2326 let mut Q1: XMVECTOR = _mm_mul_ps(Quaternion, Q0);
2327
2328 let mut V0: XMVECTOR = XM_PERMUTE_PS!(Q1, _MM_SHUFFLE(3, 0, 0, 1));
2329 V0 = _mm_and_ps(V0, *g_XMMask3);
2330 let mut V1: XMVECTOR = XM_PERMUTE_PS!(Q1, _MM_SHUFFLE(3, 1, 2, 2));
2331 V1 = _mm_and_ps(V1, *g_XMMask3);
2332 let mut R0: XMVECTOR = _mm_sub_ps(*Constant1110, V0);
2333 R0 = _mm_sub_ps(R0, V1);
2334
2335 V0 = XM_PERMUTE_PS!(Quaternion, _MM_SHUFFLE(3, 1, 0, 0));
2336 V1 = XM_PERMUTE_PS!(Q0, _MM_SHUFFLE(3, 2, 1, 2));
2337 V0 = _mm_mul_ps(V0, V1);
2338
2339 V1 = XM_PERMUTE_PS!(Quaternion, _MM_SHUFFLE(3, 3, 3, 3));
2340 let V2: XMVECTOR = XM_PERMUTE_PS!(Q0, _MM_SHUFFLE(3, 0, 2, 1));
2341 V1 = _mm_mul_ps(V1, V2);
2342
2343 let R1: XMVECTOR = _mm_add_ps(V0, V1);
2344 let R2: XMVECTOR = _mm_sub_ps(V0, V1);
2345
2346 V0 = _mm_shuffle_ps(R1, R2, _MM_SHUFFLE(1, 0, 2, 1));
2347 V0 = XM_PERMUTE_PS!(V0, _MM_SHUFFLE(1, 3, 2, 0));
2348 V1 = _mm_shuffle_ps(R1, R2, _MM_SHUFFLE(2, 2, 0, 0));
2349 V1 = XM_PERMUTE_PS!(V1, _MM_SHUFFLE(2, 0, 2, 0));
2350
2351 Q1 = _mm_shuffle_ps(R0, V0, _MM_SHUFFLE(1, 0, 3, 0));
2352 Q1 = XM_PERMUTE_PS!(Q1, _MM_SHUFFLE(1, 3, 2, 0));
2353
2354 let mut M: XMMATRIX = crate::undefined();
2355 M.r[0] = Q1;
2356
2357 Q1 = _mm_shuffle_ps(R0, V0, _MM_SHUFFLE(3, 2, 3, 1));
2358 Q1 = XM_PERMUTE_PS!(Q1, _MM_SHUFFLE(1, 3, 0, 2));
2359 M.r[1] = Q1;
2360
2361 Q1 = _mm_shuffle_ps(V1, R0, _MM_SHUFFLE(3, 2, 1, 0));
2362 M.r[2] = Q1;
2363 M.r[3] = *g_XMIdentityR3;
2364 return M;
2365 }
2366}
2367
2368#[inline]
2392pub fn XMMatrixTransformation2D(
2393 ScalingOrigin: FXMVECTOR,
2394 ScalingOrientation: f32,
2395 Scaling: FXMVECTOR,
2396 RotationOrigin: FXMVECTOR,
2397 Rotation: f32,
2398 Translation: GXMVECTOR
2399) -> XMMATRIX
2400{
2401 unsafe {
2402 let VScalingOrigin: XMVECTOR = XMVectorSelect(g_XMSelect1100.v, ScalingOrigin, g_XMSelect1100.v);
2406 let NegScalingOrigin: XMVECTOR = XMVectorNegate(VScalingOrigin);
2407
2408 let MScalingOriginI: XMMATRIX = XMMatrixTranslationFromVector(NegScalingOrigin);
2409 let MScalingOrientation: XMMATRIX = XMMatrixRotationZ(ScalingOrientation);
2410 let MScalingOrientationT: XMMATRIX = XMMatrixTranspose(MScalingOrientation);
2411 let VScaling: XMVECTOR = XMVectorSelect(g_XMOne.v, Scaling, g_XMSelect1100.v);
2412 let MScaling: XMMATRIX = XMMatrixScalingFromVector(VScaling);
2413 let VRotationOrigin: XMVECTOR = XMVectorSelect(g_XMSelect1100.v, RotationOrigin, g_XMSelect1100.v);
2414 let MRotation: XMMATRIX = XMMatrixRotationZ(Rotation);
2415 let VTranslation: XMVECTOR = XMVectorSelect(g_XMSelect1100.v, Translation, g_XMSelect1100.v);
2416
2417 let mut M: XMMATRIX = XMMatrixMultiply(MScalingOriginI, &MScalingOrientationT);
2418 M = XMMatrixMultiply(M, &MScaling);
2419 M = XMMatrixMultiply(M, &MScalingOrientation);
2420 M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin);
2421 M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
2422 M = XMMatrixMultiply(M, &MRotation);
2423 M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
2424 M.r[3] = XMVectorAdd(M.r[3], VTranslation);
2425
2426 return M;
2427 }
2428}
2429
2430#[inline]
2454pub fn XMMatrixTransformation(
2455 ScalingOrigin: FXMVECTOR,
2456 ScalingOrientationQuaternion: FXMVECTOR,
2457 Scaling: FXMVECTOR,
2458 RotationOrigin: GXMVECTOR,
2459 RotationQuaternion: HXMVECTOR,
2460 Translation: HXMVECTOR
2461) -> XMMATRIX
2462{
2463 unsafe {
2464 let VScalingOrigin: XMVECTOR = XMVectorSelect(g_XMSelect1110.v, ScalingOrigin, g_XMSelect1110.v);
2468 let NegScalingOrigin: XMVECTOR = XMVectorNegate(ScalingOrigin);
2469
2470 let MScalingOriginI: XMMATRIX = XMMatrixTranslationFromVector(NegScalingOrigin);
2471 let MScalingOrientation: XMMATRIX = XMMatrixRotationQuaternion(ScalingOrientationQuaternion);
2472 let MScalingOrientationT: XMMATRIX = XMMatrixTranspose(MScalingOrientation);
2473 let MScaling: XMMATRIX = XMMatrixScalingFromVector(Scaling);
2474 let VRotationOrigin: XMVECTOR = XMVectorSelect(g_XMSelect1110.v, RotationOrigin, g_XMSelect1110.v);
2475 let MRotation: XMMATRIX = XMMatrixRotationQuaternion(RotationQuaternion);
2476 let VTranslation: XMVECTOR = XMVectorSelect(g_XMSelect1110.v, Translation, g_XMSelect1110.v);
2477
2478 let mut M: XMMATRIX;
2479 M = XMMatrixMultiply(MScalingOriginI, &MScalingOrientationT);
2480 M = XMMatrixMultiply(M, &MScaling);
2481 M = XMMatrixMultiply(M, &MScalingOrientation);
2482 M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin);
2483 M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
2484 M = XMMatrixMultiply(M, &MRotation);
2485 M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
2486 M.r[3] = XMVectorAdd(M.r[3], VTranslation);
2487 return M;
2488 }
2489}
2490
2491#[inline]
2511pub fn XMMatrixAffineTransformation2D(
2512 Scaling: FXMVECTOR,
2513 RotationOrigin: FXMVECTOR,
2514 Rotation: f32,
2515 Translation: GXMVECTOR
2516) -> XMMATRIX
2517{
2518 unsafe {
2519 let VScaling: XMVECTOR = XMVectorSelect(g_XMOne.v, Scaling, g_XMSelect1100.v);
2522 let MScaling: XMMATRIX = XMMatrixScalingFromVector(VScaling);
2523 let VRotationOrigin: XMVECTOR = XMVectorSelect(g_XMSelect1100.v, RotationOrigin, g_XMSelect1100.v);
2524 let MRotation: XMMATRIX = XMMatrixRotationZ(Rotation);
2525 let VTranslation: XMVECTOR = XMVectorSelect(g_XMSelect1100.v, Translation, g_XMSelect1100.v);
2526
2527 let mut M: XMMATRIX;
2528 M = MScaling;
2529 M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
2530 M = XMMatrixMultiply(M, &MRotation);
2531 M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
2532 M.r[3] = XMVectorAdd(M.r[3], VTranslation);
2533 return M;
2534 }
2535}
2536
2537#[inline]
2557pub fn XMMatrixAffineTransformation(
2558 Scaling: FXMVECTOR,
2559 RotationOrigin: FXMVECTOR,
2560 RotationQuaternion: FXMVECTOR,
2561 Translation: GXMVECTOR
2562) -> XMMATRIX
2563{
2564 unsafe {
2565 let MScaling: XMMATRIX = XMMatrixScalingFromVector(Scaling);
2568 let VRotationOrigin: XMVECTOR = XMVectorSelect(g_XMSelect1110.v, RotationOrigin, g_XMSelect1110.v);
2569 let MRotation: XMMATRIX = XMMatrixRotationQuaternion(RotationQuaternion);
2570 let VTranslation: XMVECTOR = XMVectorSelect(g_XMSelect1110.v, Translation, g_XMSelect1110.v);
2571
2572 let mut M: XMMATRIX;
2573 M = MScaling;
2574 M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
2575 M = XMMatrixMultiply(M, &MRotation);
2576 M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
2577 M.r[3] = XMVectorAdd(M.r[3], VTranslation);
2578 return M;
2579 }
2580}
2581
2582#[inline]
2596pub fn XMMatrixReflect(
2597 ReflectionPlane: FXMVECTOR
2598) -> XMMATRIX
2599{
2600 unsafe {
2601 debug_assert!(!XMVector3Equal(ReflectionPlane, XMVectorZero()));
2602 debug_assert!(!XMPlaneIsInfinite(ReflectionPlane));
2603
2604 const NegativeTwo: XMVECTORF32 = XMVECTORF32 { f: [ -2.0, -2.0, -2.0, 0.0 ] };
2605
2606 let P: XMVECTOR = XMPlaneNormalize(ReflectionPlane);
2607 let S: XMVECTOR = XMVectorMultiply(P, NegativeTwo.v);
2608
2609 let A: XMVECTOR = XMVectorSplatX(P);
2610 let B: XMVECTOR = XMVectorSplatY(P);
2611 let C: XMVECTOR = XMVectorSplatZ(P);
2612 let D: XMVECTOR = XMVectorSplatW(P);
2613
2614 let mut M: XMMATRIX = undefined();
2615 M.r[0] = XMVectorMultiplyAdd(A, S, g_XMIdentityR0.v);
2616 M.r[1] = XMVectorMultiplyAdd(B, S, g_XMIdentityR1.v);
2617 M.r[2] = XMVectorMultiplyAdd(C, S, g_XMIdentityR2.v);
2618 M.r[3] = XMVectorMultiplyAdd(D, S, g_XMIdentityR3.v);
2619 return M;
2620 }
2621}
2622
2623#[inline]
2644pub fn XMMatrixShadow(
2645 ShadowPlane: FXMVECTOR,
2646 LightPosition: FXMVECTOR,
2647) -> XMMATRIX
2648{
2649 unsafe {
2650 const Select0001: XMVECTORU32 = XMVECTORU32 { u: [ XM_SELECT_0, XM_SELECT_0, XM_SELECT_0, XM_SELECT_1 ] };
2651
2652 debug_assert!(!XMVector3Equal(ShadowPlane, XMVectorZero()));
2653 debug_assert!(!XMPlaneIsInfinite(ShadowPlane));
2654
2655 let mut P: XMVECTOR = XMPlaneNormalize(ShadowPlane);
2656 let mut Dot: XMVECTOR = XMPlaneDot(P, LightPosition);
2657 P = XMVectorNegate(P);
2658 let D: XMVECTOR = XMVectorSplatW(P);
2659 let C: XMVECTOR = XMVectorSplatZ(P);
2660 let B: XMVECTOR = XMVectorSplatY(P);
2661 let A: XMVECTOR = XMVectorSplatX(P);
2662 Dot = XMVectorSelect(Select0001.v, Dot, Select0001.v);
2663
2664 let mut M: XMMATRIX = undefined();
2665 M.r[3] = XMVectorMultiplyAdd(D, LightPosition, Dot);
2666 Dot = XMVectorRotateLeft(Dot, 1);
2667 M.r[2] = XMVectorMultiplyAdd(C, LightPosition, Dot);
2668 Dot = XMVectorRotateLeft(Dot, 1);
2669 M.r[1] = XMVectorMultiplyAdd(B, LightPosition, Dot);
2670 Dot = XMVectorRotateLeft(Dot, 1);
2671 M.r[0] = XMVectorMultiplyAdd(A, LightPosition, Dot);
2672 return M;
2673 }
2674}
2675
2676#[inline]
2694pub fn XMMatrixLookAtLH(
2695 EyePosition: FXMVECTOR,
2696 FocusPosition: FXMVECTOR,
2697 UpDirection: FXMVECTOR,
2698) -> XMMATRIX
2699{
2700 let EyeDirection: XMVECTOR = XMVectorSubtract(FocusPosition, EyePosition);
2701 return XMMatrixLookToLH(EyePosition, EyeDirection, UpDirection);
2702}
2703
2704#[inline]
2722pub fn XMMatrixLookAtRH(
2723 EyePosition: FXMVECTOR,
2724 FocusPosition: FXMVECTOR,
2725 UpDirection: FXMVECTOR,
2726) -> XMMATRIX
2727{
2728 let NegEyeDirection: XMVECTOR = XMVectorSubtract(EyePosition, FocusPosition);
2729 return XMMatrixLookToLH(EyePosition, NegEyeDirection, UpDirection);
2730}
2731
2732#[inline]
2750pub fn XMMatrixLookToLH(
2751 EyePosition: FXMVECTOR,
2752 EyeDirection: FXMVECTOR,
2753 UpDirection: FXMVECTOR,
2754) -> XMMATRIX
2755{
2756 unsafe {
2757 debug_assert!(!XMVector3Equal(EyeDirection, XMVectorZero()));
2758 debug_assert!(!XMVector3IsInfinite(EyeDirection));
2759 debug_assert!(!XMVector3Equal(UpDirection, XMVectorZero()));
2760 debug_assert!(!XMVector3IsInfinite(UpDirection));
2761
2762 let R2: XMVECTOR = XMVector3Normalize(EyeDirection);
2763
2764 let mut R0: XMVECTOR = XMVector3Cross(UpDirection, R2);
2765 R0 = XMVector3Normalize(R0);
2766
2767 let R1: XMVECTOR = XMVector3Cross(R2, R0);
2768
2769 let NegEyePosition: XMVECTOR = XMVectorNegate(EyePosition);
2770
2771 let D0: XMVECTOR = XMVector3Dot(R0, NegEyePosition);
2772 let D1: XMVECTOR = XMVector3Dot(R1, NegEyePosition);
2773 let D2: XMVECTOR = XMVector3Dot(R2, NegEyePosition);
2774
2775 let mut M: XMMATRIX = crate::undefined();
2776 M.r[0] = XMVectorSelect(D0, R0, g_XMSelect1110.v);
2777 M.r[1] = XMVectorSelect(D1, R1, g_XMSelect1110.v);
2778 M.r[2] = XMVectorSelect(D2, R2, g_XMSelect1110.v);
2779 M.r[3] = g_XMIdentityR3.v;
2780
2781 M = XMMatrixTranspose(M);
2782
2783 return M;
2784 }
2785}
2786
2787#[inline]
2805pub fn XMMatrixLookToRH(
2806 EyePosition: FXMVECTOR,
2807 EyeDirection: FXMVECTOR,
2808 UpDirection: FXMVECTOR,
2809) -> XMMATRIX
2810{
2811 let NegEyeDirection: XMVECTOR = XMVectorNegate(EyeDirection);
2812 return XMMatrixLookToLH(EyePosition, NegEyeDirection, UpDirection);
2813}
2814
2815#[inline]
2841pub fn XMMatrixPerspectiveLH(
2842 ViewWidth: f32,
2843 ViewHeight: f32,
2844 NearZ: f32,
2845 FarZ: f32
2846) -> XMMATRIX
2847{
2848 debug_assert!(NearZ > 0.0 && FarZ > 0.0);
2849 debug_assert!(!XMScalarNearEqual(ViewWidth, 0.0, 0.00001));
2850 debug_assert!(!XMScalarNearEqual(ViewHeight, 0.0, 0.00001));
2851 debug_assert!(!XMScalarNearEqual(FarZ, NearZ, 0.00001));
2852
2853 #[cfg(_XM_NO_INTRINSICS_)]
2854 unsafe {
2855 let TwoNearZ: f32 = NearZ + NearZ;
2856 let fRange: f32 = FarZ / (FarZ - NearZ);
2857
2858 let mut M: XMMATRIX = crate::undefined();
2859 M.m[0][0] = TwoNearZ / ViewWidth;
2860 M.m[0][1] = 0.0;
2861 M.m[0][2] = 0.0;
2862 M.m[0][3] = 0.0;
2863
2864 M.m[1][0] = 0.0;
2865 M.m[1][1] = TwoNearZ / ViewHeight;
2866 M.m[1][2] = 0.0;
2867 M.m[1][3] = 0.0;
2868
2869 M.m[2][0] = 0.0;
2870 M.m[2][1] = 0.0;
2871 M.m[2][2] = fRange;
2872 M.m[2][3] = 1.0;
2873
2874 M.m[3][0] = 0.0;
2875 M.m[3][1] = 0.0;
2876 M.m[3][2] = -fRange * NearZ;
2877 M.m[3][3] = 0.0;
2878 return M;
2879 }
2880
2881 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
2882 {
2883 unimplemented!()
2884 }
2885
2886 #[cfg(_XM_SSE_INTRINSICS_)]
2887 unsafe {
2888 let mut M: XMMATRIX = crate::undefined();
2889 let TwoNearZ: f32 = NearZ + NearZ;
2890 let fRange: f32 = FarZ / (FarZ - NearZ);
2891 let rMem: XMVECTORF32 = XMVECTORF32 { f: [
2893 TwoNearZ / ViewWidth,
2894 TwoNearZ / ViewHeight,
2895 fRange,
2896 -fRange * NearZ
2897 ]};
2898 let mut vValues: XMVECTOR = rMem.v;
2900 let mut vTemp: XMVECTOR = _mm_setzero_ps();
2901 vTemp = _mm_move_ss(vTemp, vValues);
2903 M.r[0] = vTemp;
2905 vTemp = vValues;
2907 vTemp = _mm_and_ps(vTemp, *g_XMMaskY);
2908 M.r[1] = vTemp;
2909 vValues = _mm_shuffle_ps(vValues, *g_XMIdentityR3, _MM_SHUFFLE(3, 2, 3, 2));
2911 vTemp = _mm_setzero_ps();
2913 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(3, 0, 0, 0));
2914 M.r[2] = vTemp;
2915 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(2, 1, 0, 0));
2917 M.r[3] = vTemp;
2918 return M;
2919 }
2920}
2921
2922#[inline]
2948pub fn XMMatrixPerspectiveRH(
2949 ViewWidth: f32,
2950 ViewHeight: f32,
2951 NearZ: f32,
2952 FarZ: f32
2953) -> XMMATRIX
2954{
2955 debug_assert!(NearZ > 0.0 && FarZ > 0.0);
2956 debug_assert!(!XMScalarNearEqual(ViewWidth, 0.0, 0.00001));
2957 debug_assert!(!XMScalarNearEqual(ViewHeight, 0.0, 0.00001));
2958 debug_assert!(!XMScalarNearEqual(FarZ, NearZ, 0.00001));
2959
2960 #[cfg(_XM_NO_INTRINSICS_)]
2961 unsafe {
2962 let TwoNearZ: f32 = NearZ + NearZ;
2963 let fRange: f32 = FarZ / (NearZ - FarZ);
2964
2965 let mut M: XMMATRIX = crate::undefined();
2966 M.m[0][0] = TwoNearZ / ViewWidth;
2967 M.m[0][1] = 0.0;
2968 M.m[0][2] = 0.0;
2969 M.m[0][3] = 0.0;
2970
2971 M.m[1][0] = 0.0;
2972 M.m[1][1] = TwoNearZ / ViewHeight;
2973 M.m[1][2] = 0.0;
2974 M.m[1][3] = 0.0;
2975
2976 M.m[2][0] = 0.0;
2977 M.m[2][1] = 0.0;
2978 M.m[2][2] = fRange;
2979 M.m[2][3] = -1.0;
2980
2981 M.m[3][0] = 0.0;
2982 M.m[3][1] = 0.0;
2983 M.m[3][2] = fRange * NearZ;
2984 M.m[3][3] = 0.0;
2985 return M;
2986 }
2987
2988 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
2989 {
2990 unimplemented!()
2991 }
2992
2993 #[cfg(_XM_SSE_INTRINSICS_)]
2994 unsafe {
2995 let mut M: XMMATRIX = crate::undefined();
2996 let TwoNearZ: f32 = NearZ + NearZ;
2997 let fRange: f32 = FarZ / (NearZ - FarZ);
2998 let rMem: XMVECTORF32 = XMVECTORF32 { f: [
3000 TwoNearZ / ViewWidth,
3001 TwoNearZ / ViewHeight,
3002 fRange,
3003 fRange * NearZ
3004 ]};
3005 let mut vValues: XMVECTOR = rMem.v;
3007 let mut vTemp: XMVECTOR = _mm_setzero_ps();
3008 vTemp = _mm_move_ss(vTemp, vValues);
3010 M.r[0] = vTemp;
3012 vTemp = vValues;
3014 vTemp = _mm_and_ps(vTemp, *g_XMMaskY);
3015 M.r[1] = vTemp;
3016 vValues = _mm_shuffle_ps(vValues, *g_XMNegIdentityR3, _MM_SHUFFLE(3, 2, 3, 2));
3018 vTemp = _mm_setzero_ps();
3020 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(3, 0, 0, 0));
3021 M.r[2] = vTemp;
3022 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(2, 1, 0, 0));
3024 M.r[3] = vTemp;
3025 return M;
3026 }
3027}
3028
3029#[inline]
3055pub fn XMMatrixPerspectiveFovLH(
3056 FovAngleY: f32,
3057 AspectRatio: f32,
3058 NearZ: f32,
3059 FarZ: f32
3060) -> XMMATRIX
3061{
3062 debug_assert!(NearZ > 0.0 && FarZ > 0.0);
3063 debug_assert!(!XMScalarNearEqual(FovAngleY, 0.0, 0.00001 * 2.0));
3064 debug_assert!(!XMScalarNearEqual(AspectRatio, 0.0, 0.00001));
3065 debug_assert!(!XMScalarNearEqual(FarZ, NearZ, 0.00001));
3066
3067 #[cfg(_XM_NO_INTRINSICS_)]
3068 unsafe {
3069 let mut SinFov: f32 = 0.0;
3070 let mut CosFov: f32 = 0.0;
3071 XMScalarSinCos(&mut SinFov, &mut CosFov, 0.5 * FovAngleY);
3072
3073 let Height: f32 = CosFov / SinFov;
3074 let Width: f32 = Height / AspectRatio;
3075 let fRange: f32 = FarZ / (FarZ - NearZ);
3076
3077 let mut M: XMMATRIX = crate::undefined();
3078 M.m[0][0] = Width;
3079 M.m[0][1] = 0.0;
3080 M.m[0][2] = 0.0;
3081 M.m[0][3] = 0.0;
3082
3083 M.m[1][0] = 0.0;
3084 M.m[1][1] = Height;
3085 M.m[1][2] = 0.0;
3086 M.m[1][3] = 0.0;
3087
3088 M.m[2][0] = 0.0;
3089 M.m[2][1] = 0.0;
3090 M.m[2][2] = fRange;
3091 M.m[2][3] = 1.0;
3092
3093 M.m[3][0] = 0.0;
3094 M.m[3][1] = 0.0;
3095 M.m[3][2] = -fRange * NearZ;
3096 M.m[3][3] = 0.0;
3097 return M;
3098 }
3099
3100 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
3101 {
3102 unimplemented!()
3103 }
3104
3105 #[cfg(_XM_SSE_INTRINSICS_)]
3106 unsafe {
3107 let mut SinFov: f32 = 0.0;
3108 let mut CosFov: f32 = 0.0;
3109 XMScalarSinCos(&mut SinFov, &mut CosFov, 0.5 * FovAngleY);
3110
3111 let fRange: f32 = FarZ / (FarZ - NearZ);
3112 let Height: f32 = CosFov / SinFov;
3114 let rMem: XMVECTORF32 = XMVECTORF32 { f: [
3115 Height / AspectRatio,
3116 Height,
3117 fRange,
3118 -fRange * NearZ
3119 ]};
3120 let mut vValues: XMVECTOR = rMem.v;
3122 let mut vTemp: XMVECTOR = _mm_setzero_ps();
3123 vTemp = _mm_move_ss(vTemp, vValues);
3125 let mut M: XMMATRIX = crate::undefined();
3127 M.r[0] = vTemp;
3128 vTemp = vValues;
3130 vTemp = _mm_and_ps(vTemp, *g_XMMaskY);
3131 M.r[1] = vTemp;
3132 vTemp = _mm_setzero_ps();
3134 vValues = _mm_shuffle_ps(vValues, *g_XMIdentityR3, _MM_SHUFFLE(3, 2, 3, 2));
3135 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(3, 0, 0, 0));
3137 M.r[2] = vTemp;
3138 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(2, 1, 0, 0));
3140 M.r[3] = vTemp;
3141 return M;
3142 }
3143}
3144
3145
3146#[inline]
3172pub fn XMMatrixPerspectiveFovRH(
3173 FovAngleY: f32,
3174 AspectRatio: f32,
3175 NearZ: f32,
3176 FarZ: f32
3177) -> XMMATRIX
3178{
3179 debug_assert!(NearZ > 0.0 && FarZ > 0.0);
3180 debug_assert!(!XMScalarNearEqual(FovAngleY, 0.0, 0.00001 * 2.0));
3181 debug_assert!(!XMScalarNearEqual(AspectRatio, 0.0, 0.00001));
3182 debug_assert!(!XMScalarNearEqual(FarZ, NearZ, 0.00001));
3183
3184 #[cfg(_XM_NO_INTRINSICS_)]
3185 unsafe {
3186 let mut SinFov: f32 = 0.0;
3187 let mut CosFov: f32 = 0.0;
3188 XMScalarSinCos(&mut SinFov, &mut CosFov, 0.5 * FovAngleY);
3189
3190 let Height: f32 = CosFov / SinFov;
3191 let Width: f32 = Height / AspectRatio;
3192 let fRange: f32 = FarZ / (NearZ - FarZ);
3193
3194 let mut M: XMMATRIX = crate::undefined();
3195 M.m[0][0] = Width;
3196 M.m[0][1] = 0.0;
3197 M.m[0][2] = 0.0;
3198 M.m[0][3] = 0.0;
3199
3200 M.m[1][0] = 0.0;
3201 M.m[1][1] = Height;
3202 M.m[1][2] = 0.0;
3203 M.m[1][3] = 0.0;
3204
3205 M.m[2][0] = 0.0;
3206 M.m[2][1] = 0.0;
3207 M.m[2][2] = fRange;
3208 M.m[2][3] = -1.0;
3209
3210 M.m[3][0] = 0.0;
3211 M.m[3][1] = 0.0;
3212 M.m[3][2] = fRange * NearZ;
3213 M.m[3][3] = 0.0;
3214 return M;
3215 }
3216
3217 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
3218 {
3219 unimplemented!()
3220 }
3221
3222 #[cfg(_XM_SSE_INTRINSICS_)]
3223 unsafe {
3224 let mut SinFov: f32 = 0.0;
3225 let mut CosFov: f32 = 0.0;
3226 XMScalarSinCos(&mut SinFov, &mut CosFov, 0.5 * FovAngleY);
3227 let fRange: f32 = FarZ / (NearZ - FarZ);
3228 let Height: f32 = CosFov / SinFov;
3229 let rMem: XMVECTORF32 = XMVECTORF32 { f: [
3231 Height / AspectRatio,
3232 Height,
3233 fRange,
3234 fRange * NearZ
3235 ]};
3236 let mut vValues: XMVECTOR = rMem.v;
3238 let mut vTemp: XMVECTOR = _mm_setzero_ps();
3239 vTemp = _mm_move_ss(vTemp, vValues);
3241 let mut M: XMMATRIX = crate::undefined();
3243 M.r[0] = vTemp;
3244 vTemp = vValues;
3246 vTemp = _mm_and_ps(vTemp, *g_XMMaskY);
3247 M.r[1] = vTemp;
3248 vTemp = _mm_setzero_ps();
3250 vValues = _mm_shuffle_ps(vValues, *g_XMNegIdentityR3, _MM_SHUFFLE(3, 2, 3, 2));
3251 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(3, 0, 0, 0));
3253 M.r[2] = vTemp;
3254 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(2, 1, 0, 0));
3256 M.r[3] = vTemp;
3257 return M;
3258 }
3259}
3260
3261#[inline]
3292pub fn XMMatrixPerspectiveOffCenterLH(
3293 ViewLeft: f32,
3294 ViewRight: f32,
3295 ViewBottom: f32,
3296 ViewTop: f32,
3297 NearZ: f32,
3298 FarZ: f32,
3299) -> XMMATRIX {
3300 debug_assert!(NearZ > 0.0 && FarZ > 0.0);
3301 debug_assert!(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001));
3302 debug_assert!(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001));
3303 debug_assert!(!XMScalarNearEqual(FarZ, NearZ, 0.00001));
3304
3305 #[cfg(_XM_NO_INTRINSICS_)]
3306 unsafe {
3307 let TwoNearZ = NearZ + NearZ;
3308 let ReciprocalWidth = 1.0 / (ViewRight - ViewLeft);
3309 let ReciprocalHeight = 1.0 / (ViewTop - ViewBottom);
3310 let fRange = FarZ / (FarZ - NearZ);
3311
3312 let mut M: XMMATRIX = crate::undefined();
3313 M.m[0][0] = TwoNearZ * ReciprocalWidth;
3314 M.m[0][1] = 0.0;
3315 M.m[0][2] = 0.0;
3316 M.m[0][3] = 0.0;
3317
3318 M.m[1][0] = 0.0;
3319 M.m[1][1] = TwoNearZ * ReciprocalHeight;
3320 M.m[1][2] = 0.0;
3321 M.m[1][3] = 0.0;
3322
3323 M.m[2][0] = -(ViewLeft + ViewRight) * ReciprocalWidth;
3324 M.m[2][1] = -(ViewTop + ViewBottom) * ReciprocalHeight;
3325 M.m[2][2] = fRange;
3326 M.m[2][3] = 1.0;
3327
3328 M.m[3][0] = 0.0;
3329 M.m[3][1] = 0.0;
3330 M.m[3][2] = -fRange * NearZ;
3331 M.m[3][3] = 0.0;
3332 return M;
3333 }
3334
3335 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
3336 {
3337 unimplemented!()
3338 }
3339
3340 #[cfg(_XM_SSE_INTRINSICS_)]
3341 unsafe {
3342 let mut M: XMMATRIX = crate::undefined();
3343 let TwoNearZ = NearZ + NearZ;
3344 let ReciprocalWidth = 1.0 / (ViewRight - ViewLeft);
3345 let ReciprocalHeight = 1.0 / (ViewTop - ViewBottom);
3346 let fRange = FarZ / (FarZ - NearZ);
3347 let rMem: XMVECTORF32 = XMVECTORF32 { f: [
3349 TwoNearZ * ReciprocalWidth,
3350 TwoNearZ * ReciprocalHeight,
3351 -fRange * NearZ,
3352 0.0,
3353 ]};
3354 let mut vValues: XMVECTOR = rMem.v;
3356 let mut vTemp: XMVECTOR = _mm_setzero_ps();
3357 vTemp = _mm_move_ss(vTemp, vValues);
3359 M.r[0] = vTemp;
3361 vTemp = vValues;
3363 vTemp = _mm_and_ps(vTemp, *g_XMMaskY);
3364 M.r[1] = vTemp;
3365 M.r[2] = XMVectorSet(-(ViewLeft + ViewRight) * ReciprocalWidth,
3367 -(ViewTop + ViewBottom) * ReciprocalHeight,
3368 fRange,
3369 1.0);
3370 vValues = _mm_and_ps(vValues, *g_XMMaskZ);
3372 M.r[3] = vValues;
3373 return M;
3374 }
3375}
3376
3377
3378#[inline]
3409pub fn XMMatrixPerspectiveOffCenterRH(
3410 ViewLeft: f32,
3411 ViewRight: f32,
3412 ViewBottom: f32,
3413 ViewTop: f32,
3414 NearZ: f32,
3415 FarZ: f32,
3416) -> XMMATRIX {
3417 debug_assert!(NearZ > 0.0 && FarZ > 0.0);
3418 debug_assert!(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001));
3419 debug_assert!(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001));
3420 debug_assert!(!XMScalarNearEqual(FarZ, NearZ, 0.00001));
3421
3422 #[cfg(_XM_NO_INTRINSICS_)]
3423 unsafe {
3424 let TwoNearZ = NearZ + NearZ;
3425 let ReciprocalWidth = 1.0 / (ViewRight - ViewLeft);
3426 let ReciprocalHeight = 1.0 / (ViewTop - ViewBottom);
3427 let fRange = FarZ / (NearZ - FarZ);
3428
3429 let mut M: XMMATRIX = crate::undefined();
3430 M.m[0][0] = TwoNearZ * ReciprocalWidth;
3431 M.m[0][1] = 0.0;
3432 M.m[0][2] = 0.0;
3433 M.m[0][3] = 0.0;
3434
3435 M.m[1][0] = 0.0;
3436 M.m[1][1] = TwoNearZ * ReciprocalHeight;
3437 M.m[1][2] = 0.0;
3438 M.m[1][3] = 0.0;
3439
3440 M.m[2][0] = (ViewLeft + ViewRight) * ReciprocalWidth;
3441 M.m[2][1] = (ViewTop + ViewBottom) * ReciprocalHeight;
3442 M.m[2][2] = fRange;
3443 M.m[2][3] = -1.0;
3444
3445 M.m[3][0] = 0.0;
3446 M.m[3][1] = 0.0;
3447 M.m[3][2] = fRange * NearZ;
3448 M.m[3][3] = 0.0;
3449 return M;
3450 }
3451
3452 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
3453 {
3454 unimplemented!()
3455 }
3456
3457 #[cfg(_XM_SSE_INTRINSICS_)]
3458 unsafe {
3459 let mut M: XMMATRIX = crate::undefined();
3460 let TwoNearZ = NearZ + NearZ;
3461 let ReciprocalWidth = 1.0 / (ViewRight - ViewLeft);
3462 let ReciprocalHeight = 1.0 / (ViewTop - ViewBottom);
3463 let fRange = FarZ / (NearZ - FarZ);
3464 let rMem: XMVECTORF32 = XMVECTORF32 { f: [
3466 TwoNearZ * ReciprocalWidth,
3467 TwoNearZ * ReciprocalHeight,
3468 fRange * NearZ,
3469 0.0,
3470 ]};
3471 let mut vValues: XMVECTOR = rMem.v;
3473 let mut vTemp: XMVECTOR = _mm_setzero_ps();
3474 vTemp = _mm_move_ss(vTemp, vValues);
3476 M.r[0] = vTemp;
3478 vTemp = vValues;
3480 vTemp = _mm_and_ps(vTemp, *g_XMMaskY);
3481 M.r[1] = vTemp;
3482 M.r[2] = XMVectorSet((ViewLeft + ViewRight) * ReciprocalWidth,
3484 (ViewTop + ViewBottom) * ReciprocalHeight,
3485 fRange,
3486 -1.0);
3487 vValues = _mm_and_ps(vValues, *g_XMMaskZ);
3489 M.r[3] = vValues;
3490 return M;
3491 }
3492}
3493
3494#[inline]
3518pub fn XMMatrixOrthographicLH(
3519 ViewWidth: f32,
3520 ViewHeight: f32,
3521 NearZ: f32,
3522 FarZ: f32
3523) -> XMMATRIX
3524{
3525 debug_assert!(!XMScalarNearEqual(ViewWidth, 0.0, 0.00001));
3526 debug_assert!(!XMScalarNearEqual(ViewHeight, 0.0, 0.00001));
3527 debug_assert!(!XMScalarNearEqual(FarZ, NearZ, 0.00001));
3528
3529 #[cfg(_XM_NO_INTRINSICS_)]
3530 unsafe {
3531 let fRange: f32 = 1.0 / (FarZ - NearZ);
3532 let mut M: XMMATRIX = crate::undefined();
3533 M.m[0][0] = 2.0 / ViewWidth;
3534 M.m[0][1] = 0.0;
3535 M.m[0][2] = 0.0;
3536 M.m[0][3] = 0.0;
3537
3538 M.m[1][0] = 0.0;
3539 M.m[1][1] = 2.0 / ViewHeight;
3540 M.m[1][2] = 0.0;
3541 M.m[1][3] = 0.0;
3542
3543 M.m[2][0] = 0.0;
3544 M.m[2][1] = 0.0;
3545 M.m[2][2] = fRange;
3546 M.m[2][3] = 0.0;
3547
3548 M.m[3][0] = 0.0;
3549 M.m[3][1] = 0.0;
3550 M.m[3][2] = -fRange * NearZ;
3551 M.m[3][3] = 1.0;
3552 return M;
3553 }
3554
3555 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
3556 {
3557 unimplemented!()
3558 }
3559
3560 #[cfg(_XM_SSE_INTRINSICS_)]
3561 unsafe {
3562 let mut M: XMMATRIX = crate::undefined();
3563 let fRange: f32 = 1.0 / (FarZ - NearZ);
3564 let rMem: XMVECTORF32 = XMVECTORF32 { f: [
3566 2.0 / ViewWidth,
3567 2.0 / ViewHeight,
3568 fRange,
3569 -fRange * NearZ
3570 ]};
3571 let mut vValues: XMVECTOR = rMem.v;
3573 let mut vTemp: XMVECTOR = _mm_setzero_ps();
3574 vTemp = _mm_move_ss(vTemp, vValues);
3576 M.r[0] = vTemp;
3578 vTemp = vValues;
3580 vTemp = _mm_and_ps(vTemp, *g_XMMaskY);
3581 M.r[1] = vTemp;
3582 vTemp = _mm_setzero_ps();
3584 vValues = _mm_shuffle_ps(vValues, *g_XMIdentityR3, _MM_SHUFFLE(3, 2, 3, 2));
3585 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(2, 0, 0, 0));
3587 M.r[2] = vTemp;
3588 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(3, 1, 0, 0));
3590 M.r[3] = vTemp;
3591 return M;
3592 }
3593}
3594
3595#[inline]
3619pub fn XMMatrixOrthographicRH(
3620 ViewWidth: f32,
3621 ViewHeight: f32,
3622 NearZ: f32,
3623 FarZ: f32
3624) -> XMMATRIX
3625{
3626 debug_assert!(!XMScalarNearEqual(ViewWidth, 0.0, 0.00001));
3627 debug_assert!(!XMScalarNearEqual(ViewHeight, 0.0, 0.00001));
3628 debug_assert!(!XMScalarNearEqual(FarZ, NearZ, 0.00001));
3629
3630 #[cfg(_XM_NO_INTRINSICS_)]
3631 unsafe {
3632 let fRange: f32 = 1.0 / (NearZ - FarZ);
3633 let mut M: XMMATRIX = crate::undefined();
3634 M.m[0][0] = 2.0 / ViewWidth;
3635 M.m[0][1] = 0.0;
3636 M.m[0][2] = 0.0;
3637 M.m[0][3] = 0.0;
3638
3639 M.m[1][0] = 0.0;
3640 M.m[1][1] = 2.0 / ViewHeight;
3641 M.m[1][2] = 0.0;
3642 M.m[1][3] = 0.0;
3643
3644 M.m[2][0] = 0.0;
3645 M.m[2][1] = 0.0;
3646 M.m[2][2] = fRange;
3647 M.m[2][3] = 0.0;
3648
3649 M.m[3][0] = 0.0;
3650 M.m[3][1] = 0.0;
3651 M.m[3][2] = fRange * NearZ;
3652 M.m[3][3] = 1.0;
3653 return M;
3654 }
3655
3656 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
3657 {
3658 unimplemented!()
3659 }
3660
3661 #[cfg(_XM_SSE_INTRINSICS_)]
3662 unsafe {
3663 let mut M: XMMATRIX = crate::undefined();
3664 let fRange: f32 = 1.0 / (NearZ - FarZ);
3665 let rMem: XMVECTORF32 = XMVECTORF32 { f: [
3667 2.0 / ViewWidth,
3668 2.0 / ViewHeight,
3669 fRange,
3670 fRange * NearZ
3671 ]};
3672 let mut vValues: XMVECTOR = rMem.v;
3674 let mut vTemp: XMVECTOR = _mm_setzero_ps();
3675 vTemp = _mm_move_ss(vTemp, vValues);
3677 M.r[0] = vTemp;
3679 vTemp = vValues;
3681 vTemp = _mm_and_ps(vTemp, *g_XMMaskY);
3682 M.r[1] = vTemp;
3683 vTemp = _mm_setzero_ps();
3685 vValues = _mm_shuffle_ps(vValues, *g_XMIdentityR3, _MM_SHUFFLE(3, 2, 3, 2));
3686 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(2, 0, 0, 0));
3688 M.r[2] = vTemp;
3689 vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(3, 1, 0, 0));
3691 M.r[3] = vTemp;
3692 return M;
3693 }
3694}
3695
3696impl std::ops::Deref for XMMatrix {
3700 type Target = XMMATRIX;
3701 #[inline(always)]
3702 fn deref(&self) -> &Self::Target {
3703 &self.0
3704 }
3705}
3706
3707impl std::ops::DerefMut for XMMatrix {
3708 #[inline(always)]
3709 fn deref_mut(&mut self) -> &mut Self::Target {
3710 &mut self.0
3711 }
3712}
3713
3714impl XMMatrix {
3715 #[inline]
3716 pub fn set(
3717 m00: f32, m01: f32, m02: f32, m03: f32,
3718 m10: f32, m11: f32, m12: f32, m13: f32,
3719 m20: f32, m21: f32, m22: f32, m23: f32,
3720 m30: f32, m31: f32, m32: f32, m33: f32,
3721 ) -> XMMatrix
3722 {
3723 XMMatrix(XMMatrixSet(
3724 m00, m01, m02, m03,
3725 m10, m11, m12, m13,
3726 m20, m21, m22, m23,
3727 m30, m31, m32, m33,
3728 ))
3729 }
3730}
3731
3732impl From<&[f32; 16]> for XMMatrix {
3733 #[inline]
3734 fn from(m: &[f32; 16]) -> XMMatrix {
3735 XMMatrix(XMLoadFloat4x4(m.into()))
3736 }
3737}
3738
3739impl From<&[[f32; 4]; 4]> for XMMatrix {
3740 #[inline]
3741 fn from(m: &[[f32; 4]; 4]) -> XMMatrix {
3742 XMMatrix(XMLoadFloat4x4(m.into()))
3743 }
3744}
3745
3746impl Into<[f32; 16]> for XMMatrix {
3747 #[inline]
3748 fn into(self) -> [f32; 16] {
3749 unsafe {
3750 let mut R: XMFLOAT4X4 = crate::undefined();
3751 XMStoreFloat4x4(&mut R, self.0);
3752 mem::transmute(R)
3753 }
3754 }
3755}
3756
3757impl Into<[[f32; 4]; 4]> for XMMatrix {
3758 #[inline]
3759 fn into(self) -> [[f32; 4]; 4] {
3760 unsafe {
3761 let mut R: XMFLOAT4X4 = crate::undefined();
3762 XMStoreFloat4x4(&mut R, self.0);
3763 mem::transmute(R)
3764 }
3765 }
3766}
3767
3768impl std::ops::Add for XMMatrix {
3769 type Output = XMMatrix;
3770 #[inline]
3771 fn add(self, M: XMMatrix) -> Self::Output {
3772 unsafe {
3773 XMMatrix(XMMATRIX { r: [
3774 XMVectorAdd(self.r[0], M.r[0]),
3775 XMVectorAdd(self.r[1], M.r[1]),
3776 XMVectorAdd(self.r[2], M.r[2]),
3777 XMVectorAdd(self.r[3], M.r[3]),
3778 ]})
3779 }
3780 }
3781}
3782
3783impl std::ops::AddAssign for XMMatrix {
3784 #[inline]
3785 fn add_assign(&mut self, M: XMMatrix) {
3786 unsafe {
3787 self.r[0] = XMVectorAdd(self.r[0], M.r[0]);
3788 self.r[0] = XMVectorAdd(self.r[1], M.r[1]);
3789 self.r[0] = XMVectorAdd(self.r[2], M.r[2]);
3790 self.r[0] = XMVectorAdd(self.r[3], M.r[3]);
3791 }
3792 }
3793}
3794
3795impl std::ops::Sub for XMMatrix {
3796 type Output = XMMatrix;
3797 #[inline]
3798 fn sub(self, M: XMMatrix) -> XMMatrix{
3799 unsafe {
3800 XMMatrix(XMMATRIX { r: [
3801 XMVectorSubtract(self.r[0], M.r[0]),
3802 XMVectorSubtract(self.r[1], M.r[1]),
3803 XMVectorSubtract(self.r[2], M.r[2]),
3804 XMVectorSubtract(self.r[3], M.r[3]),
3805 ]})
3806 }
3807 }
3808}
3809
3810impl std::ops::SubAssign for XMMatrix {
3811 #[inline]
3812 fn sub_assign(&mut self, M: XMMatrix) {
3813 unsafe {
3814 self.r[0] = XMVectorSubtract(self.r[0], M.r[0]);
3815 self.r[0] = XMVectorSubtract(self.r[1], M.r[1]);
3816 self.r[0] = XMVectorSubtract(self.r[2], M.r[2]);
3817 self.r[0] = XMVectorSubtract(self.r[3], M.r[3]);
3818 }
3819 }
3820}
3821
3822impl std::ops::Mul for XMMatrix {
3823 type Output = XMMatrix;
3824 #[inline]
3825 fn mul(self, M: XMMatrix) -> XMMatrix{
3826 XMMatrix(XMMatrixMultiply(self.0, &M))
3827 }
3828}
3829
3830impl std::ops::MulAssign for XMMatrix {
3831 #[inline]
3832 fn mul_assign(&mut self, M: XMMatrix) {
3833 self.0 = XMMatrixMultiply(self.0, &M)
3834 }
3835}
3836
3837impl std::ops::Mul<XMMatrix> for f32 {
3838 type Output = XMMatrix;
3839 #[inline]
3840 fn mul(self, M: XMMatrix) -> XMMatrix {
3841 unsafe {
3842 let S = self;
3843 let mut R: XMMATRIX = crate::undefined();
3844 R.r[0] = XMVectorScale(M.r[0], S);
3845 R.r[1] = XMVectorScale(M.r[1], S);
3846 R.r[2] = XMVectorScale(M.r[2], S);
3847 R.r[3] = XMVectorScale(M.r[3], S);
3848 return XMMatrix(R);
3849 }
3850 }
3851}
3852
3853impl std::ops::Mul<f32> for XMMatrix {
3854 type Output = XMMatrix;
3855 #[inline]
3856 fn mul(self, S: f32) -> XMMatrix {
3857 unsafe {
3858 let mut R: XMMATRIX = crate::undefined();
3859 R.r[0] = XMVectorScale(self.r[0], S);
3860 R.r[1] = XMVectorScale(self.r[1], S);
3861 R.r[2] = XMVectorScale(self.r[2], S);
3862 R.r[3] = XMVectorScale(self.r[3], S);
3863 return XMMatrix(R);
3864 }
3865 }
3866}
3867
3868impl std::ops::MulAssign<f32> for XMMatrix {
3869 #[inline]
3870 fn mul_assign(&mut self, S: f32) {
3871 unsafe {
3872 self.r[0] = XMVectorScale(self.r[0], S);
3873 self.r[1] = XMVectorScale(self.r[1], S);
3874 self.r[2] = XMVectorScale(self.r[2], S);
3875 self.r[3] = XMVectorScale(self.r[3], S);
3876 }
3877 }
3878}
3879
3880impl std::ops::Div<f32> for XMMatrix {
3881 type Output = XMMatrix;
3882 #[inline]
3883 fn div(self, S: f32) -> XMMatrix {
3884 #[cfg(_XM_NO_INTRINSICS_)]
3885 unsafe {
3886 let vS: XMVECTOR = XMVectorReplicate(S);
3887 let mut R: XMMATRIX = crate::undefined();
3888 R.r[0] = XMVectorDivide(self.r[0], vS);
3889 R.r[1] = XMVectorDivide(self.r[1], vS);
3890 R.r[2] = XMVectorDivide(self.r[2], vS);
3891 R.r[3] = XMVectorDivide(self.r[3], vS);
3892 return XMMatrix(R);
3893 }
3894
3895 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
3896 {
3897 unimplemented!()
3898 }
3899
3900 #[cfg(_XM_SSE_INTRINSICS_)]
3901 unsafe {
3902 let vS: __m128 = _mm_set_ps1(S);
3903 let mut R: XMMATRIX = crate::undefined();
3904 R.r[0] = _mm_div_ps(self.r[0], vS);
3905 R.r[1] = _mm_div_ps(self.r[1], vS);
3906 R.r[2] = _mm_div_ps(self.r[2], vS);
3907 R.r[3] = _mm_div_ps(self.r[3], vS);
3908 return XMMatrix(R);
3909 }
3910 }
3911}
3912
3913impl std::ops::DivAssign<f32> for XMMatrix {
3914 #[inline]
3915 fn div_assign(&mut self, S: f32) {
3916 #[cfg(_XM_NO_INTRINSICS_)]
3917 unsafe {
3918 let vS: XMVECTOR = XMVectorReplicate(S);
3919 self.r[0] = XMVectorDivide(self.r[0], vS);
3920 self.r[1] = XMVectorDivide(self.r[1], vS);
3921 self.r[2] = XMVectorDivide(self.r[2], vS);
3922 self.r[3] = XMVectorDivide(self.r[3], vS);
3923 }
3924
3925 #[cfg(_XM_ARM_NEON_INTRINSICS_)]
3926 {
3927 unimplemented!()
3928 }
3929
3930 #[cfg(_XM_SSE_INTRINSICS_)]
3931 unsafe {
3932 let vS: __m128 = _mm_set_ps1(S);
3933 self.r[0] = _mm_div_ps(self.r[0], vS);
3934 self.r[1] = _mm_div_ps(self.r[1], vS);
3935 self.r[2] = _mm_div_ps(self.r[2], vS);
3936 self.r[3] = _mm_div_ps(self.r[3], vS);
3937 }
3938 }
3939}
3940
3941impl std::ops::Neg for XMMatrix {
3942 type Output = XMMatrix;
3943 #[inline]
3944 fn neg(self) -> Self::Output {
3945 unsafe {
3946 let mut R: XMMATRIX = crate::undefined();
3947 R.r[0] = XMVectorNegate(self.r[0]);
3948 R.r[1] = XMVectorNegate(self.r[1]);
3949 R.r[2] = XMVectorNegate(self.r[2]);
3950 R.r[3] = XMVectorNegate(self.r[3]);
3951 XMMatrix(R)
3952 }
3953 }
3954}
3955
3956impl std::cmp::PartialEq for XMMatrix {
3957 #[inline]
3958 fn eq(&self, rhs: &Self) -> bool {
3959 unsafe {
3960 XMVector(self.r[0]) == XMVector(rhs.r[0]) &&
3961 XMVector(self.r[1]) == XMVector(rhs.r[1]) &&
3962 XMVector(self.r[2]) == XMVector(rhs.r[2]) &&
3963 XMVector(self.r[3]) == XMVector(rhs.r[3])
3964 }
3965 }
3966}
3967
3968impl std::fmt::Debug for XMMatrix {
3969 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3970 let rows = unsafe {
3971 &[
3972 [
3973 XMVectorGetX(self.r[0]),
3974 XMVectorGetY(self.r[0]),
3975 XMVectorGetZ(self.r[0]),
3976 XMVectorGetW(self.r[0]),
3977 ],
3978 [
3979 XMVectorGetX(self.r[1]),
3980 XMVectorGetY(self.r[1]),
3981 XMVectorGetZ(self.r[1]),
3982 XMVectorGetW(self.r[1]),
3983 ],
3984 [
3985 XMVectorGetX(self.r[2]),
3986 XMVectorGetY(self.r[2]),
3987 XMVectorGetZ(self.r[2]),
3988 XMVectorGetW(self.r[2]),
3989 ],
3990 [
3991 XMVectorGetX(self.r[3]),
3992 XMVectorGetY(self.r[3]),
3993 XMVectorGetZ(self.r[3]),
3994 XMVectorGetW(self.r[3]),
3995 ],
3996 ]
3997 };
3998 f.debug_list()
3999 .entries(rows)
4000 .finish()
4001 }
4002}
4003
4004#[test]
4005fn test_debug() {
4006 #[rustfmt::skip]
4007 let m = XMMatrix::from(&[
4008 [ 1.0, 2.0, 3.0, 4.0],
4009 [ 5.0, 6.0, 7.0, 8.0],
4010 [ 9.0, 10.0, 11.0, 12.0],
4011 [13.0, 14.0, 15.0, 16.0],
4012 ]);
4013 let s = format!("{:?}", m);
4014 assert_eq!("[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0]]", s);
4015}