]> git.cworth.org Git - apitrace/blob - thirdparty/directxtex/XNAMath/xnamathmatrix.inl
thirdparty/directxtex: Import DirectXTex library.
[apitrace] / thirdparty / directxtex / XNAMath / xnamathmatrix.inl
1 /************************************************************************
2 *                                                                       *
3 * xnamathmatrix.inl -- SIMD C++ Math library for Windows and Xbox 360   *
4 *                      Matrix functions                                 *
5 *                                                                       *
6 * Copyright (c) Microsoft Corp. All rights reserved.                    *
7 *                                                                       *
8 ************************************************************************/
9
10 #if defined(_MSC_VER) && (_MSC_VER > 1000)
11 #pragma once
12 #endif
13
14 #ifndef __XNAMATHMATRIX_INL__
15 #define __XNAMATHMATRIX_INL__
16
17 /****************************************************************************
18  *
19  * Matrix
20  *
21  ****************************************************************************/
22
23 //------------------------------------------------------------------------------
24 // Comparison operations
25 //------------------------------------------------------------------------------
26
27 //------------------------------------------------------------------------------
28
29 // Return TRUE if any entry in the matrix is NaN
30 XMFINLINE BOOL XMMatrixIsNaN
31 (
32     CXMMATRIX M
33 )
34 {
35 #if defined(_XM_NO_INTRINSICS_)
36     UINT i, uTest;
37     const UINT *pWork;
38
39     i = 16;
40     pWork = (const UINT *)(&M.m[0][0]);
41     do {
42         // Fetch value into integer unit
43         uTest = pWork[0];
44         // Remove sign
45         uTest &= 0x7FFFFFFFU;
46         // NaN is 0x7F800001 through 0x7FFFFFFF inclusive
47         uTest -= 0x7F800001U;
48         if (uTest<0x007FFFFFU) {
49             break;      // NaN found
50         }
51         ++pWork;        // Next entry
52     } while (--i);
53     return (i!=0);      // i == 0 if nothing matched
54 #elif defined(_XM_SSE_INTRINSICS_)
55     // Load in registers
56     XMVECTOR vX = M.r[0];
57     XMVECTOR vY = M.r[1];
58     XMVECTOR vZ = M.r[2];
59     XMVECTOR vW = M.r[3];
60     // Test themselves to check for NaN
61     vX = _mm_cmpneq_ps(vX,vX);
62     vY = _mm_cmpneq_ps(vY,vY);
63     vZ = _mm_cmpneq_ps(vZ,vZ);
64     vW = _mm_cmpneq_ps(vW,vW);
65     // Or all the results
66     vX = _mm_or_ps(vX,vZ);
67     vY = _mm_or_ps(vY,vW);
68     vX = _mm_or_ps(vX,vY);
69     // If any tested true, return true
70     return (_mm_movemask_ps(vX)!=0);
71 #else
72 #endif
73 }
74
75 //------------------------------------------------------------------------------
76
77 // Return TRUE if any entry in the matrix is +/-INF
78 XMFINLINE BOOL XMMatrixIsInfinite
79 (
80     CXMMATRIX M
81 )
82 {
83 #if defined(_XM_NO_INTRINSICS_)
84     UINT i, uTest;
85     const UINT *pWork;
86
87     i = 16;
88     pWork = (const UINT *)(&M.m[0][0]);
89     do {
90         // Fetch value into integer unit
91         uTest = pWork[0];
92         // Remove sign
93         uTest &= 0x7FFFFFFFU;
94         // INF is 0x7F800000
95         if (uTest==0x7F800000U) {
96             break;      // INF found
97         }
98         ++pWork;        // Next entry
99     } while (--i);
100     return (i!=0);      // i == 0 if nothing matched
101 #elif defined(_XM_SSE_INTRINSICS_)
102     // Mask off the sign bits
103     XMVECTOR vTemp1 = _mm_and_ps(M.r[0],g_XMAbsMask);
104     XMVECTOR vTemp2 = _mm_and_ps(M.r[1],g_XMAbsMask);
105     XMVECTOR vTemp3 = _mm_and_ps(M.r[2],g_XMAbsMask);
106     XMVECTOR vTemp4 = _mm_and_ps(M.r[3],g_XMAbsMask);
107     // Compare to infinity
108     vTemp1 = _mm_cmpeq_ps(vTemp1,g_XMInfinity);
109     vTemp2 = _mm_cmpeq_ps(vTemp2,g_XMInfinity);
110     vTemp3 = _mm_cmpeq_ps(vTemp3,g_XMInfinity);
111     vTemp4 = _mm_cmpeq_ps(vTemp4,g_XMInfinity);
112     // Or the answers together
113     vTemp1 = _mm_or_ps(vTemp1,vTemp2);
114     vTemp3 = _mm_or_ps(vTemp3,vTemp4);
115     vTemp1 = _mm_or_ps(vTemp1,vTemp3);
116     // If any are infinity, the signs are true.
117     return (_mm_movemask_ps(vTemp1)!=0);
118 #else // _XM_VMX128_INTRINSICS_
119 #endif // _XM_VMX128_INTRINSICS_
120 }
121
122 //------------------------------------------------------------------------------
123
124 // Return TRUE if the XMMatrix is equal to identity
125 XMFINLINE BOOL XMMatrixIsIdentity
126 (
127     CXMMATRIX M
128 )
129 {
130 #if defined(_XM_NO_INTRINSICS_)
131     unsigned int uOne, uZero;
132     const unsigned int *pWork;
133
134     // Use the integer pipeline to reduce branching to a minimum
135     pWork = (const unsigned int*)(&M.m[0][0]);
136     // Convert 1.0f to zero and or them together
137     uOne = pWork[0]^0x3F800000U;
138     // Or all the 0.0f entries together
139     uZero = pWork[1];
140     uZero |= pWork[2];
141     uZero |= pWork[3];
142     // 2nd row
143     uZero |= pWork[4];
144     uOne |= pWork[5]^0x3F800000U;
145     uZero |= pWork[6];
146     uZero |= pWork[7];
147     // 3rd row
148     uZero |= pWork[8];
149     uZero |= pWork[9];
150     uOne |= pWork[10]^0x3F800000U;
151     uZero |= pWork[11];
152     // 4th row
153     uZero |= pWork[12];
154     uZero |= pWork[13];
155     uZero |= pWork[14];
156     uOne |= pWork[15]^0x3F800000U;
157     // If all zero entries are zero, the uZero==0
158     uZero &= 0x7FFFFFFF;    // Allow -0.0f
159     // If all 1.0f entries are 1.0f, then uOne==0
160     uOne |= uZero;
161     return (uOne==0);
162 #elif defined(_XM_SSE_INTRINSICS_)
163     XMVECTOR vTemp1 = _mm_cmpeq_ps(M.r[0],g_XMIdentityR0);
164     XMVECTOR vTemp2 = _mm_cmpeq_ps(M.r[1],g_XMIdentityR1);
165     XMVECTOR vTemp3 = _mm_cmpeq_ps(M.r[2],g_XMIdentityR2);
166     XMVECTOR vTemp4 = _mm_cmpeq_ps(M.r[3],g_XMIdentityR3);
167     vTemp1 = _mm_and_ps(vTemp1,vTemp2);
168     vTemp3 = _mm_and_ps(vTemp3,vTemp4);
169     vTemp1 = _mm_and_ps(vTemp1,vTemp3);
170     return (_mm_movemask_ps(vTemp1)==0x0f);
171 #else // _XM_VMX128_INTRINSICS_
172 #endif // _XM_VMX128_INTRINSICS_
173 }
174
175 //------------------------------------------------------------------------------
176 // Computation operations
177 //------------------------------------------------------------------------------
178
179 //------------------------------------------------------------------------------
180 // Perform a 4x4 matrix multiply by a 4x4 matrix
181 XMFINLINE XMMATRIX XMMatrixMultiply
182 (
183     CXMMATRIX M1, 
184     CXMMATRIX M2
185 )
186 {
187 #if defined(_XM_NO_INTRINSICS_)
188     XMMATRIX mResult;
189     // Cache the invariants in registers
190     float x = M1.m[0][0];
191     float y = M1.m[0][1];
192     float z = M1.m[0][2];
193     float w = M1.m[0][3];
194     // Perform the operation on the first row
195     mResult.m[0][0] = (M2.m[0][0]*x)+(M2.m[1][0]*y)+(M2.m[2][0]*z)+(M2.m[3][0]*w);
196     mResult.m[0][1] = (M2.m[0][1]*x)+(M2.m[1][1]*y)+(M2.m[2][1]*z)+(M2.m[3][1]*w);
197     mResult.m[0][2] = (M2.m[0][2]*x)+(M2.m[1][2]*y)+(M2.m[2][2]*z)+(M2.m[3][2]*w);
198     mResult.m[0][3] = (M2.m[0][3]*x)+(M2.m[1][3]*y)+(M2.m[2][3]*z)+(M2.m[3][3]*w);
199     // Repeat for all the other rows
200     x = M1.m[1][0];
201     y = M1.m[1][1];
202     z = M1.m[1][2];
203     w = M1.m[1][3];
204     mResult.m[1][0] = (M2.m[0][0]*x)+(M2.m[1][0]*y)+(M2.m[2][0]*z)+(M2.m[3][0]*w);
205     mResult.m[1][1] = (M2.m[0][1]*x)+(M2.m[1][1]*y)+(M2.m[2][1]*z)+(M2.m[3][1]*w);
206     mResult.m[1][2] = (M2.m[0][2]*x)+(M2.m[1][2]*y)+(M2.m[2][2]*z)+(M2.m[3][2]*w);
207     mResult.m[1][3] = (M2.m[0][3]*x)+(M2.m[1][3]*y)+(M2.m[2][3]*z)+(M2.m[3][3]*w);
208     x = M1.m[2][0];
209     y = M1.m[2][1];
210     z = M1.m[2][2];
211     w = M1.m[2][3];
212     mResult.m[2][0] = (M2.m[0][0]*x)+(M2.m[1][0]*y)+(M2.m[2][0]*z)+(M2.m[3][0]*w);
213     mResult.m[2][1] = (M2.m[0][1]*x)+(M2.m[1][1]*y)+(M2.m[2][1]*z)+(M2.m[3][1]*w);
214     mResult.m[2][2] = (M2.m[0][2]*x)+(M2.m[1][2]*y)+(M2.m[2][2]*z)+(M2.m[3][2]*w);
215     mResult.m[2][3] = (M2.m[0][3]*x)+(M2.m[1][3]*y)+(M2.m[2][3]*z)+(M2.m[3][3]*w);
216     x = M1.m[3][0];
217     y = M1.m[3][1];
218     z = M1.m[3][2];
219     w = M1.m[3][3];
220     mResult.m[3][0] = (M2.m[0][0]*x)+(M2.m[1][0]*y)+(M2.m[2][0]*z)+(M2.m[3][0]*w);
221     mResult.m[3][1] = (M2.m[0][1]*x)+(M2.m[1][1]*y)+(M2.m[2][1]*z)+(M2.m[3][1]*w);
222     mResult.m[3][2] = (M2.m[0][2]*x)+(M2.m[1][2]*y)+(M2.m[2][2]*z)+(M2.m[3][2]*w);
223     mResult.m[3][3] = (M2.m[0][3]*x)+(M2.m[1][3]*y)+(M2.m[2][3]*z)+(M2.m[3][3]*w);
224     return mResult;
225 #elif defined(_XM_SSE_INTRINSICS_)
226     XMMATRIX mResult;
227     // Use vW to hold the original row
228     XMVECTOR vW = M1.r[0];
229     // Splat the component X,Y,Z then W
230     XMVECTOR vX = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(0,0,0,0));
231     XMVECTOR vY = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(1,1,1,1));
232     XMVECTOR vZ = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(2,2,2,2));
233     vW = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(3,3,3,3));
234     // Perform the opertion on the first row
235     vX = _mm_mul_ps(vX,M2.r[0]);
236     vY = _mm_mul_ps(vY,M2.r[1]);
237     vZ = _mm_mul_ps(vZ,M2.r[2]);
238     vW = _mm_mul_ps(vW,M2.r[3]);
239     // Perform a binary add to reduce cumulative errors
240     vX = _mm_add_ps(vX,vZ);
241     vY = _mm_add_ps(vY,vW);
242     vX = _mm_add_ps(vX,vY);
243     mResult.r[0] = vX;
244     // Repeat for the other 3 rows
245     vW = M1.r[1];
246     vX = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(0,0,0,0));
247     vY = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(1,1,1,1));
248     vZ = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(2,2,2,2));
249     vW = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(3,3,3,3));
250     vX = _mm_mul_ps(vX,M2.r[0]);
251     vY = _mm_mul_ps(vY,M2.r[1]);
252     vZ = _mm_mul_ps(vZ,M2.r[2]);
253     vW = _mm_mul_ps(vW,M2.r[3]);
254     vX = _mm_add_ps(vX,vZ);
255     vY = _mm_add_ps(vY,vW);
256     vX = _mm_add_ps(vX,vY);
257     mResult.r[1] = vX;
258     vW = M1.r[2];
259     vX = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(0,0,0,0));
260     vY = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(1,1,1,1));
261     vZ = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(2,2,2,2));
262     vW = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(3,3,3,3));
263     vX = _mm_mul_ps(vX,M2.r[0]);
264     vY = _mm_mul_ps(vY,M2.r[1]);
265     vZ = _mm_mul_ps(vZ,M2.r[2]);
266     vW = _mm_mul_ps(vW,M2.r[3]);
267     vX = _mm_add_ps(vX,vZ);
268     vY = _mm_add_ps(vY,vW);
269     vX = _mm_add_ps(vX,vY);
270     mResult.r[2] = vX;
271     vW = M1.r[3];
272     vX = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(0,0,0,0));
273     vY = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(1,1,1,1));
274     vZ = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(2,2,2,2));
275     vW = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(3,3,3,3));
276     vX = _mm_mul_ps(vX,M2.r[0]);
277     vY = _mm_mul_ps(vY,M2.r[1]);
278     vZ = _mm_mul_ps(vZ,M2.r[2]);
279     vW = _mm_mul_ps(vW,M2.r[3]);
280     vX = _mm_add_ps(vX,vZ);
281     vY = _mm_add_ps(vY,vW);
282     vX = _mm_add_ps(vX,vY);
283     mResult.r[3] = vX;
284     return mResult;
285 #else // _XM_VMX128_INTRINSICS_
286 #endif // _XM_VMX128_INTRINSICS_
287 }
288
289 //------------------------------------------------------------------------------
290
291 XMFINLINE XMMATRIX XMMatrixMultiplyTranspose
292 (
293     CXMMATRIX M1, 
294     CXMMATRIX M2
295 )
296 {
297 #if defined(_XM_NO_INTRINSICS_)
298     XMMATRIX mResult;
299     // Cache the invariants in registers
300     float x = M2.m[0][0];
301     float y = M2.m[1][0];
302     float z = M2.m[2][0];
303     float w = M2.m[3][0];
304     // Perform the operation on the first row
305     mResult.m[0][0] = (M1.m[0][0]*x)+(M1.m[0][1]*y)+(M1.m[0][2]*z)+(M1.m[0][3]*w);
306     mResult.m[0][1] = (M1.m[1][0]*x)+(M1.m[1][1]*y)+(M1.m[1][2]*z)+(M1.m[1][3]*w);
307     mResult.m[0][2] = (M1.m[2][0]*x)+(M1.m[2][1]*y)+(M1.m[2][2]*z)+(M1.m[2][3]*w);
308     mResult.m[0][3] = (M1.m[3][0]*x)+(M1.m[3][1]*y)+(M1.m[3][2]*z)+(M1.m[3][3]*w);
309     // Repeat for all the other rows
310     x = M2.m[0][1];
311     y = M2.m[1][1];
312     z = M2.m[2][1];
313     w = M2.m[3][1];
314     mResult.m[1][0] = (M1.m[0][0]*x)+(M1.m[0][1]*y)+(M1.m[0][2]*z)+(M1.m[0][3]*w);
315     mResult.m[1][1] = (M1.m[1][0]*x)+(M1.m[1][1]*y)+(M1.m[1][2]*z)+(M1.m[1][3]*w);
316     mResult.m[1][2] = (M1.m[2][0]*x)+(M1.m[2][1]*y)+(M1.m[2][2]*z)+(M1.m[2][3]*w);
317     mResult.m[1][3] = (M1.m[3][0]*x)+(M1.m[3][1]*y)+(M1.m[3][2]*z)+(M1.m[3][3]*w);
318     x = M2.m[0][2];
319     y = M2.m[1][2];
320     z = M2.m[2][2];
321     w = M2.m[3][2];
322     mResult.m[2][0] = (M1.m[0][0]*x)+(M1.m[0][1]*y)+(M1.m[0][2]*z)+(M1.m[0][3]*w);
323     mResult.m[2][1] = (M1.m[1][0]*x)+(M1.m[1][1]*y)+(M1.m[1][2]*z)+(M1.m[1][3]*w);
324     mResult.m[2][2] = (M1.m[2][0]*x)+(M1.m[2][1]*y)+(M1.m[2][2]*z)+(M1.m[2][3]*w);
325     mResult.m[2][3] = (M1.m[3][0]*x)+(M1.m[3][1]*y)+(M1.m[3][2]*z)+(M1.m[3][3]*w);
326     x = M2.m[0][3];
327     y = M2.m[1][3];
328     z = M2.m[2][3];
329     w = M2.m[3][3];
330     mResult.m[3][0] = (M1.m[0][0]*x)+(M1.m[0][1]*y)+(M1.m[0][2]*z)+(M1.m[0][3]*w);
331     mResult.m[3][1] = (M1.m[1][0]*x)+(M1.m[1][1]*y)+(M1.m[1][2]*z)+(M1.m[1][3]*w);
332     mResult.m[3][2] = (M1.m[2][0]*x)+(M1.m[2][1]*y)+(M1.m[2][2]*z)+(M1.m[2][3]*w);
333     mResult.m[3][3] = (M1.m[3][0]*x)+(M1.m[3][1]*y)+(M1.m[3][2]*z)+(M1.m[3][3]*w);
334     return mResult;
335 #elif defined(_XM_SSE_INTRINSICS_)
336     XMMATRIX Product;
337     XMMATRIX Result;
338     Product = XMMatrixMultiply(M1, M2);
339     Result = XMMatrixTranspose(Product);
340     return Result;
341 #else // _XM_VMX128_INTRINSICS_
342 #endif // _XM_VMX128_INTRINSICS_
343 }
344
345 //------------------------------------------------------------------------------
346
347 XMFINLINE XMMATRIX XMMatrixTranspose
348 (
349     CXMMATRIX M
350 )
351 {
352 #if defined(_XM_NO_INTRINSICS_)
353
354     XMMATRIX P;
355     XMMATRIX MT;
356
357     // Original matrix:
358     //
359     //     m00m01m02m03
360     //     m10m11m12m13
361     //     m20m21m22m23
362     //     m30m31m32m33
363
364     P.r[0] = XMVectorMergeXY(M.r[0], M.r[2]); // m00m20m01m21
365     P.r[1] = XMVectorMergeXY(M.r[1], M.r[3]); // m10m30m11m31
366     P.r[2] = XMVectorMergeZW(M.r[0], M.r[2]); // m02m22m03m23
367     P.r[3] = XMVectorMergeZW(M.r[1], M.r[3]); // m12m32m13m33
368
369     MT.r[0] = XMVectorMergeXY(P.r[0], P.r[1]); // m00m10m20m30
370     MT.r[1] = XMVectorMergeZW(P.r[0], P.r[1]); // m01m11m21m31
371     MT.r[2] = XMVectorMergeXY(P.r[2], P.r[3]); // m02m12m22m32
372     MT.r[3] = XMVectorMergeZW(P.r[2], P.r[3]); // m03m13m23m33
373
374     return MT;
375
376 #elif defined(_XM_SSE_INTRINSICS_)
377     // x.x,x.y,y.x,y.y
378     XMVECTOR vTemp1 = _mm_shuffle_ps(M.r[0],M.r[1],_MM_SHUFFLE(1,0,1,0));
379     // x.z,x.w,y.z,y.w
380     XMVECTOR vTemp3 = _mm_shuffle_ps(M.r[0],M.r[1],_MM_SHUFFLE(3,2,3,2));
381     // z.x,z.y,w.x,w.y
382     XMVECTOR vTemp2 = _mm_shuffle_ps(M.r[2],M.r[3],_MM_SHUFFLE(1,0,1,0));
383     // z.z,z.w,w.z,w.w
384     XMVECTOR vTemp4 = _mm_shuffle_ps(M.r[2],M.r[3],_MM_SHUFFLE(3,2,3,2));
385     XMMATRIX mResult;
386
387     // x.x,y.x,z.x,w.x
388     mResult.r[0] = _mm_shuffle_ps(vTemp1, vTemp2,_MM_SHUFFLE(2,0,2,0));
389     // x.y,y.y,z.y,w.y
390     mResult.r[1] = _mm_shuffle_ps(vTemp1, vTemp2,_MM_SHUFFLE(3,1,3,1));
391     // x.z,y.z,z.z,w.z
392     mResult.r[2] = _mm_shuffle_ps(vTemp3, vTemp4,_MM_SHUFFLE(2,0,2,0));
393     // x.w,y.w,z.w,w.w
394     mResult.r[3] = _mm_shuffle_ps(vTemp3, vTemp4,_MM_SHUFFLE(3,1,3,1));
395     return mResult;
396 #else // _XM_VMX128_INTRINSICS_
397 #endif // _XM_VMX128_INTRINSICS_
398 }
399
400 //------------------------------------------------------------------------------
401 // Return the inverse and the determinant of a 4x4 matrix
402 XMINLINE XMMATRIX XMMatrixInverse
403 (
404     XMVECTOR* pDeterminant, 
405     CXMMATRIX  M
406 )
407 {
408 #if defined(_XM_NO_INTRINSICS_)
409
410     XMMATRIX               R;
411     XMMATRIX               MT;
412     XMVECTOR               D0, D1, D2;
413     XMVECTOR               C0, C1, C2, C3, C4, C5, C6, C7;
414     XMVECTOR               V0[4], V1[4];
415     XMVECTOR               Determinant;
416     XMVECTOR               Reciprocal;
417     XMMATRIX               Result;
418     static CONST XMVECTORU32 SwizzleXXYY = {XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_0Y};
419     static CONST XMVECTORU32 SwizzleZWZW = {XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_0Z, XM_PERMUTE_0W};
420     static CONST XMVECTORU32 SwizzleYZXY = {XM_PERMUTE_0Y, XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0Y};
421     static CONST XMVECTORU32 SwizzleZWYZ = {XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_0Y, XM_PERMUTE_0Z};
422     static CONST XMVECTORU32 SwizzleWXWX = {XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0X};
423     static CONST XMVECTORU32 SwizzleZXYX = {XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_0X};
424     static CONST XMVECTORU32 SwizzleYWXZ = {XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0Z};
425     static CONST XMVECTORU32 SwizzleWZWY = {XM_PERMUTE_0W, XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_0Y};
426     static CONST XMVECTORU32 Permute0X0Z1X1Z = {XM_PERMUTE_0X, XM_PERMUTE_0Z, XM_PERMUTE_1X, XM_PERMUTE_1Z};
427     static CONST XMVECTORU32 Permute0Y0W1Y1W = {XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_1Y, XM_PERMUTE_1W};
428     static CONST XMVECTORU32 Permute1Y0Y0W0X = {XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_0X};
429     static CONST XMVECTORU32 Permute0W0X0Y1X = {XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_1X};
430     static CONST XMVECTORU32 Permute0Z1Y1X0Z = {XM_PERMUTE_0Z, XM_PERMUTE_1Y, XM_PERMUTE_1X, XM_PERMUTE_0Z};
431     static CONST XMVECTORU32 Permute0W1Y0Y0Z = {XM_PERMUTE_0W, XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_0Z};
432     static CONST XMVECTORU32 Permute0Z0Y1X0X = {XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_0X};
433     static CONST XMVECTORU32 Permute1Y0X0W1X = {XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_1X};
434     static CONST XMVECTORU32 Permute1W0Y0W0X = {XM_PERMUTE_1W, XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_0X};
435     static CONST XMVECTORU32 Permute0W0X0Y1Z = {XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_1Z};
436     static CONST XMVECTORU32 Permute0Z1W1Z0Z = {XM_PERMUTE_0Z, XM_PERMUTE_1W, XM_PERMUTE_1Z, XM_PERMUTE_0Z};
437     static CONST XMVECTORU32 Permute0W1W0Y0Z = {XM_PERMUTE_0W, XM_PERMUTE_1W, XM_PERMUTE_0Y, XM_PERMUTE_0Z};
438     static CONST XMVECTORU32 Permute0Z0Y1Z0X = {XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1Z, XM_PERMUTE_0X};
439     static CONST XMVECTORU32 Permute1W0X0W1Z = {XM_PERMUTE_1W, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_1Z};
440
441     MT = XMMatrixTranspose(M);
442
443     V0[0] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleXXYY.v);
444     V1[0] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleZWZW.v);
445     V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleXXYY.v);
446     V1[1] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleZWZW.v);
447     V0[2] = XMVectorPermute(MT.r[2], MT.r[0], Permute0X0Z1X1Z.v);
448     V1[2] = XMVectorPermute(MT.r[3], MT.r[1], Permute0Y0W1Y1W.v);
449
450     D0 = XMVectorMultiply(V0[0], V1[0]);
451     D1 = XMVectorMultiply(V0[1], V1[1]);
452     D2 = XMVectorMultiply(V0[2], V1[2]);
453
454     V0[0] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleZWZW.v);
455     V1[0] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleXXYY.v);
456     V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleZWZW.v);
457     V1[1] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleXXYY.v);
458     V0[2] = XMVectorPermute(MT.r[2], MT.r[0], Permute0Y0W1Y1W.v);
459     V1[2] = XMVectorPermute(MT.r[3], MT.r[1], Permute0X0Z1X1Z.v);
460
461     D0 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], D0);
462     D1 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], D1);
463     D2 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], D2);
464
465     V0[0] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleYZXY.v);
466     V1[0] = XMVectorPermute(D0, D2, Permute1Y0Y0W0X.v);
467     V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleZXYX.v);
468     V1[1] = XMVectorPermute(D0, D2, Permute0W1Y0Y0Z.v);
469     V0[2] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleYZXY.v);
470     V1[2] = XMVectorPermute(D1, D2, Permute1W0Y0W0X.v);
471     V0[3] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleZXYX.v);
472     V1[3] = XMVectorPermute(D1, D2, Permute0W1W0Y0Z.v);
473
474     C0 = XMVectorMultiply(V0[0], V1[0]);
475     C2 = XMVectorMultiply(V0[1], V1[1]);
476     C4 = XMVectorMultiply(V0[2], V1[2]);
477     C6 = XMVectorMultiply(V0[3], V1[3]);
478
479     V0[0] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleZWYZ.v);
480     V1[0] = XMVectorPermute(D0, D2, Permute0W0X0Y1X.v);
481     V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleWZWY.v);
482     V1[1] = XMVectorPermute(D0, D2, Permute0Z0Y1X0X.v);
483     V0[2] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleZWYZ.v);
484     V1[2] = XMVectorPermute(D1, D2, Permute0W0X0Y1Z.v);
485     V0[3] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleWZWY.v);
486     V1[3] = XMVectorPermute(D1, D2, Permute0Z0Y1Z0X.v);
487
488     C0 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], C0);
489     C2 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], C2);
490     C4 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], C4);
491     C6 = XMVectorNegativeMultiplySubtract(V0[3], V1[3], C6);
492
493     V0[0] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleWXWX.v);
494     V1[0] = XMVectorPermute(D0, D2, Permute0Z1Y1X0Z.v);
495     V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleYWXZ.v);
496     V1[1] = XMVectorPermute(D0, D2, Permute1Y0X0W1X.v);
497     V0[2] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleWXWX.v);
498     V1[2] = XMVectorPermute(D1, D2, Permute0Z1W1Z0Z.v);
499     V0[3] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleYWXZ.v);
500     V1[3] = XMVectorPermute(D1, D2, Permute1W0X0W1Z.v);
501
502     C1 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], C0);
503     C0 = XMVectorMultiplyAdd(V0[0], V1[0], C0);
504     C3 = XMVectorMultiplyAdd(V0[1], V1[1], C2);
505     C2 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], C2);
506     C5 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], C4);
507     C4 = XMVectorMultiplyAdd(V0[2], V1[2], C4);
508     C7 = XMVectorMultiplyAdd(V0[3], V1[3], C6);
509     C6 = XMVectorNegativeMultiplySubtract(V0[3], V1[3], C6);
510
511     R.r[0] = XMVectorSelect(C0, C1, g_XMSelect0101.v);
512     R.r[1] = XMVectorSelect(C2, C3, g_XMSelect0101.v);
513     R.r[2] = XMVectorSelect(C4, C5, g_XMSelect0101.v);
514     R.r[3] = XMVectorSelect(C6, C7, g_XMSelect0101.v);
515
516     Determinant = XMVector4Dot(R.r[0], MT.r[0]);
517
518     if (pDeterminant)
519         *pDeterminant = Determinant;
520
521     Reciprocal = XMVectorReciprocal(Determinant);
522
523     Result.r[0] = XMVectorMultiply(R.r[0], Reciprocal);
524     Result.r[1] = XMVectorMultiply(R.r[1], Reciprocal);
525     Result.r[2] = XMVectorMultiply(R.r[2], Reciprocal);
526     Result.r[3] = XMVectorMultiply(R.r[3], Reciprocal);
527
528     return Result;
529
530 #elif defined(_XM_SSE_INTRINSICS_)
531     XMMATRIX MT = XMMatrixTranspose(M);
532     XMVECTOR V00 = _mm_shuffle_ps(MT.r[2], MT.r[2],_MM_SHUFFLE(1,1,0,0));
533     XMVECTOR V10 = _mm_shuffle_ps(MT.r[3], MT.r[3],_MM_SHUFFLE(3,2,3,2));
534     XMVECTOR V01 = _mm_shuffle_ps(MT.r[0], MT.r[0],_MM_SHUFFLE(1,1,0,0));
535     XMVECTOR V11 = _mm_shuffle_ps(MT.r[1], MT.r[1],_MM_SHUFFLE(3,2,3,2));
536     XMVECTOR V02 = _mm_shuffle_ps(MT.r[2], MT.r[0],_MM_SHUFFLE(2,0,2,0));
537     XMVECTOR V12 = _mm_shuffle_ps(MT.r[3], MT.r[1],_MM_SHUFFLE(3,1,3,1));
538
539     XMVECTOR D0 = _mm_mul_ps(V00,V10);
540     XMVECTOR D1 = _mm_mul_ps(V01,V11);
541     XMVECTOR D2 = _mm_mul_ps(V02,V12);
542
543     V00 = _mm_shuffle_ps(MT.r[2],MT.r[2],_MM_SHUFFLE(3,2,3,2));
544     V10 = _mm_shuffle_ps(MT.r[3],MT.r[3],_MM_SHUFFLE(1,1,0,0));
545     V01 = _mm_shuffle_ps(MT.r[0],MT.r[0],_MM_SHUFFLE(3,2,3,2));
546     V11 = _mm_shuffle_ps(MT.r[1],MT.r[1],_MM_SHUFFLE(1,1,0,0));
547     V02 = _mm_shuffle_ps(MT.r[2],MT.r[0],_MM_SHUFFLE(3,1,3,1));
548     V12 = _mm_shuffle_ps(MT.r[3],MT.r[1],_MM_SHUFFLE(2,0,2,0));
549
550     V00 = _mm_mul_ps(V00,V10);
551     V01 = _mm_mul_ps(V01,V11);
552     V02 = _mm_mul_ps(V02,V12);
553     D0 = _mm_sub_ps(D0,V00);
554     D1 = _mm_sub_ps(D1,V01);
555     D2 = _mm_sub_ps(D2,V02);
556     // V11 = D0Y,D0W,D2Y,D2Y
557     V11 = _mm_shuffle_ps(D0,D2,_MM_SHUFFLE(1,1,3,1));
558     V00 = _mm_shuffle_ps(MT.r[1], MT.r[1],_MM_SHUFFLE(1,0,2,1));
559     V10 = _mm_shuffle_ps(V11,D0,_MM_SHUFFLE(0,3,0,2));
560     V01 = _mm_shuffle_ps(MT.r[0], MT.r[0],_MM_SHUFFLE(0,1,0,2));
561     V11 = _mm_shuffle_ps(V11,D0,_MM_SHUFFLE(2,1,2,1));
562     // V13 = D1Y,D1W,D2W,D2W
563     XMVECTOR V13 = _mm_shuffle_ps(D1,D2,_MM_SHUFFLE(3,3,3,1));
564     V02 = _mm_shuffle_ps(MT.r[3], MT.r[3],_MM_SHUFFLE(1,0,2,1));
565     V12 = _mm_shuffle_ps(V13,D1,_MM_SHUFFLE(0,3,0,2));
566     XMVECTOR V03 = _mm_shuffle_ps(MT.r[2], MT.r[2],_MM_SHUFFLE(0,1,0,2));
567     V13 = _mm_shuffle_ps(V13,D1,_MM_SHUFFLE(2,1,2,1));
568
569     XMVECTOR C0 = _mm_mul_ps(V00,V10);
570     XMVECTOR C2 = _mm_mul_ps(V01,V11);
571     XMVECTOR C4 = _mm_mul_ps(V02,V12);
572     XMVECTOR C6 = _mm_mul_ps(V03,V13);
573
574     // V11 = D0X,D0Y,D2X,D2X
575     V11 = _mm_shuffle_ps(D0,D2,_MM_SHUFFLE(0,0,1,0));
576     V00 = _mm_shuffle_ps(MT.r[1], MT.r[1],_MM_SHUFFLE(2,1,3,2));
577     V10 = _mm_shuffle_ps(D0,V11,_MM_SHUFFLE(2,1,0,3));
578     V01 = _mm_shuffle_ps(MT.r[0], MT.r[0],_MM_SHUFFLE(1,3,2,3));
579     V11 = _mm_shuffle_ps(D0,V11,_MM_SHUFFLE(0,2,1,2));
580     // V13 = D1X,D1Y,D2Z,D2Z
581     V13 = _mm_shuffle_ps(D1,D2,_MM_SHUFFLE(2,2,1,0));
582     V02 = _mm_shuffle_ps(MT.r[3], MT.r[3],_MM_SHUFFLE(2,1,3,2));
583     V12 = _mm_shuffle_ps(D1,V13,_MM_SHUFFLE(2,1,0,3));
584     V03 = _mm_shuffle_ps(MT.r[2], MT.r[2],_MM_SHUFFLE(1,3,2,3));
585     V13 = _mm_shuffle_ps(D1,V13,_MM_SHUFFLE(0,2,1,2));
586
587     V00 = _mm_mul_ps(V00,V10);
588     V01 = _mm_mul_ps(V01,V11);
589     V02 = _mm_mul_ps(V02,V12);
590     V03 = _mm_mul_ps(V03,V13);
591     C0 = _mm_sub_ps(C0,V00);
592     C2 = _mm_sub_ps(C2,V01);
593     C4 = _mm_sub_ps(C4,V02);
594     C6 = _mm_sub_ps(C6,V03);
595
596     V00 = _mm_shuffle_ps(MT.r[1],MT.r[1],_MM_SHUFFLE(0,3,0,3));
597     // V10 = D0Z,D0Z,D2X,D2Y
598     V10 = _mm_shuffle_ps(D0,D2,_MM_SHUFFLE(1,0,2,2));
599     V10 = _mm_shuffle_ps(V10,V10,_MM_SHUFFLE(0,2,3,0));
600     V01 = _mm_shuffle_ps(MT.r[0],MT.r[0],_MM_SHUFFLE(2,0,3,1));
601     // V11 = D0X,D0W,D2X,D2Y
602     V11 = _mm_shuffle_ps(D0,D2,_MM_SHUFFLE(1,0,3,0));
603     V11 = _mm_shuffle_ps(V11,V11,_MM_SHUFFLE(2,1,0,3));
604     V02 = _mm_shuffle_ps(MT.r[3],MT.r[3],_MM_SHUFFLE(0,3,0,3));
605     // V12 = D1Z,D1Z,D2Z,D2W
606     V12 = _mm_shuffle_ps(D1,D2,_MM_SHUFFLE(3,2,2,2));
607     V12 = _mm_shuffle_ps(V12,V12,_MM_SHUFFLE(0,2,3,0));
608     V03 = _mm_shuffle_ps(MT.r[2],MT.r[2],_MM_SHUFFLE(2,0,3,1));
609     // V13 = D1X,D1W,D2Z,D2W
610     V13 = _mm_shuffle_ps(D1,D2,_MM_SHUFFLE(3,2,3,0));
611     V13 = _mm_shuffle_ps(V13,V13,_MM_SHUFFLE(2,1,0,3));
612
613     V00 = _mm_mul_ps(V00,V10);
614     V01 = _mm_mul_ps(V01,V11);
615     V02 = _mm_mul_ps(V02,V12);
616     V03 = _mm_mul_ps(V03,V13);
617     XMVECTOR C1 = _mm_sub_ps(C0,V00);
618     C0 = _mm_add_ps(C0,V00);
619     XMVECTOR C3 = _mm_add_ps(C2,V01);
620     C2 = _mm_sub_ps(C2,V01);
621     XMVECTOR C5 = _mm_sub_ps(C4,V02);
622     C4 = _mm_add_ps(C4,V02);
623     XMVECTOR C7 = _mm_add_ps(C6,V03);
624     C6 = _mm_sub_ps(C6,V03);
625
626     C0 = _mm_shuffle_ps(C0,C1,_MM_SHUFFLE(3,1,2,0));
627     C2 = _mm_shuffle_ps(C2,C3,_MM_SHUFFLE(3,1,2,0));
628     C4 = _mm_shuffle_ps(C4,C5,_MM_SHUFFLE(3,1,2,0));
629     C6 = _mm_shuffle_ps(C6,C7,_MM_SHUFFLE(3,1,2,0));
630     C0 = _mm_shuffle_ps(C0,C0,_MM_SHUFFLE(3,1,2,0));
631     C2 = _mm_shuffle_ps(C2,C2,_MM_SHUFFLE(3,1,2,0));
632     C4 = _mm_shuffle_ps(C4,C4,_MM_SHUFFLE(3,1,2,0));
633     C6 = _mm_shuffle_ps(C6,C6,_MM_SHUFFLE(3,1,2,0));
634     // Get the determinate
635     XMVECTOR vTemp = XMVector4Dot(C0,MT.r[0]);
636     if (pDeterminant)
637         *pDeterminant = vTemp;
638     vTemp = _mm_div_ps(g_XMOne,vTemp);
639     XMMATRIX mResult;
640     mResult.r[0] = _mm_mul_ps(C0,vTemp);
641     mResult.r[1] = _mm_mul_ps(C2,vTemp);
642     mResult.r[2] = _mm_mul_ps(C4,vTemp);
643     mResult.r[3] = _mm_mul_ps(C6,vTemp);
644     return mResult;
645 #else // _XM_VMX128_INTRINSICS_
646 #endif // _XM_VMX128_INTRINSICS_
647 }
648
649 //------------------------------------------------------------------------------
650
651 XMINLINE XMVECTOR XMMatrixDeterminant
652 (
653     CXMMATRIX M
654 )
655 {
656 #if defined(_XM_NO_INTRINSICS_)
657
658     XMVECTOR                V0, V1, V2, V3, V4, V5;
659     XMVECTOR                P0, P1, P2, R, S;
660     XMVECTOR                Result;
661     static CONST XMVECTORU32 SwizzleYXXX = {XM_PERMUTE_0Y, XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_0X};
662     static CONST XMVECTORU32 SwizzleZZYY = {XM_PERMUTE_0Z, XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_0Y};
663     static CONST XMVECTORU32 SwizzleWWWZ = {XM_PERMUTE_0W, XM_PERMUTE_0W, XM_PERMUTE_0W, XM_PERMUTE_0Z};
664     static CONST XMVECTOR   Sign = {1.0f, -1.0f, 1.0f, -1.0f};
665
666     V0 = XMVectorPermute(M.r[2], M.r[2], SwizzleYXXX.v);
667     V1 = XMVectorPermute(M.r[3], M.r[3], SwizzleZZYY.v);
668     V2 = XMVectorPermute(M.r[2], M.r[2], SwizzleYXXX.v);
669     V3 = XMVectorPermute(M.r[3], M.r[3], SwizzleWWWZ.v);
670     V4 = XMVectorPermute(M.r[2], M.r[2], SwizzleZZYY.v);
671     V5 = XMVectorPermute(M.r[3], M.r[3], SwizzleWWWZ.v);
672
673     P0 = XMVectorMultiply(V0, V1);
674     P1 = XMVectorMultiply(V2, V3);
675     P2 = XMVectorMultiply(V4, V5);
676
677     V0 = XMVectorPermute(M.r[2], M.r[2], SwizzleZZYY.v);
678     V1 = XMVectorPermute(M.r[3], M.r[3], SwizzleYXXX.v);
679     V2 = XMVectorPermute(M.r[2], M.r[2], SwizzleWWWZ.v);
680     V3 = XMVectorPermute(M.r[3], M.r[3], SwizzleYXXX.v);
681     V4 = XMVectorPermute(M.r[2], M.r[2], SwizzleWWWZ.v);
682     V5 = XMVectorPermute(M.r[3], M.r[3], SwizzleZZYY.v);
683
684     P0 = XMVectorNegativeMultiplySubtract(V0, V1, P0);
685     P1 = XMVectorNegativeMultiplySubtract(V2, V3, P1);
686     P2 = XMVectorNegativeMultiplySubtract(V4, V5, P2);
687
688     V0 = XMVectorPermute(M.r[1], M.r[1], SwizzleWWWZ.v);
689     V1 = XMVectorPermute(M.r[1], M.r[1], SwizzleZZYY.v);
690     V2 = XMVectorPermute(M.r[1], M.r[1], SwizzleYXXX.v);
691
692     S = XMVectorMultiply(M.r[0], Sign);
693     R = XMVectorMultiply(V0, P0);
694     R = XMVectorNegativeMultiplySubtract(V1, P1, R);
695     R = XMVectorMultiplyAdd(V2, P2, R);
696
697     Result = XMVector4Dot(S, R);
698
699     return Result;
700
701 #elif defined(_XM_SSE_INTRINSICS_)
702     XMVECTOR                V0, V1, V2, V3, V4, V5;
703     XMVECTOR                P0, P1, P2, R, S;
704     XMVECTOR                Result;
705     static CONST XMVECTORU32 SwizzleYXXX = {XM_PERMUTE_0Y, XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_0X};
706     static CONST XMVECTORU32 SwizzleZZYY = {XM_PERMUTE_0Z, XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_0Y};
707     static CONST XMVECTORU32 SwizzleWWWZ = {XM_PERMUTE_0W, XM_PERMUTE_0W, XM_PERMUTE_0W, XM_PERMUTE_0Z};
708     static CONST XMVECTORF32 Sign = {1.0f, -1.0f, 1.0f, -1.0f};
709
710     V0 = XMVectorPermute(M.r[2], M.r[2], SwizzleYXXX);
711     V1 = XMVectorPermute(M.r[3], M.r[3], SwizzleZZYY);
712     V2 = XMVectorPermute(M.r[2], M.r[2], SwizzleYXXX);
713     V3 = XMVectorPermute(M.r[3], M.r[3], SwizzleWWWZ);
714     V4 = XMVectorPermute(M.r[2], M.r[2], SwizzleZZYY);
715     V5 = XMVectorPermute(M.r[3], M.r[3], SwizzleWWWZ);
716
717     P0 = _mm_mul_ps(V0, V1);
718     P1 = _mm_mul_ps(V2, V3);
719     P2 = _mm_mul_ps(V4, V5);
720
721     V0 = XMVectorPermute(M.r[2], M.r[2], SwizzleZZYY);
722     V1 = XMVectorPermute(M.r[3], M.r[3], SwizzleYXXX);
723     V2 = XMVectorPermute(M.r[2], M.r[2], SwizzleWWWZ);
724     V3 = XMVectorPermute(M.r[3], M.r[3], SwizzleYXXX);
725     V4 = XMVectorPermute(M.r[2], M.r[2], SwizzleWWWZ);
726     V5 = XMVectorPermute(M.r[3], M.r[3], SwizzleZZYY);
727
728     P0 = XMVectorNegativeMultiplySubtract(V0, V1, P0);
729     P1 = XMVectorNegativeMultiplySubtract(V2, V3, P1);
730     P2 = XMVectorNegativeMultiplySubtract(V4, V5, P2);
731
732     V0 = XMVectorPermute(M.r[1], M.r[1], SwizzleWWWZ);
733     V1 = XMVectorPermute(M.r[1], M.r[1], SwizzleZZYY);
734     V2 = XMVectorPermute(M.r[1], M.r[1], SwizzleYXXX);
735
736     S = _mm_mul_ps(M.r[0], Sign);
737     R = _mm_mul_ps(V0, P0);
738     R = XMVectorNegativeMultiplySubtract(V1, P1, R);
739     R = XMVectorMultiplyAdd(V2, P2, R);
740
741     Result = XMVector4Dot(S, R);
742
743     return Result;
744
745 #else // _XM_VMX128_INTRINSICS_
746 #endif // _XM_VMX128_INTRINSICS_
747 }
748
749 #undef XMRANKDECOMPOSE
750 #undef XM_DECOMP_EPSILON
751
752 #define XMRANKDECOMPOSE(a, b, c, x, y, z)      \
753     if((x) < (y))                   \
754     {                               \
755         if((y) < (z))               \
756         {                           \
757             (a) = 2;                \
758             (b) = 1;                \
759             (c) = 0;                \
760         }                           \
761         else                        \
762         {                           \
763             (a) = 1;                \
764                                     \
765             if((x) < (z))           \
766             {                       \
767                 (b) = 2;            \
768                 (c) = 0;            \
769             }                       \
770             else                    \
771             {                       \
772                 (b) = 0;            \
773                 (c) = 2;            \
774             }                       \
775         }                           \
776     }                               \
777     else                            \
778     {                               \
779         if((x) < (z))               \
780         {                           \
781             (a) = 2;                \
782             (b) = 0;                \
783             (c) = 1;                \
784         }                           \
785         else                        \
786         {                           \
787             (a) = 0;                \
788                                     \
789             if((y) < (z))           \
790             {                       \
791                 (b) = 2;            \
792                 (c) = 1;            \
793             }                       \
794             else                    \
795             {                       \
796                 (b) = 1;            \
797                 (c) = 2;            \
798             }                       \
799         }                           \
800     }
801                                     
802 #define XM_DECOMP_EPSILON 0.0001f
803
804 XMINLINE BOOL XMMatrixDecompose
805 (
806     XMVECTOR *outScale,
807     XMVECTOR *outRotQuat,
808     XMVECTOR *outTrans,
809     CXMMATRIX M
810 )
811 {
812     FLOAT fDet;
813     FLOAT *pfScales;
814     XMVECTOR *ppvBasis[3];
815     XMMATRIX matTemp;
816     UINT a, b, c;
817     static const XMVECTOR *pvCanonicalBasis[3] = {
818         &g_XMIdentityR0.v,
819         &g_XMIdentityR1.v,
820         &g_XMIdentityR2.v
821     };
822
823     XMASSERT( outScale != NULL );
824     XMASSERT( outRotQuat != NULL );
825     XMASSERT( outTrans != NULL );
826
827     // Get the translation
828     outTrans[0] = M.r[3];
829
830     ppvBasis[0] = &matTemp.r[0];
831     ppvBasis[1] = &matTemp.r[1];
832     ppvBasis[2] = &matTemp.r[2];
833
834     matTemp.r[0] = M.r[0];
835     matTemp.r[1] = M.r[1];
836     matTemp.r[2] = M.r[2];
837     matTemp.r[3] = g_XMIdentityR3.v;
838
839     pfScales = (FLOAT *)outScale;
840
841     XMVectorGetXPtr(&pfScales[0],XMVector3Length(ppvBasis[0][0])); 
842     XMVectorGetXPtr(&pfScales[1],XMVector3Length(ppvBasis[1][0])); 
843     XMVectorGetXPtr(&pfScales[2],XMVector3Length(ppvBasis[2][0])); 
844     pfScales[3] = 0.f;
845
846     XMRANKDECOMPOSE(a, b, c, pfScales[0], pfScales[1], pfScales[2])
847
848     if(pfScales[a] < XM_DECOMP_EPSILON)
849     {
850         ppvBasis[a][0] = pvCanonicalBasis[a][0];
851     }
852     ppvBasis[a][0] = XMVector3Normalize(ppvBasis[a][0]);
853
854     if(pfScales[b] < XM_DECOMP_EPSILON)
855     {
856         UINT aa, bb, cc;
857         FLOAT fAbsX, fAbsY, fAbsZ;
858
859         fAbsX = fabsf(XMVectorGetX(ppvBasis[a][0]));
860         fAbsY = fabsf(XMVectorGetY(ppvBasis[a][0]));
861         fAbsZ = fabsf(XMVectorGetZ(ppvBasis[a][0]));
862
863         XMRANKDECOMPOSE(aa, bb, cc, fAbsX, fAbsY, fAbsZ)
864
865         ppvBasis[b][0] = XMVector3Cross(ppvBasis[a][0],pvCanonicalBasis[cc][0]);
866     }
867
868     ppvBasis[b][0] = XMVector3Normalize(ppvBasis[b][0]);
869
870     if(pfScales[c] < XM_DECOMP_EPSILON)
871     {
872         ppvBasis[c][0] = XMVector3Cross(ppvBasis[a][0],ppvBasis[b][0]);
873     }
874         
875     ppvBasis[c][0] = XMVector3Normalize(ppvBasis[c][0]);
876
877     fDet = XMVectorGetX(XMMatrixDeterminant(matTemp));
878
879     // use Kramer's rule to check for handedness of coordinate system
880     if(fDet < 0.0f)
881     {
882         // switch coordinate system by negating the scale and inverting the basis vector on the x-axis
883         pfScales[a] = -pfScales[a];
884         ppvBasis[a][0] = XMVectorNegate(ppvBasis[a][0]);
885
886         fDet = -fDet;
887     }
888
889     fDet -= 1.0f;
890     fDet *= fDet;
891
892     if(XM_DECOMP_EPSILON < fDet)
893     {
894         // Non-SRT matrix encountered
895         return FALSE;
896     }
897
898     // generate the quaternion from the matrix
899     outRotQuat[0] = XMQuaternionRotationMatrix(matTemp);
900     return TRUE;
901 }
902
903 #undef XMRANKDECOMPOSE
904 #undef XM_DECOMP_EPSILON
905
906 //------------------------------------------------------------------------------
907 // Transformation operations
908 //------------------------------------------------------------------------------
909
910 //------------------------------------------------------------------------------
911
912 XMFINLINE XMMATRIX XMMatrixIdentity()
913 {
914 #if defined(_XM_NO_INTRINSICS_) 
915
916     XMMATRIX M;
917     M.r[0] = g_XMIdentityR0.v;
918     M.r[1] = g_XMIdentityR1.v;
919     M.r[2] = g_XMIdentityR2.v;
920     M.r[3] = g_XMIdentityR3.v;
921     return M;
922
923 #elif defined(_XM_SSE_INTRINSICS_)
924     XMMATRIX M;
925     M.r[0] = g_XMIdentityR0;
926     M.r[1] = g_XMIdentityR1;
927     M.r[2] = g_XMIdentityR2;
928     M.r[3] = g_XMIdentityR3;
929     return M;
930 #else // _XM_VMX128_INTRINSICS_
931 #endif // _XM_VMX128_INTRINSICS_
932 }
933
934 //------------------------------------------------------------------------------
935
936 XMFINLINE XMMATRIX XMMatrixSet
937 (
938     FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03,
939     FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13,
940     FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23,
941     FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33
942 )
943 {
944     XMMATRIX M;
945
946     M.r[0] = XMVectorSet(m00, m01, m02, m03);
947     M.r[1] = XMVectorSet(m10, m11, m12, m13);
948     M.r[2] = XMVectorSet(m20, m21, m22, m23);
949     M.r[3] = XMVectorSet(m30, m31, m32, m33);
950
951     return M;
952 }
953
954 //------------------------------------------------------------------------------
955
956 XMFINLINE XMMATRIX XMMatrixTranslation
957 (
958     FLOAT OffsetX, 
959     FLOAT OffsetY, 
960     FLOAT OffsetZ
961 )
962 {
963 #if defined(_XM_NO_INTRINSICS_)
964
965     XMMATRIX M;
966
967     M.m[0][0] = 1.0f;
968     M.m[0][1] = 0.0f;
969     M.m[0][2] = 0.0f;
970     M.m[0][3] = 0.0f;
971
972     M.m[1][0] = 0.0f;
973     M.m[1][1] = 1.0f;
974     M.m[1][2] = 0.0f;
975     M.m[1][3] = 0.0f;
976
977     M.m[2][0] = 0.0f;
978     M.m[2][1] = 0.0f;
979     M.m[2][2] = 1.0f;
980     M.m[2][3] = 0.0f;
981
982     M.m[3][0] = OffsetX;
983     M.m[3][1] = OffsetY;
984     M.m[3][2] = OffsetZ;
985     M.m[3][3] = 1.0f;
986     return M;
987
988 #elif defined(_XM_SSE_INTRINSICS_)
989     XMMATRIX M;
990     M.r[0] = g_XMIdentityR0;
991     M.r[1] = g_XMIdentityR1;
992     M.r[2] = g_XMIdentityR2;
993     M.r[3] = _mm_set_ps(1.0f,OffsetZ,OffsetY,OffsetX);
994     return M;
995 #else // _XM_VMX128_INTRINSICS_
996 #endif // _XM_VMX128_INTRINSICS_
997 }
998
999
1000 //------------------------------------------------------------------------------
1001
1002 XMFINLINE XMMATRIX XMMatrixTranslationFromVector
1003 (
1004     FXMVECTOR Offset
1005 )
1006 {
1007 #if defined(_XM_NO_INTRINSICS_)
1008
1009     XMMATRIX M;
1010     M.m[0][0] = 1.0f;
1011     M.m[0][1] = 0.0f;
1012     M.m[0][2] = 0.0f;
1013     M.m[0][3] = 0.0f;
1014
1015     M.m[1][0] = 0.0f;
1016     M.m[1][1] = 1.0f;
1017     M.m[1][2] = 0.0f;
1018     M.m[1][3] = 0.0f;
1019
1020     M.m[2][0] = 0.0f;
1021     M.m[2][1] = 0.0f;
1022     M.m[2][2] = 1.0f;
1023     M.m[2][3] = 0.0f;
1024
1025     M.m[3][0] = Offset.vector4_f32[0];
1026     M.m[3][1] = Offset.vector4_f32[1];
1027     M.m[3][2] = Offset.vector4_f32[2];
1028     M.m[3][3] = 1.0f;
1029     return M;
1030
1031 #elif defined(_XM_SSE_INTRINSICS_)
1032     XMVECTOR vTemp = _mm_and_ps(Offset,g_XMMask3);
1033     vTemp = _mm_or_ps(vTemp,g_XMIdentityR3);
1034     XMMATRIX M;
1035     M.r[0] = g_XMIdentityR0;
1036     M.r[1] = g_XMIdentityR1;
1037     M.r[2] = g_XMIdentityR2;
1038     M.r[3] = vTemp;
1039     return M;
1040 #else // _XM_VMX128_INTRINSICS_
1041 #endif // _XM_VMX128_INTRINSICS_
1042 }
1043
1044 //------------------------------------------------------------------------------
1045
1046 XMFINLINE XMMATRIX XMMatrixScaling
1047 (
1048     FLOAT ScaleX, 
1049     FLOAT ScaleY, 
1050     FLOAT ScaleZ
1051 )
1052 {
1053 #if defined(_XM_NO_INTRINSICS_)
1054
1055     XMMATRIX M;
1056
1057     M.r[0] = XMVectorSet(ScaleX, 0.0f, 0.0f, 0.0f);
1058     M.r[1] = XMVectorSet(0.0f, ScaleY, 0.0f, 0.0f);
1059     M.r[2] = XMVectorSet(0.0f, 0.0f, ScaleZ, 0.0f);
1060
1061     M.r[3] = g_XMIdentityR3.v;
1062
1063     return M;
1064
1065 #elif defined(_XM_SSE_INTRINSICS_)
1066     XMMATRIX M;
1067     M.r[0] = _mm_set_ps( 0, 0, 0, ScaleX );
1068     M.r[1] = _mm_set_ps( 0, 0, ScaleY, 0 );
1069     M.r[2] = _mm_set_ps( 0, ScaleZ, 0, 0 );
1070     M.r[3] = g_XMIdentityR3;
1071     return M;
1072 #elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
1073 #endif // _XM_VMX128_INTRINSICS_
1074 }
1075
1076 //------------------------------------------------------------------------------
1077
1078 XMFINLINE XMMATRIX XMMatrixScalingFromVector
1079 (
1080     FXMVECTOR Scale
1081 )
1082 {
1083 #if defined(_XM_NO_INTRINSICS_)
1084     XMMATRIX M;
1085     M.m[0][0] = Scale.vector4_f32[0];
1086     M.m[0][1] = 0.0f;
1087     M.m[0][2] = 0.0f;
1088     M.m[0][3] = 0.0f;
1089
1090     M.m[1][0] = 0.0f;
1091     M.m[1][1] = Scale.vector4_f32[1];
1092     M.m[1][2] = 0.0f;
1093     M.m[1][3] = 0.0f;
1094
1095     M.m[2][0] = 0.0f;
1096     M.m[2][1] = 0.0f;
1097     M.m[2][2] = Scale.vector4_f32[2];
1098     M.m[2][3] = 0.0f;
1099
1100     M.m[3][0] = 0.0f;
1101     M.m[3][1] = 0.0f;
1102     M.m[3][2] = 0.0f;
1103     M.m[3][3] = 1.0f;
1104     return M;
1105
1106 #elif defined(_XM_SSE_INTRINSICS_)
1107     XMMATRIX M;
1108     M.r[0] = _mm_and_ps(Scale,g_XMMaskX);
1109     M.r[1] = _mm_and_ps(Scale,g_XMMaskY);
1110     M.r[2] = _mm_and_ps(Scale,g_XMMaskZ);
1111     M.r[3] = g_XMIdentityR3;
1112     return M;
1113 #else // _XM_VMX128_INTRINSICS_
1114 #endif // _XM_VMX128_INTRINSICS_
1115 }
1116
1117 //------------------------------------------------------------------------------
1118
1119 XMINLINE XMMATRIX XMMatrixRotationX
1120 (
1121     FLOAT Angle
1122 )
1123 {
1124 #if defined(_XM_NO_INTRINSICS_)
1125     XMMATRIX M;
1126  
1127     FLOAT fSinAngle = sinf(Angle);
1128     FLOAT fCosAngle = cosf(Angle);
1129
1130     M.m[0][0] = 1.0f;
1131     M.m[0][1] = 0.0f;
1132     M.m[0][2] = 0.0f;
1133     M.m[0][3] = 0.0f;
1134
1135     M.m[1][0] = 0.0f;
1136     M.m[1][1] = fCosAngle;
1137     M.m[1][2] = fSinAngle;
1138     M.m[1][3] = 0.0f;
1139
1140     M.m[2][0] = 0.0f;
1141     M.m[2][1] = -fSinAngle;
1142     M.m[2][2] = fCosAngle;
1143     M.m[2][3] = 0.0f;
1144
1145     M.m[3][0] = 0.0f;
1146     M.m[3][1] = 0.0f;
1147     M.m[3][2] = 0.0f;
1148     M.m[3][3] = 1.0f;
1149     return M;
1150
1151 #elif defined(_XM_SSE_INTRINSICS_)
1152     FLOAT SinAngle = sinf(Angle);
1153     FLOAT CosAngle = cosf(Angle);
1154
1155     XMVECTOR vSin = _mm_set_ss(SinAngle);
1156     XMVECTOR vCos = _mm_set_ss(CosAngle);
1157     // x = 0,y = cos,z = sin, w = 0
1158     vCos = _mm_shuffle_ps(vCos,vSin,_MM_SHUFFLE(3,0,0,3));
1159     XMMATRIX M;
1160     M.r[0] = g_XMIdentityR0;
1161     M.r[1] = vCos;
1162     // x = 0,y = sin,z = cos, w = 0
1163     vCos = _mm_shuffle_ps(vCos,vCos,_MM_SHUFFLE(3,1,2,0));
1164     // x = 0,y = -sin,z = cos, w = 0
1165     vCos = _mm_mul_ps(vCos,g_XMNegateY);
1166     M.r[2] = vCos;
1167     M.r[3] = g_XMIdentityR3;
1168     return M;
1169 #else // _XM_VMX128_INTRINSICS_
1170 #endif // _XM_VMX128_INTRINSICS_
1171 }
1172
1173 //------------------------------------------------------------------------------
1174
1175 XMINLINE XMMATRIX XMMatrixRotationY
1176 (
1177     FLOAT Angle
1178 )
1179 {
1180 #if defined(_XM_NO_INTRINSICS_)
1181     XMMATRIX M;
1182  
1183     FLOAT fSinAngle = sinf(Angle);
1184     FLOAT fCosAngle = cosf(Angle);
1185
1186     M.m[0][0] = fCosAngle;
1187     M.m[0][1] = 0.0f;
1188     M.m[0][2] = -fSinAngle;
1189     M.m[0][3] = 0.0f;
1190
1191     M.m[1][0] = 0.0f;
1192     M.m[1][1] = 1.0f;
1193     M.m[1][2] = 0.0f;
1194     M.m[1][3] = 0.0f;
1195
1196     M.m[2][0] = fSinAngle;
1197     M.m[2][1] = 0.0f;
1198     M.m[2][2] = fCosAngle;
1199     M.m[2][3] = 0.0f;
1200
1201     M.m[3][0] = 0.0f;
1202     M.m[3][1] = 0.0f;
1203     M.m[3][2] = 0.0f;
1204     M.m[3][3] = 1.0f;
1205     return M;
1206 #elif defined(_XM_SSE_INTRINSICS_)
1207     FLOAT SinAngle = sinf(Angle);
1208     FLOAT CosAngle = cosf(Angle);
1209
1210     XMVECTOR vSin = _mm_set_ss(SinAngle);
1211     XMVECTOR vCos = _mm_set_ss(CosAngle);
1212     // x = sin,y = 0,z = cos, w = 0
1213     vSin = _mm_shuffle_ps(vSin,vCos,_MM_SHUFFLE(3,0,3,0));
1214     XMMATRIX M;
1215     M.r[2] = vSin;
1216     M.r[1] = g_XMIdentityR1;
1217     // x = cos,y = 0,z = sin, w = 0
1218     vSin = _mm_shuffle_ps(vSin,vSin,_MM_SHUFFLE(3,0,1,2));
1219     // x = cos,y = 0,z = -sin, w = 0
1220     vSin = _mm_mul_ps(vSin,g_XMNegateZ);
1221     M.r[0] = vSin;
1222     M.r[3] = g_XMIdentityR3;
1223     return M;
1224 #else // _XM_VMX128_INTRINSICS_
1225 #endif // _XM_VMX128_INTRINSICS_
1226 }
1227
1228 //------------------------------------------------------------------------------
1229
1230 XMINLINE XMMATRIX XMMatrixRotationZ
1231 (
1232     FLOAT Angle
1233 )
1234 {
1235 #if defined(_XM_NO_INTRINSICS_)
1236     XMMATRIX M;
1237  
1238     FLOAT fSinAngle = sinf(Angle);
1239     FLOAT fCosAngle = cosf(Angle);
1240
1241     M.m[0][0] = fCosAngle;
1242     M.m[0][1] = fSinAngle;
1243     M.m[0][2] = 0.0f;
1244     M.m[0][3] = 0.0f;
1245
1246     M.m[1][0] = -fSinAngle;
1247     M.m[1][1] = fCosAngle;
1248     M.m[1][2] = 0.0f;
1249     M.m[1][3] = 0.0f;
1250
1251     M.m[2][0] = 0.0f;
1252     M.m[2][1] = 0.0f;
1253     M.m[2][2] = 1.0f;
1254     M.m[2][3] = 0.0f;
1255
1256     M.m[3][0] = 0.0f;
1257     M.m[3][1] = 0.0f;
1258     M.m[3][2] = 0.0f;
1259     M.m[3][3] = 1.0f;
1260     return M;
1261
1262 #elif defined(_XM_SSE_INTRINSICS_)
1263     FLOAT SinAngle = sinf(Angle);
1264     FLOAT CosAngle = cosf(Angle);
1265
1266     XMVECTOR vSin = _mm_set_ss(SinAngle);
1267     XMVECTOR vCos = _mm_set_ss(CosAngle);
1268     // x = cos,y = sin,z = 0, w = 0
1269     vCos = _mm_unpacklo_ps(vCos,vSin);
1270     XMMATRIX M;
1271     M.r[0] = vCos;
1272     // x = sin,y = cos,z = 0, w = 0
1273     vCos = _mm_shuffle_ps(vCos,vCos,_MM_SHUFFLE(3,2,0,1));
1274     // x = cos,y = -sin,z = 0, w = 0
1275     vCos = _mm_mul_ps(vCos,g_XMNegateX);
1276     M.r[1] = vCos;
1277     M.r[2] = g_XMIdentityR2;
1278     M.r[3] = g_XMIdentityR3;
1279     return M;
1280 #else // _XM_VMX128_INTRINSICS_
1281 #endif // _XM_VMX128_INTRINSICS_
1282 }
1283
1284 //------------------------------------------------------------------------------
1285
1286 XMINLINE XMMATRIX XMMatrixRotationRollPitchYaw
1287 (
1288     FLOAT Pitch, 
1289     FLOAT Yaw, 
1290     FLOAT Roll
1291 )
1292 {
1293     XMVECTOR Angles;
1294     XMMATRIX M;
1295
1296     Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f);
1297     M = XMMatrixRotationRollPitchYawFromVector(Angles);
1298
1299     return M;
1300 }
1301
1302 //------------------------------------------------------------------------------
1303
1304 XMINLINE XMMATRIX XMMatrixRotationRollPitchYawFromVector
1305 (
1306     FXMVECTOR Angles // <Pitch, Yaw, Roll, undefined>
1307 )
1308 {
1309     XMVECTOR Q;
1310     XMMATRIX M;
1311     
1312     Q = XMQuaternionRotationRollPitchYawFromVector(Angles);
1313     M = XMMatrixRotationQuaternion(Q);
1314
1315     return M;
1316 }
1317
1318 //------------------------------------------------------------------------------
1319
1320 XMINLINE XMMATRIX XMMatrixRotationNormal
1321 (
1322     FXMVECTOR NormalAxis, 
1323     FLOAT    Angle
1324 )
1325 {
1326 #if defined(_XM_NO_INTRINSICS_)
1327     XMVECTOR               A;
1328     XMVECTOR               N0, N1;
1329     XMVECTOR               V0, V1, V2;
1330     XMVECTOR               R0, R1, R2;
1331     XMVECTOR               C0, C1, C2;
1332     XMMATRIX               M;
1333     static CONST XMVECTORU32 SwizzleYZXW = {XM_PERMUTE_0Y, XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0W};
1334     static CONST XMVECTORU32 SwizzleZXYW = {XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_0W};
1335     static CONST XMVECTORU32 Permute0Z1Y1Z0X = {XM_PERMUTE_0Z, XM_PERMUTE_1Y, XM_PERMUTE_1Z, XM_PERMUTE_0X};
1336     static CONST XMVECTORU32 Permute0Y1X0Y1X = {XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_0Y, XM_PERMUTE_1X};
1337     static CONST XMVECTORU32 Permute0X1X1Y0W = {XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0W};
1338     static CONST XMVECTORU32 Permute1Z0Y1W0W = {XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_1W, XM_PERMUTE_0W};
1339     static CONST XMVECTORU32 Permute1X1Y0Z0W = {XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z, XM_PERMUTE_0W};
1340
1341     FLOAT fSinAngle = sinf(Angle);
1342     FLOAT fCosAngle = cosf(Angle);
1343
1344     A = XMVectorSet(fSinAngle, fCosAngle, 1.0f - fCosAngle, 0.0f);
1345
1346     C2 = XMVectorSplatZ(A);
1347     C1 = XMVectorSplatY(A);
1348     C0 = XMVectorSplatX(A);
1349
1350     N0 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleYZXW.v);
1351     N1 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleZXYW.v);
1352
1353     V0 = XMVectorMultiply(C2, N0);
1354     V0 = XMVectorMultiply(V0, N1);
1355
1356     R0 = XMVectorMultiply(C2, NormalAxis);
1357     R0 = XMVectorMultiplyAdd(R0, NormalAxis, C1);
1358
1359     R1 = XMVectorMultiplyAdd(C0, NormalAxis, V0);
1360     R2 = XMVectorNegativeMultiplySubtract(C0, NormalAxis, V0);
1361
1362     V0 = XMVectorSelect(A, R0, g_XMSelect1110.v);
1363     V1 = XMVectorPermute(R1, R2, Permute0Z1Y1Z0X.v);
1364     V2 = XMVectorPermute(R1, R2, Permute0Y1X0Y1X.v);
1365
1366     M.r[0] = XMVectorPermute(V0, V1, Permute0X1X1Y0W.v);
1367     M.r[1] = XMVectorPermute(V0, V1, Permute1Z0Y1W0W.v);
1368     M.r[2] = XMVectorPermute(V0, V2, Permute1X1Y0Z0W.v);
1369     M.r[3] = g_XMIdentityR3.v;
1370
1371     return M;
1372
1373 #elif defined(_XM_SSE_INTRINSICS_)
1374     XMVECTOR               N0, N1;
1375     XMVECTOR               V0, V1, V2;
1376     XMVECTOR               R0, R1, R2;
1377     XMVECTOR               C0, C1, C2;
1378     XMMATRIX               M;
1379
1380     FLOAT fSinAngle = sinf(Angle);
1381     FLOAT fCosAngle = cosf(Angle);
1382
1383     C2 = _mm_set_ps1(1.0f - fCosAngle);
1384     C1 = _mm_set_ps1(fCosAngle);
1385     C0 = _mm_set_ps1(fSinAngle);
1386
1387     N0 = _mm_shuffle_ps(NormalAxis,NormalAxis,_MM_SHUFFLE(3,0,2,1));
1388 //    N0 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleYZXW);
1389     N1 = _mm_shuffle_ps(NormalAxis,NormalAxis,_MM_SHUFFLE(3,1,0,2));
1390 //    N1 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleZXYW);
1391
1392     V0 = _mm_mul_ps(C2, N0);
1393     V0 = _mm_mul_ps(V0, N1);
1394
1395     R0 = _mm_mul_ps(C2, NormalAxis);
1396     R0 = _mm_mul_ps(R0, NormalAxis);
1397     R0 = _mm_add_ps(R0, C1);
1398
1399     R1 = _mm_mul_ps(C0, NormalAxis);
1400     R1 = _mm_add_ps(R1, V0);
1401     R2 = _mm_mul_ps(C0, NormalAxis);
1402     R2 = _mm_sub_ps(V0,R2);
1403
1404     V0 = _mm_and_ps(R0,g_XMMask3);
1405 //    V0 = XMVectorSelect(A, R0, g_XMSelect1110);
1406     V1 = _mm_shuffle_ps(R1,R2,_MM_SHUFFLE(2,1,2,0));
1407     V1 = _mm_shuffle_ps(V1,V1,_MM_SHUFFLE(0,3,2,1));
1408 //    V1 = XMVectorPermute(R1, R2, Permute0Z1Y1Z0X);
1409     V2 = _mm_shuffle_ps(R1,R2,_MM_SHUFFLE(0,0,1,1));
1410     V2 = _mm_shuffle_ps(V2,V2,_MM_SHUFFLE(2,0,2,0));
1411 //    V2 = XMVectorPermute(R1, R2, Permute0Y1X0Y1X);
1412
1413     R2 = _mm_shuffle_ps(V0,V1,_MM_SHUFFLE(1,0,3,0));
1414     R2 = _mm_shuffle_ps(R2,R2,_MM_SHUFFLE(1,3,2,0));
1415     M.r[0] = R2;
1416 //    M.r[0] = XMVectorPermute(V0, V1, Permute0X1X1Y0W);
1417     R2 = _mm_shuffle_ps(V0,V1,_MM_SHUFFLE(3,2,3,1));
1418     R2 = _mm_shuffle_ps(R2,R2,_MM_SHUFFLE(1,3,0,2));
1419     M.r[1] = R2;
1420 //    M.r[1] = XMVectorPermute(V0, V1, Permute1Z0Y1W0W);
1421     V2 = _mm_shuffle_ps(V2,V0,_MM_SHUFFLE(3,2,1,0));
1422 //    R2 = _mm_shuffle_ps(R2,R2,_MM_SHUFFLE(3,2,1,0));
1423     M.r[2] = V2;
1424 //    M.r[2] = XMVectorPermute(V0, V2, Permute1X1Y0Z0W);
1425     M.r[3] = g_XMIdentityR3;
1426     return M;
1427 #else // _XM_VMX128_INTRINSICS_
1428 #endif // _XM_VMX128_INTRINSICS_
1429 }
1430
1431 //------------------------------------------------------------------------------
1432
1433 XMINLINE XMMATRIX XMMatrixRotationAxis
1434 (
1435     FXMVECTOR Axis, 
1436     FLOAT    Angle
1437 )
1438 {
1439 #if defined(_XM_NO_INTRINSICS_)
1440
1441     XMVECTOR Normal;
1442     XMMATRIX M;
1443
1444     XMASSERT(!XMVector3Equal(Axis, XMVectorZero()));
1445     XMASSERT(!XMVector3IsInfinite(Axis));
1446
1447     Normal = XMVector3Normalize(Axis);
1448     M = XMMatrixRotationNormal(Normal, Angle);
1449
1450     return M;
1451
1452 #elif defined(_XM_SSE_INTRINSICS_)
1453     XMASSERT(!XMVector3Equal(Axis, XMVectorZero()));
1454     XMASSERT(!XMVector3IsInfinite(Axis));
1455     XMVECTOR Normal = XMVector3Normalize(Axis);
1456     XMMATRIX M = XMMatrixRotationNormal(Normal, Angle);
1457     return M;
1458 #else // _XM_VMX128_INTRINSICS_
1459 #endif // _XM_VMX128_INTRINSICS_
1460 }
1461
1462 //------------------------------------------------------------------------------
1463
1464 XMFINLINE XMMATRIX XMMatrixRotationQuaternion
1465 (
1466     FXMVECTOR Quaternion
1467 )
1468 {
1469 #if defined(_XM_NO_INTRINSICS_)
1470
1471     XMMATRIX               M;
1472     XMVECTOR               Q0, Q1;
1473     XMVECTOR               V0, V1, V2;
1474     XMVECTOR               R0, R1, R2;
1475     static CONST XMVECTOR  Constant1110 = {1.0f, 1.0f, 1.0f, 0.0f};
1476     static CONST XMVECTORU32 SwizzleXXYW = {XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_0W};
1477     static CONST XMVECTORU32 SwizzleZYZW = {XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_0Z, XM_PERMUTE_0W};
1478     static CONST XMVECTORU32 SwizzleYZXW = {XM_PERMUTE_0Y, XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0W};
1479     static CONST XMVECTORU32 Permute0Y0X0X1W = {XM_PERMUTE_0Y, XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_1W};
1480     static CONST XMVECTORU32 Permute0Z0Z0Y1W = {XM_PERMUTE_0Z, XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1W};
1481     static CONST XMVECTORU32 Permute0Y1X1Y0Z = {XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z};
1482     static CONST XMVECTORU32 Permute0X1Z0X1Z = {XM_PERMUTE_0X, XM_PERMUTE_1Z, XM_PERMUTE_0X, XM_PERMUTE_1Z};
1483     static CONST XMVECTORU32 Permute0X1X1Y0W = {XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0W};
1484     static CONST XMVECTORU32 Permute1Z0Y1W0W = {XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_1W, XM_PERMUTE_0W};
1485     static CONST XMVECTORU32 Permute1X1Y0Z0W = {XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z, XM_PERMUTE_0W};
1486
1487     Q0 = XMVectorAdd(Quaternion, Quaternion);
1488     Q1 = XMVectorMultiply(Quaternion, Q0);
1489
1490     V0 = XMVectorPermute(Q1, Constant1110, Permute0Y0X0X1W.v);
1491     V1 = XMVectorPermute(Q1, Constant1110, Permute0Z0Z0Y1W.v);
1492     R0 = XMVectorSubtract(Constant1110, V0);
1493     R0 = XMVectorSubtract(R0, V1);
1494
1495     V0 = XMVectorPermute(Quaternion, Quaternion, SwizzleXXYW.v);
1496     V1 = XMVectorPermute(Q0, Q0, SwizzleZYZW.v);
1497     V0 = XMVectorMultiply(V0, V1);
1498
1499     V1 = XMVectorSplatW(Quaternion);
1500     V2 = XMVectorPermute(Q0, Q0, SwizzleYZXW.v);
1501     V1 = XMVectorMultiply(V1, V2);
1502
1503     R1 = XMVectorAdd(V0, V1);
1504     R2 = XMVectorSubtract(V0, V1);
1505
1506     V0 = XMVectorPermute(R1, R2, Permute0Y1X1Y0Z.v);
1507     V1 = XMVectorPermute(R1, R2, Permute0X1Z0X1Z.v);
1508
1509     M.r[0] = XMVectorPermute(R0, V0, Permute0X1X1Y0W.v);
1510     M.r[1] = XMVectorPermute(R0, V0, Permute1Z0Y1W0W.v);
1511     M.r[2] = XMVectorPermute(R0, V1, Permute1X1Y0Z0W.v);
1512     M.r[3] = g_XMIdentityR3.v;
1513
1514     return M;
1515
1516 #elif defined(_XM_SSE_INTRINSICS_)
1517     XMMATRIX M;
1518     XMVECTOR               Q0, Q1;
1519     XMVECTOR               V0, V1, V2;
1520     XMVECTOR               R0, R1, R2;
1521     static CONST XMVECTORF32  Constant1110 = {1.0f, 1.0f, 1.0f, 0.0f};
1522
1523     Q0 = _mm_add_ps(Quaternion,Quaternion);
1524     Q1 = _mm_mul_ps(Quaternion,Q0);
1525
1526     V0 = _mm_shuffle_ps(Q1,Q1,_MM_SHUFFLE(3,0,0,1));
1527     V0 = _mm_and_ps(V0,g_XMMask3);
1528 //    V0 = XMVectorPermute(Q1, Constant1110,Permute0Y0X0X1W);
1529     V1 = _mm_shuffle_ps(Q1,Q1,_MM_SHUFFLE(3,1,2,2));
1530     V1 = _mm_and_ps(V1,g_XMMask3);
1531 //    V1 = XMVectorPermute(Q1, Constant1110,Permute0Z0Z0Y1W);
1532     R0 = _mm_sub_ps(Constant1110,V0);
1533     R0 = _mm_sub_ps(R0, V1);
1534
1535     V0 = _mm_shuffle_ps(Quaternion,Quaternion,_MM_SHUFFLE(3,1,0,0));
1536 //    V0 = XMVectorPermute(Quaternion, Quaternion,SwizzleXXYW);
1537     V1 = _mm_shuffle_ps(Q0,Q0,_MM_SHUFFLE(3,2,1,2));
1538 //    V1 = XMVectorPermute(Q0, Q0,SwizzleZYZW);
1539     V0 = _mm_mul_ps(V0, V1);
1540
1541     V1 = _mm_shuffle_ps(Quaternion,Quaternion,_MM_SHUFFLE(3,3,3,3));
1542 //    V1 = XMVectorSplatW(Quaternion);
1543     V2 = _mm_shuffle_ps(Q0,Q0,_MM_SHUFFLE(3,0,2,1));
1544 //    V2 = XMVectorPermute(Q0, Q0,SwizzleYZXW);
1545     V1 = _mm_mul_ps(V1, V2);
1546
1547     R1 = _mm_add_ps(V0, V1);
1548     R2 = _mm_sub_ps(V0, V1);
1549
1550     V0 = _mm_shuffle_ps(R1,R2,_MM_SHUFFLE(1,0,2,1));
1551     V0 = _mm_shuffle_ps(V0,V0,_MM_SHUFFLE(1,3,2,0));
1552 //    V0 = XMVectorPermute(R1, R2,Permute0Y1X1Y0Z);
1553     V1 = _mm_shuffle_ps(R1,R2,_MM_SHUFFLE(2,2,0,0));
1554     V1 = _mm_shuffle_ps(V1,V1,_MM_SHUFFLE(2,0,2,0));
1555 //    V1 = XMVectorPermute(R1, R2,Permute0X1Z0X1Z);
1556
1557     Q1 = _mm_shuffle_ps(R0,V0,_MM_SHUFFLE(1,0,3,0));
1558     Q1 = _mm_shuffle_ps(Q1,Q1,_MM_SHUFFLE(1,3,2,0));
1559     M.r[0] = Q1;
1560 //    M.r[0] = XMVectorPermute(R0, V0,Permute0X1X1Y0W);
1561     Q1 = _mm_shuffle_ps(R0,V0,_MM_SHUFFLE(3,2,3,1));
1562     Q1 = _mm_shuffle_ps(Q1,Q1,_MM_SHUFFLE(1,3,0,2));
1563     M.r[1] = Q1;
1564 //    M.r[1] = XMVectorPermute(R0, V0,Permute1Z0Y1W0W);
1565     Q1 = _mm_shuffle_ps(V1,R0,_MM_SHUFFLE(3,2,1,0));
1566     M.r[2] = Q1;
1567 //    M.r[2] = XMVectorPermute(R0, V1,Permute1X1Y0Z0W);
1568     M.r[3] = g_XMIdentityR3;
1569     return M;
1570 #else // _XM_VMX128_INTRINSICS_
1571 #endif // _XM_VMX128_INTRINSICS_
1572 }
1573
1574 //------------------------------------------------------------------------------
1575
1576 XMINLINE XMMATRIX XMMatrixTransformation2D
1577 (
1578     FXMVECTOR ScalingOrigin, 
1579     FLOAT    ScalingOrientation, 
1580     FXMVECTOR Scaling, 
1581     FXMVECTOR RotationOrigin, 
1582     FLOAT    Rotation, 
1583     CXMVECTOR Translation
1584 )
1585 {
1586 #if defined(_XM_NO_INTRINSICS_)
1587
1588     XMMATRIX M;
1589     XMVECTOR VScaling;
1590     XMVECTOR NegScalingOrigin;
1591     XMVECTOR VScalingOrigin;
1592     XMMATRIX MScalingOriginI;
1593     XMMATRIX MScalingOrientation;
1594     XMMATRIX MScalingOrientationT;
1595     XMMATRIX MScaling;
1596     XMVECTOR VRotationOrigin;
1597     XMMATRIX MRotation;
1598     XMVECTOR VTranslation;
1599
1600     // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation *
1601     //         MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1602
1603     VScalingOrigin       = XMVectorSelect(g_XMSelect1100.v, ScalingOrigin, g_XMSelect1100.v);
1604     NegScalingOrigin     = XMVectorNegate(VScalingOrigin);
1605
1606     MScalingOriginI      = XMMatrixTranslationFromVector(NegScalingOrigin);
1607     MScalingOrientation  = XMMatrixRotationZ(ScalingOrientation);
1608     MScalingOrientationT = XMMatrixTranspose(MScalingOrientation);
1609     VScaling             = XMVectorSelect(g_XMOne.v, Scaling, g_XMSelect1100.v);
1610     MScaling             = XMMatrixScalingFromVector(VScaling);
1611     VRotationOrigin      = XMVectorSelect(g_XMSelect1100.v, RotationOrigin, g_XMSelect1100.v);
1612     MRotation            = XMMatrixRotationZ(Rotation);
1613     VTranslation         = XMVectorSelect(g_XMSelect1100.v, Translation,g_XMSelect1100.v);
1614
1615     M      = XMMatrixMultiply(MScalingOriginI, MScalingOrientationT);
1616     M      = XMMatrixMultiply(M, MScaling);
1617     M      = XMMatrixMultiply(M, MScalingOrientation);
1618     M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin);
1619     M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
1620     M      = XMMatrixMultiply(M, MRotation);
1621     M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
1622     M.r[3] = XMVectorAdd(M.r[3], VTranslation);
1623
1624     return M;
1625
1626 #elif defined(_XM_SSE_INTRINSICS_)
1627     XMMATRIX M;
1628     XMVECTOR VScaling;
1629     XMVECTOR NegScalingOrigin;
1630     XMVECTOR VScalingOrigin;
1631     XMMATRIX MScalingOriginI;
1632     XMMATRIX MScalingOrientation;
1633     XMMATRIX MScalingOrientationT;
1634     XMMATRIX MScaling;
1635     XMVECTOR VRotationOrigin;
1636     XMMATRIX MRotation;
1637     XMVECTOR VTranslation;
1638
1639     // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation *
1640     //         MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1641     static const XMVECTORU32 Mask2 = {0xFFFFFFFF,0xFFFFFFFF,0,0};
1642     static const XMVECTORF32 ZWOne = {0,0,1.0f,1.0f};
1643
1644     VScalingOrigin       = _mm_and_ps(ScalingOrigin, Mask2);
1645     NegScalingOrigin     = XMVectorNegate(VScalingOrigin);
1646
1647     MScalingOriginI      = XMMatrixTranslationFromVector(NegScalingOrigin);
1648     MScalingOrientation  = XMMatrixRotationZ(ScalingOrientation);
1649     MScalingOrientationT = XMMatrixTranspose(MScalingOrientation);
1650     VScaling             = _mm_and_ps(Scaling, Mask2);
1651     VScaling = _mm_or_ps(VScaling,ZWOne);
1652     MScaling             = XMMatrixScalingFromVector(VScaling);
1653     VRotationOrigin      = _mm_and_ps(RotationOrigin, Mask2);
1654     MRotation            = XMMatrixRotationZ(Rotation);
1655     VTranslation         = _mm_and_ps(Translation, Mask2);
1656
1657     M      = XMMatrixMultiply(MScalingOriginI, MScalingOrientationT);
1658     M      = XMMatrixMultiply(M, MScaling);
1659     M      = XMMatrixMultiply(M, MScalingOrientation);
1660     M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin);
1661     M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
1662     M      = XMMatrixMultiply(M, MRotation);
1663     M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
1664     M.r[3] = XMVectorAdd(M.r[3], VTranslation);
1665
1666     return M;
1667 #else // _XM_VMX128_INTRINSICS_
1668 #endif // _XM_VMX128_INTRINSICS_
1669 }
1670
1671 //------------------------------------------------------------------------------
1672
1673 XMINLINE XMMATRIX XMMatrixTransformation
1674 (
1675     FXMVECTOR ScalingOrigin, 
1676     FXMVECTOR ScalingOrientationQuaternion, 
1677     FXMVECTOR Scaling, 
1678     CXMVECTOR RotationOrigin, 
1679     CXMVECTOR RotationQuaternion, 
1680     CXMVECTOR Translation
1681 )
1682 {
1683 #if defined(_XM_NO_INTRINSICS_)
1684
1685     XMMATRIX M;
1686     XMVECTOR NegScalingOrigin;
1687     XMVECTOR VScalingOrigin;
1688     XMMATRIX MScalingOriginI;
1689     XMMATRIX MScalingOrientation;
1690     XMMATRIX MScalingOrientationT;
1691     XMMATRIX MScaling;
1692     XMVECTOR VRotationOrigin;
1693     XMMATRIX MRotation;
1694     XMVECTOR VTranslation;
1695
1696     // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation *
1697     //         MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1698
1699     VScalingOrigin       = XMVectorSelect(g_XMSelect1110.v, ScalingOrigin, g_XMSelect1110.v);
1700     NegScalingOrigin     = XMVectorNegate(ScalingOrigin);
1701
1702     MScalingOriginI      = XMMatrixTranslationFromVector(NegScalingOrigin);
1703     MScalingOrientation  = XMMatrixRotationQuaternion(ScalingOrientationQuaternion);
1704     MScalingOrientationT = XMMatrixTranspose(MScalingOrientation);
1705     MScaling             = XMMatrixScalingFromVector(Scaling);
1706     VRotationOrigin      = XMVectorSelect(g_XMSelect1110.v, RotationOrigin, g_XMSelect1110.v);
1707     MRotation            = XMMatrixRotationQuaternion(RotationQuaternion);
1708     VTranslation         = XMVectorSelect(g_XMSelect1110.v, Translation, g_XMSelect1110.v);
1709
1710     M      = XMMatrixMultiply(MScalingOriginI, MScalingOrientationT);
1711     M      = XMMatrixMultiply(M, MScaling);
1712     M      = XMMatrixMultiply(M, MScalingOrientation);
1713     M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin);
1714     M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
1715     M      = XMMatrixMultiply(M, MRotation);
1716     M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
1717     M.r[3] = XMVectorAdd(M.r[3], VTranslation);
1718
1719     return M;
1720
1721 #elif defined(_XM_SSE_INTRINSICS_)
1722     XMMATRIX M;
1723     XMVECTOR NegScalingOrigin;
1724     XMVECTOR VScalingOrigin;
1725     XMMATRIX MScalingOriginI;
1726     XMMATRIX MScalingOrientation;
1727     XMMATRIX MScalingOrientationT;
1728     XMMATRIX MScaling;
1729     XMVECTOR VRotationOrigin;
1730     XMMATRIX MRotation;
1731     XMVECTOR VTranslation;
1732
1733     // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation *
1734     //         MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1735
1736     VScalingOrigin       = _mm_and_ps(ScalingOrigin,g_XMMask3);
1737     NegScalingOrigin     = XMVectorNegate(ScalingOrigin);
1738
1739     MScalingOriginI      = XMMatrixTranslationFromVector(NegScalingOrigin);
1740     MScalingOrientation  = XMMatrixRotationQuaternion(ScalingOrientationQuaternion);
1741     MScalingOrientationT = XMMatrixTranspose(MScalingOrientation);
1742     MScaling             = XMMatrixScalingFromVector(Scaling);
1743     VRotationOrigin      = _mm_and_ps(RotationOrigin,g_XMMask3);
1744     MRotation            = XMMatrixRotationQuaternion(RotationQuaternion);
1745     VTranslation         = _mm_and_ps(Translation,g_XMMask3);
1746
1747     M      = XMMatrixMultiply(MScalingOriginI, MScalingOrientationT);
1748     M      = XMMatrixMultiply(M, MScaling);
1749     M      = XMMatrixMultiply(M, MScalingOrientation);
1750     M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin);
1751     M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
1752     M      = XMMatrixMultiply(M, MRotation);
1753     M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
1754     M.r[3] = XMVectorAdd(M.r[3], VTranslation);
1755
1756     return M;
1757 #else // _XM_VMX128_INTRINSICS_
1758 #endif // _XM_VMX128_INTRINSICS_
1759 }
1760
1761 //------------------------------------------------------------------------------
1762
1763 XMINLINE XMMATRIX XMMatrixAffineTransformation2D
1764 (
1765     FXMVECTOR Scaling, 
1766     FXMVECTOR RotationOrigin, 
1767     FLOAT    Rotation, 
1768     FXMVECTOR Translation
1769 )
1770 {
1771 #if defined(_XM_NO_INTRINSICS_)
1772
1773     XMMATRIX M;
1774     XMVECTOR VScaling;
1775     XMMATRIX MScaling;
1776     XMVECTOR VRotationOrigin;
1777     XMMATRIX MRotation;
1778     XMVECTOR VTranslation;
1779
1780     // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1781
1782     VScaling             = XMVectorSelect(g_XMOne.v, Scaling, g_XMSelect1100.v);
1783     MScaling             = XMMatrixScalingFromVector(VScaling);
1784     VRotationOrigin      = XMVectorSelect(g_XMSelect1100.v, RotationOrigin, g_XMSelect1100.v);
1785     MRotation            = XMMatrixRotationZ(Rotation);
1786     VTranslation         = XMVectorSelect(g_XMSelect1100.v, Translation,g_XMSelect1100.v);
1787
1788     M      = MScaling;
1789     M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
1790     M      = XMMatrixMultiply(M, MRotation);
1791     M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
1792     M.r[3] = XMVectorAdd(M.r[3], VTranslation);
1793
1794     return M;
1795
1796 #elif defined(_XM_SSE_INTRINSICS_)
1797     XMMATRIX M;
1798     XMVECTOR VScaling;
1799     XMMATRIX MScaling;
1800     XMVECTOR VRotationOrigin;
1801     XMMATRIX MRotation;
1802     XMVECTOR VTranslation;
1803     static const XMVECTORU32 Mask2 = {0xFFFFFFFFU,0xFFFFFFFFU,0,0};
1804     static const XMVECTORF32 ZW1 = {0,0,1.0f,1.0f};
1805
1806     // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1807
1808     VScaling = _mm_and_ps(Scaling, Mask2);
1809     VScaling = _mm_or_ps(VScaling, ZW1);
1810     MScaling = XMMatrixScalingFromVector(VScaling);
1811     VRotationOrigin = _mm_and_ps(RotationOrigin, Mask2);
1812     MRotation = XMMatrixRotationZ(Rotation);
1813     VTranslation = _mm_and_ps(Translation, Mask2);
1814
1815     M      = MScaling;
1816     M.r[3] = _mm_sub_ps(M.r[3], VRotationOrigin);
1817     M      = XMMatrixMultiply(M, MRotation);
1818     M.r[3] = _mm_add_ps(M.r[3], VRotationOrigin);
1819     M.r[3] = _mm_add_ps(M.r[3], VTranslation);
1820     return M;
1821 #else // _XM_VMX128_INTRINSICS_
1822 #endif // _XM_VMX128_INTRINSICS_
1823 }
1824
1825 //------------------------------------------------------------------------------
1826
1827 XMINLINE XMMATRIX XMMatrixAffineTransformation
1828 (
1829     FXMVECTOR Scaling, 
1830     FXMVECTOR RotationOrigin, 
1831     FXMVECTOR RotationQuaternion, 
1832     CXMVECTOR Translation
1833 )
1834 {
1835 #if defined(_XM_NO_INTRINSICS_)
1836
1837     XMMATRIX M;
1838     XMMATRIX MScaling;
1839     XMVECTOR VRotationOrigin;
1840     XMMATRIX MRotation;
1841     XMVECTOR VTranslation;
1842
1843     // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1844
1845     MScaling            = XMMatrixScalingFromVector(Scaling);
1846     VRotationOrigin     = XMVectorSelect(g_XMSelect1110.v, RotationOrigin,g_XMSelect1110.v);
1847     MRotation           = XMMatrixRotationQuaternion(RotationQuaternion);
1848     VTranslation        = XMVectorSelect(g_XMSelect1110.v, Translation,g_XMSelect1110.v);
1849
1850     M      = MScaling;
1851     M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin);
1852     M      = XMMatrixMultiply(M, MRotation);
1853     M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin);
1854     M.r[3] = XMVectorAdd(M.r[3], VTranslation);
1855
1856     return M;
1857
1858 #elif defined(_XM_SSE_INTRINSICS_)
1859     XMMATRIX M;
1860     XMMATRIX MScaling;
1861     XMVECTOR VRotationOrigin;
1862     XMMATRIX MRotation;
1863     XMVECTOR VTranslation;
1864
1865     // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1866
1867     MScaling            = XMMatrixScalingFromVector(Scaling);
1868     VRotationOrigin     = _mm_and_ps(RotationOrigin,g_XMMask3);
1869     MRotation           = XMMatrixRotationQuaternion(RotationQuaternion);
1870     VTranslation        = _mm_and_ps(Translation,g_XMMask3);
1871
1872     M      = MScaling;
1873     M.r[3] = _mm_sub_ps(M.r[3], VRotationOrigin);
1874     M      = XMMatrixMultiply(M, MRotation);
1875     M.r[3] = _mm_add_ps(M.r[3], VRotationOrigin);
1876     M.r[3] = _mm_add_ps(M.r[3], VTranslation);
1877
1878     return M;
1879 #else // _XM_VMX128_INTRINSICS_
1880 #endif // _XM_VMX128_INTRINSICS_
1881 }
1882
1883 //------------------------------------------------------------------------------
1884
1885 XMFINLINE XMMATRIX XMMatrixReflect
1886 (
1887     FXMVECTOR ReflectionPlane
1888 )
1889 {
1890 #if defined(_XM_NO_INTRINSICS_)
1891
1892     XMVECTOR               P;
1893     XMVECTOR               S;
1894     XMVECTOR               A, B, C, D;
1895     XMMATRIX               M;
1896     static CONST XMVECTOR  NegativeTwo = {-2.0f, -2.0f, -2.0f, 0.0f};
1897
1898     XMASSERT(!XMVector3Equal(ReflectionPlane, XMVectorZero()));
1899     XMASSERT(!XMPlaneIsInfinite(ReflectionPlane));
1900
1901     P = XMPlaneNormalize(ReflectionPlane);
1902     S = XMVectorMultiply(P, NegativeTwo);
1903
1904     A = XMVectorSplatX(P);
1905     B = XMVectorSplatY(P);
1906     C = XMVectorSplatZ(P);
1907     D = XMVectorSplatW(P);
1908
1909     M.r[0] = XMVectorMultiplyAdd(A, S, g_XMIdentityR0.v);
1910     M.r[1] = XMVectorMultiplyAdd(B, S, g_XMIdentityR1.v);
1911     M.r[2] = XMVectorMultiplyAdd(C, S, g_XMIdentityR2.v);
1912     M.r[3] = XMVectorMultiplyAdd(D, S, g_XMIdentityR3.v);
1913
1914     return M;
1915
1916 #elif defined(_XM_SSE_INTRINSICS_)
1917     XMMATRIX M;
1918     static CONST XMVECTORF32 NegativeTwo = {-2.0f, -2.0f, -2.0f, 0.0f};
1919
1920     XMASSERT(!XMVector3Equal(ReflectionPlane, XMVectorZero()));
1921     XMASSERT(!XMPlaneIsInfinite(ReflectionPlane));
1922
1923     XMVECTOR P = XMPlaneNormalize(ReflectionPlane);
1924     XMVECTOR S = _mm_mul_ps(P,NegativeTwo);
1925     XMVECTOR X = _mm_shuffle_ps(P,P,_MM_SHUFFLE(0,0,0,0));
1926     XMVECTOR Y = _mm_shuffle_ps(P,P,_MM_SHUFFLE(1,1,1,1));
1927     XMVECTOR Z = _mm_shuffle_ps(P,P,_MM_SHUFFLE(2,2,2,2));
1928     P = _mm_shuffle_ps(P,P,_MM_SHUFFLE(3,3,3,3));
1929     X = _mm_mul_ps(X,S);
1930     Y = _mm_mul_ps(Y,S);
1931     Z = _mm_mul_ps(Z,S);
1932     P = _mm_mul_ps(P,S);
1933     X = _mm_add_ps(X,g_XMIdentityR0);
1934     Y = _mm_add_ps(Y,g_XMIdentityR1);
1935     Z = _mm_add_ps(Z,g_XMIdentityR2);
1936     P = _mm_add_ps(P,g_XMIdentityR3);
1937     M.r[0] = X;
1938     M.r[1] = Y;
1939     M.r[2] = Z;
1940     M.r[3] = P;
1941     return M;
1942 #else // _XM_VMX128_INTRINSICS_
1943 #endif // _XM_VMX128_INTRINSICS_
1944 }
1945
1946 //------------------------------------------------------------------------------
1947
1948 XMFINLINE XMMATRIX XMMatrixShadow
1949 (
1950     FXMVECTOR ShadowPlane, 
1951     FXMVECTOR LightPosition
1952 )
1953 {
1954 #if defined(_XM_NO_INTRINSICS_)
1955
1956     XMVECTOR               P;
1957     XMVECTOR               Dot;
1958     XMVECTOR               A, B, C, D;
1959     XMMATRIX               M;
1960     static CONST XMVECTORU32 Select0001 = {XM_SELECT_0, XM_SELECT_0, XM_SELECT_0, XM_SELECT_1};
1961
1962     XMASSERT(!XMVector3Equal(ShadowPlane, XMVectorZero()));
1963     XMASSERT(!XMPlaneIsInfinite(ShadowPlane));
1964
1965     P = XMPlaneNormalize(ShadowPlane);
1966     Dot = XMPlaneDot(P, LightPosition);
1967     P = XMVectorNegate(P);
1968     D = XMVectorSplatW(P);
1969     C = XMVectorSplatZ(P);
1970     B = XMVectorSplatY(P);
1971     A = XMVectorSplatX(P);
1972     Dot = XMVectorSelect(Select0001.v, Dot, Select0001.v);
1973     M.r[3] = XMVectorMultiplyAdd(D, LightPosition, Dot);
1974     Dot = XMVectorRotateLeft(Dot, 1);
1975     M.r[2] = XMVectorMultiplyAdd(C, LightPosition, Dot);
1976     Dot = XMVectorRotateLeft(Dot, 1);
1977     M.r[1] = XMVectorMultiplyAdd(B, LightPosition, Dot);
1978     Dot = XMVectorRotateLeft(Dot, 1);
1979     M.r[0] = XMVectorMultiplyAdd(A, LightPosition, Dot);
1980     return M;
1981
1982 #elif defined(_XM_SSE_INTRINSICS_)
1983     XMMATRIX M;
1984     XMASSERT(!XMVector3Equal(ShadowPlane, XMVectorZero()));
1985     XMASSERT(!XMPlaneIsInfinite(ShadowPlane));
1986     XMVECTOR P = XMPlaneNormalize(ShadowPlane);
1987     XMVECTOR Dot = XMPlaneDot(P,LightPosition);
1988     // Negate
1989     P = _mm_mul_ps(P,g_XMNegativeOne);
1990     XMVECTOR X = _mm_shuffle_ps(P,P,_MM_SHUFFLE(0,0,0,0));
1991     XMVECTOR Y = _mm_shuffle_ps(P,P,_MM_SHUFFLE(1,1,1,1));
1992     XMVECTOR Z = _mm_shuffle_ps(P,P,_MM_SHUFFLE(2,2,2,2));
1993     P = _mm_shuffle_ps(P,P,_MM_SHUFFLE(3,3,3,3));
1994     Dot = _mm_and_ps(Dot,g_XMMaskW);
1995     X = _mm_mul_ps(X,LightPosition);
1996     Y = _mm_mul_ps(Y,LightPosition);
1997     Z = _mm_mul_ps(Z,LightPosition);
1998     P = _mm_mul_ps(P,LightPosition);
1999     P = _mm_add_ps(P,Dot);
2000     Dot = _mm_shuffle_ps(Dot,Dot,_MM_SHUFFLE(0,3,2,1));
2001     Z = _mm_add_ps(Z,Dot);
2002     Dot = _mm_shuffle_ps(Dot,Dot,_MM_SHUFFLE(0,3,2,1));
2003     Y = _mm_add_ps(Y,Dot);
2004     Dot = _mm_shuffle_ps(Dot,Dot,_MM_SHUFFLE(0,3,2,1));
2005     X = _mm_add_ps(X,Dot);
2006     // Store the resulting matrix
2007     M.r[0] = X;
2008     M.r[1] = Y;
2009     M.r[2] = Z;
2010     M.r[3] = P;
2011     return M;
2012 #else // _XM_VMX128_INTRINSICS_
2013 #endif // _XM_VMX128_INTRINSICS_
2014 }
2015
2016 //------------------------------------------------------------------------------
2017 // View and projection initialization operations
2018 //------------------------------------------------------------------------------
2019
2020
2021 //------------------------------------------------------------------------------
2022
2023 XMFINLINE XMMATRIX XMMatrixLookAtLH
2024 (
2025     FXMVECTOR EyePosition, 
2026     FXMVECTOR FocusPosition, 
2027     FXMVECTOR UpDirection
2028 )
2029 {
2030     XMVECTOR EyeDirection;
2031     XMMATRIX M;
2032
2033     EyeDirection = XMVectorSubtract(FocusPosition, EyePosition);
2034     M = XMMatrixLookToLH(EyePosition, EyeDirection, UpDirection);
2035     
2036     return M;
2037 }
2038
2039 //------------------------------------------------------------------------------
2040
2041 XMFINLINE XMMATRIX XMMatrixLookAtRH
2042 (
2043     FXMVECTOR EyePosition, 
2044     FXMVECTOR FocusPosition, 
2045     FXMVECTOR UpDirection
2046 )
2047 {
2048     XMVECTOR NegEyeDirection;
2049     XMMATRIX M;
2050
2051     NegEyeDirection = XMVectorSubtract(EyePosition, FocusPosition);
2052     M = XMMatrixLookToLH(EyePosition, NegEyeDirection, UpDirection);
2053     
2054     return M;
2055 }
2056
2057 //------------------------------------------------------------------------------
2058
2059 XMINLINE XMMATRIX XMMatrixLookToLH
2060 (
2061     FXMVECTOR EyePosition, 
2062     FXMVECTOR EyeDirection, 
2063     FXMVECTOR UpDirection
2064 )
2065 {
2066 #if defined(_XM_NO_INTRINSICS_)
2067
2068     XMVECTOR NegEyePosition;
2069     XMVECTOR D0, D1, D2;
2070     XMVECTOR R0, R1, R2;
2071     XMMATRIX M;
2072
2073     XMASSERT(!XMVector3Equal(EyeDirection, XMVectorZero()));
2074     XMASSERT(!XMVector3IsInfinite(EyeDirection));
2075     XMASSERT(!XMVector3Equal(UpDirection, XMVectorZero()));
2076     XMASSERT(!XMVector3IsInfinite(UpDirection));
2077
2078     R2 = XMVector3Normalize(EyeDirection);
2079
2080     R0 = XMVector3Cross(UpDirection, R2);
2081     R0 = XMVector3Normalize(R0);
2082
2083     R1 = XMVector3Cross(R2, R0);
2084
2085     NegEyePosition = XMVectorNegate(EyePosition);
2086
2087     D0 = XMVector3Dot(R0, NegEyePosition);
2088     D1 = XMVector3Dot(R1, NegEyePosition);
2089     D2 = XMVector3Dot(R2, NegEyePosition);
2090
2091     M.r[0] = XMVectorSelect(D0, R0, g_XMSelect1110.v);
2092     M.r[1] = XMVectorSelect(D1, R1, g_XMSelect1110.v);
2093     M.r[2] = XMVectorSelect(D2, R2, g_XMSelect1110.v);
2094     M.r[3] = g_XMIdentityR3.v;
2095
2096     M = XMMatrixTranspose(M);
2097
2098     return M;
2099
2100 #elif defined(_XM_SSE_INTRINSICS_)
2101     XMMATRIX M;
2102
2103     XMASSERT(!XMVector3Equal(EyeDirection, XMVectorZero()));
2104     XMASSERT(!XMVector3IsInfinite(EyeDirection));
2105     XMASSERT(!XMVector3Equal(UpDirection, XMVectorZero()));
2106     XMASSERT(!XMVector3IsInfinite(UpDirection));
2107
2108     XMVECTOR R2 = XMVector3Normalize(EyeDirection);
2109     XMVECTOR R0 = XMVector3Cross(UpDirection, R2);
2110     R0 = XMVector3Normalize(R0);
2111     XMVECTOR R1 = XMVector3Cross(R2,R0);
2112     XMVECTOR NegEyePosition = _mm_mul_ps(EyePosition,g_XMNegativeOne);
2113     XMVECTOR D0 = XMVector3Dot(R0,NegEyePosition);
2114     XMVECTOR D1 = XMVector3Dot(R1,NegEyePosition);
2115     XMVECTOR D2 = XMVector3Dot(R2,NegEyePosition);
2116     R0 = _mm_and_ps(R0,g_XMMask3);
2117     R1 = _mm_and_ps(R1,g_XMMask3);
2118     R2 = _mm_and_ps(R2,g_XMMask3);
2119     D0 = _mm_and_ps(D0,g_XMMaskW);
2120     D1 = _mm_and_ps(D1,g_XMMaskW);
2121     D2 = _mm_and_ps(D2,g_XMMaskW);
2122     D0 = _mm_or_ps(D0,R0);
2123     D1 = _mm_or_ps(D1,R1);
2124     D2 = _mm_or_ps(D2,R2);
2125     M.r[0] = D0;
2126     M.r[1] = D1;
2127     M.r[2] = D2;
2128     M.r[3] = g_XMIdentityR3;
2129     M = XMMatrixTranspose(M);
2130     return M;
2131 #else // _XM_VMX128_INTRINSICS_
2132 #endif // _XM_VMX128_INTRINSICS_
2133 }
2134
2135 //------------------------------------------------------------------------------
2136
2137 XMFINLINE XMMATRIX XMMatrixLookToRH
2138 (
2139     FXMVECTOR EyePosition, 
2140     FXMVECTOR EyeDirection, 
2141     FXMVECTOR UpDirection
2142 )
2143 {
2144     XMVECTOR NegEyeDirection;
2145     XMMATRIX M;
2146
2147     NegEyeDirection = XMVectorNegate(EyeDirection);
2148     M = XMMatrixLookToLH(EyePosition, NegEyeDirection, UpDirection);
2149
2150     return M;
2151 }
2152
2153 //------------------------------------------------------------------------------
2154
2155 XMFINLINE XMMATRIX XMMatrixPerspectiveLH
2156 (
2157     FLOAT ViewWidth, 
2158     FLOAT ViewHeight, 
2159     FLOAT NearZ, 
2160     FLOAT FarZ
2161 )
2162 {
2163 #if defined(_XM_NO_INTRINSICS_)
2164
2165     FLOAT TwoNearZ, fRange;
2166     XMMATRIX M;
2167
2168     XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2169     XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2170     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2171
2172     TwoNearZ = NearZ + NearZ;
2173     fRange = FarZ / (FarZ - NearZ);
2174     M.m[0][0] = TwoNearZ / ViewWidth;
2175     M.m[0][1] = 0.0f;
2176     M.m[0][2] = 0.0f;
2177     M.m[0][3] = 0.0f;
2178
2179     M.m[1][0] = 0.0f;
2180     M.m[1][1] = TwoNearZ / ViewHeight;
2181     M.m[1][2] = 0.0f;
2182     M.m[1][3] = 0.0f;
2183
2184     M.m[2][0] = 0.0f;
2185     M.m[2][1] = 0.0f;
2186     M.m[2][2] = fRange;
2187     M.m[2][3] = 1.0f;
2188
2189     M.m[3][0] = 0.0f;  
2190     M.m[3][1] = 0.0f;
2191     M.m[3][2] = -fRange * NearZ;
2192     M.m[3][3] = 0.0f;
2193
2194     return M;
2195
2196 #elif defined(_XM_SSE_INTRINSICS_)
2197     XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2198     XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2199     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2200
2201     XMMATRIX M;
2202     FLOAT TwoNearZ = NearZ + NearZ;
2203     FLOAT fRange = FarZ / (FarZ - NearZ);
2204     // Note: This is recorded on the stack
2205     XMVECTOR rMem = {
2206         TwoNearZ / ViewWidth,
2207         TwoNearZ / ViewHeight,
2208         fRange,
2209         -fRange * NearZ
2210     };
2211     // Copy from memory to SSE register
2212     XMVECTOR vValues = rMem;
2213     XMVECTOR vTemp = _mm_setzero_ps(); 
2214     // Copy x only
2215     vTemp = _mm_move_ss(vTemp,vValues);
2216     // TwoNearZ / ViewWidth,0,0,0
2217     M.r[0] = vTemp;
2218     // 0,TwoNearZ / ViewHeight,0,0
2219     vTemp = vValues;
2220     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2221     M.r[1] = vTemp;
2222     // x=fRange,y=-fRange * NearZ,0,1.0f
2223     vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2));
2224     // 0,0,fRange,1.0f
2225     vTemp = _mm_setzero_ps();
2226     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0));
2227     M.r[2] = vTemp;
2228     // 0,0,-fRange * NearZ,0
2229     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0));
2230     M.r[3] = vTemp;
2231
2232     return M;
2233 #else // _XM_VMX128_INTRINSICS_
2234 #endif // _XM_VMX128_INTRINSICS_
2235 }
2236
2237 //------------------------------------------------------------------------------
2238
2239 XMFINLINE XMMATRIX XMMatrixPerspectiveRH
2240 (
2241     FLOAT ViewWidth, 
2242     FLOAT ViewHeight, 
2243     FLOAT NearZ, 
2244     FLOAT FarZ
2245 )
2246 {
2247 #if defined(_XM_NO_INTRINSICS_)
2248
2249     FLOAT TwoNearZ, fRange;
2250     XMMATRIX M;
2251
2252     XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2253     XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2254     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2255
2256     TwoNearZ = NearZ + NearZ;
2257     fRange = FarZ / (NearZ - FarZ);
2258     M.m[0][0] = TwoNearZ / ViewWidth;
2259     M.m[0][1] = 0.0f;
2260     M.m[0][2] = 0.0f;
2261     M.m[0][3] = 0.0f;
2262
2263     M.m[1][0] = 0.0f;
2264     M.m[1][1] = TwoNearZ / ViewHeight;
2265     M.m[1][2] = 0.0f;
2266     M.m[1][3] = 0.0f;
2267
2268     M.m[2][0] = 0.0f;
2269     M.m[2][1] = 0.0f;
2270     M.m[2][2] = fRange;
2271     M.m[2][3] = -1.0f;
2272
2273     M.m[3][0] = 0.0f;
2274     M.m[3][1] = 0.0f;
2275     M.m[3][2] = fRange * NearZ;
2276     M.m[3][3] = 0.0f;
2277
2278     return M;
2279
2280 #elif defined(_XM_SSE_INTRINSICS_)
2281     XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2282     XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2283     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2284
2285     XMMATRIX M;
2286     FLOAT TwoNearZ = NearZ + NearZ;
2287     FLOAT fRange = FarZ / (NearZ-FarZ);
2288     // Note: This is recorded on the stack
2289     XMVECTOR rMem = {
2290         TwoNearZ / ViewWidth,
2291         TwoNearZ / ViewHeight,
2292         fRange,
2293         fRange * NearZ
2294     };
2295     // Copy from memory to SSE register
2296     XMVECTOR vValues = rMem;
2297     XMVECTOR vTemp = _mm_setzero_ps(); 
2298     // Copy x only
2299     vTemp = _mm_move_ss(vTemp,vValues);
2300     // TwoNearZ / ViewWidth,0,0,0
2301     M.r[0] = vTemp;
2302     // 0,TwoNearZ / ViewHeight,0,0
2303     vTemp = vValues;
2304     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2305     M.r[1] = vTemp;
2306     // x=fRange,y=-fRange * NearZ,0,-1.0f
2307     vValues = _mm_shuffle_ps(vValues,g_XMNegIdentityR3,_MM_SHUFFLE(3,2,3,2));
2308     // 0,0,fRange,-1.0f
2309     vTemp = _mm_setzero_ps();
2310     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0));
2311     M.r[2] = vTemp;
2312     // 0,0,-fRange * NearZ,0
2313     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0));
2314     M.r[3] = vTemp;
2315     return M;
2316 #else // _XM_VMX128_INTRINSICS_
2317 #endif // _XM_VMX128_INTRINSICS_
2318 }
2319
2320 //------------------------------------------------------------------------------
2321
2322 XMFINLINE XMMATRIX XMMatrixPerspectiveFovLH
2323 (
2324     FLOAT FovAngleY, 
2325     FLOAT AspectHByW, 
2326     FLOAT NearZ, 
2327     FLOAT FarZ
2328 )
2329 {
2330 #if defined(_XM_NO_INTRINSICS_)
2331
2332     FLOAT    SinFov;
2333     FLOAT    CosFov;
2334     FLOAT    Height;
2335     FLOAT    Width;
2336     XMMATRIX M;
2337
2338     XMASSERT(!XMScalarNearEqual(FovAngleY, 0.0f, 0.00001f * 2.0f));
2339     XMASSERT(!XMScalarNearEqual(AspectHByW, 0.0f, 0.00001f));
2340     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2341
2342     XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY);
2343
2344     Height = CosFov / SinFov;
2345     Width = Height / AspectHByW;
2346
2347     M.r[0] = XMVectorSet(Width, 0.0f, 0.0f, 0.0f);
2348     M.r[1] = XMVectorSet(0.0f, Height, 0.0f, 0.0f);
2349     M.r[2] = XMVectorSet(0.0f, 0.0f, FarZ / (FarZ - NearZ), 1.0f);
2350     M.r[3] = XMVectorSet(0.0f, 0.0f, -M.r[2].vector4_f32[2] * NearZ, 0.0f);
2351
2352     return M;
2353
2354 #elif defined(_XM_SSE_INTRINSICS_)
2355     XMASSERT(!XMScalarNearEqual(FovAngleY, 0.0f, 0.00001f * 2.0f));
2356     XMASSERT(!XMScalarNearEqual(AspectHByW, 0.0f, 0.00001f));
2357     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2358     XMMATRIX M;
2359     FLOAT    SinFov;
2360     FLOAT    CosFov;
2361     XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY);
2362     FLOAT fRange = FarZ / (FarZ-NearZ);
2363     // Note: This is recorded on the stack
2364     FLOAT Height = CosFov / SinFov;
2365     XMVECTOR rMem = {
2366         Height / AspectHByW,
2367         Height,
2368         fRange,
2369         -fRange * NearZ
2370     };
2371     // Copy from memory to SSE register
2372     XMVECTOR vValues = rMem;
2373     XMVECTOR vTemp = _mm_setzero_ps(); 
2374     // Copy x only
2375     vTemp = _mm_move_ss(vTemp,vValues);
2376     // CosFov / SinFov,0,0,0
2377     M.r[0] = vTemp;
2378     // 0,Height / AspectHByW,0,0
2379     vTemp = vValues;
2380     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2381     M.r[1] = vTemp;
2382     // x=fRange,y=-fRange * NearZ,0,1.0f
2383     vTemp = _mm_setzero_ps();
2384     vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2));
2385     // 0,0,fRange,1.0f
2386     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0));
2387     M.r[2] = vTemp;
2388     // 0,0,-fRange * NearZ,0.0f
2389     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0));
2390     M.r[3] = vTemp;
2391     return M;
2392 #else // _XM_VMX128_INTRINSICS_
2393 #endif // _XM_VMX128_INTRINSICS_
2394 }
2395
2396 //------------------------------------------------------------------------------
2397
2398 XMFINLINE XMMATRIX XMMatrixPerspectiveFovRH
2399 (
2400     FLOAT FovAngleY, 
2401     FLOAT AspectHByW, 
2402     FLOAT NearZ, 
2403     FLOAT FarZ
2404 )
2405 {
2406 #if defined(_XM_NO_INTRINSICS_)
2407
2408     FLOAT    SinFov;
2409     FLOAT    CosFov;
2410     FLOAT    Height;
2411     FLOAT    Width;
2412     XMMATRIX M;
2413
2414     XMASSERT(!XMScalarNearEqual(FovAngleY, 0.0f, 0.00001f * 2.0f));
2415     XMASSERT(!XMScalarNearEqual(AspectHByW, 0.0f, 0.00001f));
2416     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2417
2418     XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY);
2419
2420     Height = CosFov / SinFov;
2421     Width = Height / AspectHByW;
2422
2423     M.r[0] = XMVectorSet(Width, 0.0f, 0.0f, 0.0f);
2424     M.r[1] = XMVectorSet(0.0f, Height, 0.0f, 0.0f);
2425     M.r[2] = XMVectorSet(0.0f, 0.0f, FarZ / (NearZ - FarZ), -1.0f);
2426     M.r[3] = XMVectorSet(0.0f, 0.0f, M.r[2].vector4_f32[2] * NearZ, 0.0f);
2427
2428     return M;
2429
2430 #elif defined(_XM_SSE_INTRINSICS_)
2431     XMASSERT(!XMScalarNearEqual(FovAngleY, 0.0f, 0.00001f * 2.0f));
2432     XMASSERT(!XMScalarNearEqual(AspectHByW, 0.0f, 0.00001f));
2433     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2434     XMMATRIX M;
2435     FLOAT    SinFov;
2436     FLOAT    CosFov;
2437     XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY);
2438     FLOAT fRange = FarZ / (NearZ-FarZ);
2439     // Note: This is recorded on the stack
2440     FLOAT Height = CosFov / SinFov;
2441     XMVECTOR rMem = {
2442         Height / AspectHByW,
2443         Height,
2444         fRange,
2445         fRange * NearZ
2446     };
2447     // Copy from memory to SSE register
2448     XMVECTOR vValues = rMem;
2449     XMVECTOR vTemp = _mm_setzero_ps(); 
2450     // Copy x only
2451     vTemp = _mm_move_ss(vTemp,vValues);
2452     // CosFov / SinFov,0,0,0
2453     M.r[0] = vTemp;
2454     // 0,Height / AspectHByW,0,0
2455     vTemp = vValues;
2456     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2457     M.r[1] = vTemp;
2458     // x=fRange,y=-fRange * NearZ,0,-1.0f
2459     vTemp = _mm_setzero_ps();
2460     vValues = _mm_shuffle_ps(vValues,g_XMNegIdentityR3,_MM_SHUFFLE(3,2,3,2));
2461     // 0,0,fRange,-1.0f
2462     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0));
2463     M.r[2] = vTemp;
2464     // 0,0,fRange * NearZ,0.0f
2465     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0));
2466     M.r[3] = vTemp;
2467     return M;
2468 #else // _XM_VMX128_INTRINSICS_
2469 #endif // _XM_VMX128_INTRINSICS_
2470 }
2471
2472 //------------------------------------------------------------------------------
2473
2474 XMFINLINE XMMATRIX XMMatrixPerspectiveOffCenterLH
2475 (
2476     FLOAT ViewLeft, 
2477     FLOAT ViewRight, 
2478     FLOAT ViewBottom, 
2479     FLOAT ViewTop, 
2480     FLOAT NearZ, 
2481     FLOAT FarZ
2482 )
2483 {
2484 #if defined(_XM_NO_INTRINSICS_)
2485
2486     FLOAT    TwoNearZ;
2487     FLOAT    ReciprocalWidth;
2488     FLOAT    ReciprocalHeight;
2489     FLOAT    fRange;
2490     XMMATRIX M;
2491
2492     XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2493     XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2494     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2495
2496     TwoNearZ = NearZ + NearZ;
2497     ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2498     ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2499     fRange = FarZ / (FarZ-NearZ);
2500
2501     M.m[0][0] = TwoNearZ * ReciprocalWidth;
2502     M.m[0][1] = 0.0f;
2503     M.m[0][2] = 0.0f;
2504     M.m[0][3] = 0.0f;
2505
2506     M.m[1][0] = 0.0f;
2507     M.m[1][1] = TwoNearZ * ReciprocalHeight;
2508     M.m[1][2] = 0.0f;
2509     M.m[1][3] = 0.0f;
2510
2511     M.m[2][0] = -(ViewLeft + ViewRight) * ReciprocalWidth;
2512     M.m[2][1] = -(ViewTop + ViewBottom) * ReciprocalHeight;
2513     M.m[2][2] = fRange;
2514     M.m[2][3] = 1.0f;
2515
2516     M.m[3][0] = 0.0f;
2517     M.m[3][1] = 0.0f;
2518     M.m[3][2] = -fRange * NearZ;
2519     M.m[3][3] = 0.0f;
2520     return M;
2521
2522 #elif defined(_XM_SSE_INTRINSICS_)
2523     XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2524     XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2525     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2526     XMMATRIX M;
2527     FLOAT TwoNearZ = NearZ+NearZ;
2528     FLOAT ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2529     FLOAT ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2530     FLOAT fRange = FarZ / (FarZ-NearZ);
2531     // Note: This is recorded on the stack
2532     XMVECTOR rMem = {
2533         TwoNearZ*ReciprocalWidth,
2534         TwoNearZ*ReciprocalHeight,
2535         -fRange * NearZ,
2536         0
2537     };
2538     // Copy from memory to SSE register
2539     XMVECTOR vValues = rMem;
2540     XMVECTOR vTemp = _mm_setzero_ps(); 
2541     // Copy x only
2542     vTemp = _mm_move_ss(vTemp,vValues);
2543     // TwoNearZ*ReciprocalWidth,0,0,0
2544     M.r[0] = vTemp;
2545     // 0,TwoNearZ*ReciprocalHeight,0,0
2546     vTemp = vValues;
2547     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2548     M.r[1] = vTemp;
2549     // 0,0,fRange,1.0f
2550     M.r[2] = XMVectorSet( -(ViewLeft + ViewRight) * ReciprocalWidth,
2551                           -(ViewTop + ViewBottom) * ReciprocalHeight,
2552                           fRange,
2553                           1.0f );
2554     // 0,0,-fRange * NearZ,0.0f
2555     vValues = _mm_and_ps(vValues,g_XMMaskZ);
2556     M.r[3] = vValues;
2557     return M;
2558 #else // _XM_VMX128_INTRINSICS_
2559 #endif // _XM_VMX128_INTRINSICS_
2560 }
2561
2562 //------------------------------------------------------------------------------
2563
2564 XMFINLINE XMMATRIX XMMatrixPerspectiveOffCenterRH
2565 (
2566     FLOAT ViewLeft, 
2567     FLOAT ViewRight, 
2568     FLOAT ViewBottom, 
2569     FLOAT ViewTop, 
2570     FLOAT NearZ, 
2571     FLOAT FarZ
2572 )
2573 {
2574 #if defined(_XM_NO_INTRINSICS_)
2575
2576     FLOAT    TwoNearZ;
2577     FLOAT    ReciprocalWidth;
2578     FLOAT    ReciprocalHeight;
2579     FLOAT    fRange;
2580     XMMATRIX M;
2581
2582     XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2583     XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2584     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2585
2586     TwoNearZ = NearZ + NearZ;
2587     ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2588     ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2589     fRange = FarZ / (NearZ-FarZ);
2590
2591     M.m[0][0] = TwoNearZ * ReciprocalWidth;
2592     M.m[0][1] = 0.0f;
2593     M.m[0][2] = 0.0f;
2594     M.m[0][3] = 0.0f;
2595
2596     M.m[1][0] = 0.0f;
2597     M.m[1][1] = TwoNearZ * ReciprocalHeight;
2598     M.m[1][2] = 0.0f;
2599     M.m[1][3] = 0.0f;
2600
2601     M.m[2][0] = (ViewLeft + ViewRight) * ReciprocalWidth;
2602     M.m[2][1] = (ViewTop + ViewBottom) * ReciprocalHeight;
2603     M.m[2][2] = fRange;
2604     M.m[2][3] = -1.0f;
2605
2606     M.m[3][0] = 0.0f;
2607     M.m[3][1] = 0.0f;
2608     M.m[3][2] = fRange * NearZ;
2609     M.m[3][3] = 0.0f;
2610     return M;
2611
2612 #elif defined(_XM_SSE_INTRINSICS_)
2613     XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2614     XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2615     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2616
2617     XMMATRIX M;
2618     FLOAT TwoNearZ = NearZ+NearZ;
2619     FLOAT ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2620     FLOAT ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2621     FLOAT fRange = FarZ / (NearZ-FarZ);
2622     // Note: This is recorded on the stack
2623     XMVECTOR rMem = {
2624         TwoNearZ*ReciprocalWidth,
2625         TwoNearZ*ReciprocalHeight,
2626         fRange * NearZ,
2627         0
2628     };
2629     // Copy from memory to SSE register
2630     XMVECTOR vValues = rMem;
2631     XMVECTOR vTemp = _mm_setzero_ps(); 
2632     // Copy x only
2633     vTemp = _mm_move_ss(vTemp,vValues);
2634     // TwoNearZ*ReciprocalWidth,0,0,0
2635     M.r[0] = vTemp;
2636     // 0,TwoNearZ*ReciprocalHeight,0,0
2637     vTemp = vValues;
2638     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2639     M.r[1] = vTemp;
2640     // 0,0,fRange,1.0f
2641     M.r[2] = XMVectorSet((ViewLeft + ViewRight) * ReciprocalWidth, 
2642                          (ViewTop + ViewBottom) * ReciprocalHeight,
2643                          fRange,
2644                          -1.0f);
2645     // 0,0,-fRange * NearZ,0.0f
2646     vValues = _mm_and_ps(vValues,g_XMMaskZ);
2647     M.r[3] = vValues;
2648     return M;
2649 #else // _XM_VMX128_INTRINSICS_
2650 #endif // _XM_VMX128_INTRINSICS_
2651 }
2652
2653 //------------------------------------------------------------------------------
2654
2655 XMFINLINE XMMATRIX XMMatrixOrthographicLH
2656 (
2657     FLOAT ViewWidth, 
2658     FLOAT ViewHeight, 
2659     FLOAT NearZ, 
2660     FLOAT FarZ
2661 )
2662 {
2663 #if defined(_XM_NO_INTRINSICS_)
2664
2665     FLOAT fRange;
2666     XMMATRIX M;
2667
2668     XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2669     XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2670     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2671
2672     fRange = 1.0f / (FarZ-NearZ);
2673     M.r[0] = XMVectorSet(2.0f / ViewWidth, 0.0f, 0.0f, 0.0f);
2674     M.r[1] = XMVectorSet(0.0f, 2.0f / ViewHeight, 0.0f, 0.0f);
2675     M.r[2] = XMVectorSet(0.0f, 0.0f, fRange, 0.0f);
2676     M.r[3] = XMVectorSet(0.0f, 0.0f, -fRange * NearZ, 1.0f);
2677
2678     return M;
2679
2680 #elif defined(_XM_SSE_INTRINSICS_)
2681     XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2682     XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2683     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2684     XMMATRIX M;
2685     FLOAT fRange = 1.0f / (FarZ-NearZ);
2686     // Note: This is recorded on the stack
2687     XMVECTOR rMem = {
2688         2.0f / ViewWidth,
2689         2.0f / ViewHeight,
2690         fRange,
2691         -fRange * NearZ
2692     };
2693     // Copy from memory to SSE register
2694     XMVECTOR vValues = rMem;
2695     XMVECTOR vTemp = _mm_setzero_ps(); 
2696     // Copy x only
2697     vTemp = _mm_move_ss(vTemp,vValues);
2698     // 2.0f / ViewWidth,0,0,0
2699     M.r[0] = vTemp;
2700     // 0,2.0f / ViewHeight,0,0
2701     vTemp = vValues;
2702     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2703     M.r[1] = vTemp;
2704     // x=fRange,y=-fRange * NearZ,0,1.0f
2705     vTemp = _mm_setzero_ps();
2706     vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2));
2707     // 0,0,fRange,0.0f
2708     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,0,0,0));
2709     M.r[2] = vTemp;
2710     // 0,0,-fRange * NearZ,1.0f
2711     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,1,0,0));
2712     M.r[3] = vTemp;
2713     return M;
2714 #else // _XM_VMX128_INTRINSICS_
2715 #endif // _XM_VMX128_INTRINSICS_
2716 }
2717
2718 //------------------------------------------------------------------------------
2719
2720 XMFINLINE XMMATRIX XMMatrixOrthographicRH
2721 (
2722     FLOAT ViewWidth, 
2723     FLOAT ViewHeight, 
2724     FLOAT NearZ, 
2725     FLOAT FarZ
2726 )
2727 {
2728 #if defined(_XM_NO_INTRINSICS_)
2729
2730     XMMATRIX M;
2731
2732     XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2733     XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2734     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2735
2736     M.r[0] = XMVectorSet(2.0f / ViewWidth, 0.0f, 0.0f, 0.0f);
2737     M.r[1] = XMVectorSet(0.0f, 2.0f / ViewHeight, 0.0f, 0.0f);
2738     M.r[2] = XMVectorSet(0.0f, 0.0f, 1.0f / (NearZ - FarZ), 0.0f);
2739     M.r[3] = XMVectorSet(0.0f, 0.0f, M.r[2].vector4_f32[2] * NearZ, 1.0f);
2740
2741     return M;
2742
2743 #elif defined(_XM_SSE_INTRINSICS_)
2744     XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2745     XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2746     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2747     XMMATRIX M;
2748     FLOAT fRange = 1.0f / (NearZ-FarZ);
2749     // Note: This is recorded on the stack
2750     XMVECTOR rMem = {
2751         2.0f / ViewWidth,
2752         2.0f / ViewHeight,
2753         fRange,
2754         fRange * NearZ
2755     };
2756     // Copy from memory to SSE register
2757     XMVECTOR vValues = rMem;
2758     XMVECTOR vTemp = _mm_setzero_ps(); 
2759     // Copy x only
2760     vTemp = _mm_move_ss(vTemp,vValues);
2761     // 2.0f / ViewWidth,0,0,0
2762     M.r[0] = vTemp;
2763     // 0,2.0f / ViewHeight,0,0
2764     vTemp = vValues;
2765     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2766     M.r[1] = vTemp;
2767     // x=fRange,y=fRange * NearZ,0,1.0f
2768     vTemp = _mm_setzero_ps();
2769     vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2));
2770     // 0,0,fRange,0.0f
2771     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,0,0,0));
2772     M.r[2] = vTemp;
2773     // 0,0,fRange * NearZ,1.0f
2774     vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,1,0,0));
2775     M.r[3] = vTemp;
2776     return M;
2777 #else // _XM_VMX128_INTRINSICS_
2778 #endif // _XM_VMX128_INTRINSICS_
2779 }
2780
2781 //------------------------------------------------------------------------------
2782
2783 XMFINLINE XMMATRIX XMMatrixOrthographicOffCenterLH
2784 (
2785     FLOAT ViewLeft, 
2786     FLOAT ViewRight, 
2787     FLOAT ViewBottom, 
2788     FLOAT ViewTop, 
2789     FLOAT NearZ, 
2790     FLOAT FarZ
2791 )
2792 {
2793 #if defined(_XM_NO_INTRINSICS_)
2794
2795     FLOAT    ReciprocalWidth;
2796     FLOAT    ReciprocalHeight;
2797     XMMATRIX M;
2798
2799     XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2800     XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2801     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2802
2803     ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2804     ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2805
2806     M.r[0] = XMVectorSet(ReciprocalWidth + ReciprocalWidth, 0.0f, 0.0f, 0.0f);
2807     M.r[1] = XMVectorSet(0.0f, ReciprocalHeight + ReciprocalHeight, 0.0f, 0.0f);
2808     M.r[2] = XMVectorSet(0.0f, 0.0f, 1.0f / (FarZ - NearZ), 0.0f);
2809     M.r[3] = XMVectorSet(-(ViewLeft + ViewRight) * ReciprocalWidth, 
2810                          -(ViewTop + ViewBottom) * ReciprocalHeight,
2811                          -M.r[2].vector4_f32[2] * NearZ,
2812                          1.0f);
2813
2814     return M;
2815
2816 #elif defined(_XM_SSE_INTRINSICS_)
2817     XMMATRIX M;
2818     FLOAT fReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2819     FLOAT fReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2820     FLOAT fRange = 1.0f / (FarZ-NearZ);
2821     // Note: This is recorded on the stack
2822     XMVECTOR rMem = {
2823         fReciprocalWidth,
2824         fReciprocalHeight,
2825         fRange,
2826         1.0f
2827     };
2828     XMVECTOR rMem2 = {
2829         -(ViewLeft + ViewRight),
2830         -(ViewTop + ViewBottom),
2831         -NearZ,
2832         1.0f
2833     };
2834     // Copy from memory to SSE register
2835     XMVECTOR vValues = rMem;
2836     XMVECTOR vTemp = _mm_setzero_ps(); 
2837     // Copy x only
2838     vTemp = _mm_move_ss(vTemp,vValues);
2839     // fReciprocalWidth*2,0,0,0
2840     vTemp = _mm_add_ss(vTemp,vTemp);
2841     M.r[0] = vTemp;
2842     // 0,fReciprocalHeight*2,0,0
2843     vTemp = vValues;
2844     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2845     vTemp = _mm_add_ps(vTemp,vTemp);
2846     M.r[1] = vTemp;
2847     // 0,0,fRange,0.0f
2848     vTemp = vValues;
2849     vTemp = _mm_and_ps(vTemp,g_XMMaskZ);
2850     M.r[2] = vTemp;
2851     // -(ViewLeft + ViewRight)*fReciprocalWidth,-(ViewTop + ViewBottom)*fReciprocalHeight,fRange*-NearZ,1.0f
2852     vValues = _mm_mul_ps(vValues,rMem2);
2853     M.r[3] = vValues;
2854     return M;
2855 #else // _XM_VMX128_INTRINSICS_
2856 #endif // _XM_VMX128_INTRINSICS_
2857 }
2858
2859 //------------------------------------------------------------------------------
2860
2861 XMFINLINE XMMATRIX XMMatrixOrthographicOffCenterRH
2862 (
2863     FLOAT ViewLeft, 
2864     FLOAT ViewRight, 
2865     FLOAT ViewBottom, 
2866     FLOAT ViewTop, 
2867     FLOAT NearZ, 
2868     FLOAT FarZ
2869 )
2870 {
2871 #if defined(_XM_NO_INTRINSICS_)
2872
2873     FLOAT    ReciprocalWidth;
2874     FLOAT    ReciprocalHeight;
2875     XMMATRIX M;
2876
2877     XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2878     XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2879     XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2880
2881     ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2882     ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2883
2884     M.r[0] = XMVectorSet(ReciprocalWidth + ReciprocalWidth, 0.0f, 0.0f, 0.0f);
2885     M.r[1] = XMVectorSet(0.0f, ReciprocalHeight + ReciprocalHeight, 0.0f, 0.0f);
2886     M.r[2] = XMVectorSet(0.0f, 0.0f, 1.0f / (NearZ - FarZ), 0.0f);
2887     M.r[3] = XMVectorSet(-(ViewLeft + ViewRight) * ReciprocalWidth, 
2888                          -(ViewTop + ViewBottom) * ReciprocalHeight,
2889                          M.r[2].vector4_f32[2] * NearZ,
2890                          1.0f);
2891
2892     return M;
2893
2894 #elif defined(_XM_SSE_INTRINSICS_)
2895     XMMATRIX M;
2896     FLOAT fReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2897     FLOAT fReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2898     FLOAT fRange = 1.0f / (NearZ-FarZ);
2899     // Note: This is recorded on the stack
2900     XMVECTOR rMem = {
2901         fReciprocalWidth,
2902         fReciprocalHeight,
2903         fRange,
2904         1.0f
2905     };
2906     XMVECTOR rMem2 = {
2907         -(ViewLeft + ViewRight),
2908         -(ViewTop + ViewBottom),
2909         NearZ,
2910         1.0f
2911     };
2912     // Copy from memory to SSE register
2913     XMVECTOR vValues = rMem;
2914     XMVECTOR vTemp = _mm_setzero_ps(); 
2915     // Copy x only
2916     vTemp = _mm_move_ss(vTemp,vValues);
2917     // fReciprocalWidth*2,0,0,0
2918     vTemp = _mm_add_ss(vTemp,vTemp);
2919     M.r[0] = vTemp;
2920     // 0,fReciprocalHeight*2,0,0
2921     vTemp = vValues;
2922     vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2923     vTemp = _mm_add_ps(vTemp,vTemp);
2924     M.r[1] = vTemp;
2925     // 0,0,fRange,0.0f
2926     vTemp = vValues;
2927     vTemp = _mm_and_ps(vTemp,g_XMMaskZ);
2928     M.r[2] = vTemp;
2929     // -(ViewLeft + ViewRight)*fReciprocalWidth,-(ViewTop + ViewBottom)*fReciprocalHeight,fRange*-NearZ,1.0f
2930     vValues = _mm_mul_ps(vValues,rMem2);
2931     M.r[3] = vValues;
2932     return M;
2933 #else // _XM_VMX128_INTRINSICS_
2934 #endif // _XM_VMX128_INTRINSICS_
2935 }
2936
2937
2938 #ifdef __cplusplus
2939
2940 /****************************************************************************
2941  *
2942  * XMMATRIX operators and methods
2943  *
2944  ****************************************************************************/
2945
2946 //------------------------------------------------------------------------------
2947
2948 XMFINLINE _XMMATRIX::_XMMATRIX
2949 (
2950     FXMVECTOR R0,
2951     FXMVECTOR R1,
2952     FXMVECTOR R2,
2953     CXMVECTOR R3
2954 )
2955 {
2956     r[0] = R0;
2957     r[1] = R1;
2958     r[2] = R2;
2959     r[3] = R3;
2960 }
2961
2962 //------------------------------------------------------------------------------
2963
2964 XMFINLINE _XMMATRIX::_XMMATRIX
2965 (
2966     FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03,
2967     FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13,
2968     FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23,
2969     FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33
2970 )
2971 {
2972     r[0] = XMVectorSet(m00, m01, m02, m03);
2973     r[1] = XMVectorSet(m10, m11, m12, m13);
2974     r[2] = XMVectorSet(m20, m21, m22, m23);
2975     r[3] = XMVectorSet(m30, m31, m32, m33);
2976 }
2977
2978 //------------------------------------------------------------------------------
2979
2980 XMFINLINE _XMMATRIX::_XMMATRIX
2981 (
2982     CONST FLOAT* pArray
2983 )
2984 {
2985     r[0] = XMLoadFloat4((const XMFLOAT4*)pArray);
2986     r[1] = XMLoadFloat4((const XMFLOAT4*)(pArray + 4));
2987     r[2] = XMLoadFloat4((const XMFLOAT4*)(pArray + 8));
2988     r[3] = XMLoadFloat4((const XMFLOAT4*)(pArray + 12));
2989 }
2990
2991 //------------------------------------------------------------------------------
2992
2993 XMFINLINE _XMMATRIX& _XMMATRIX::operator=
2994 (
2995     CONST _XMMATRIX& M
2996 )
2997 {
2998     r[0] = M.r[0];
2999     r[1] = M.r[1];
3000     r[2] = M.r[2];
3001     r[3] = M.r[3];
3002     return *this;
3003 }
3004
3005 //------------------------------------------------------------------------------
3006
3007 #ifndef XM_NO_OPERATOR_OVERLOADS
3008
3009 #if !defined(_XBOX_VER) && defined(_XM_ISVS2005_) && defined(_XM_X64_)
3010 #pragma warning(push)
3011 #pragma warning(disable : 4328)
3012 #endif
3013
3014 XMFINLINE _XMMATRIX& _XMMATRIX::operator*=
3015 (
3016     CONST _XMMATRIX& M
3017 )
3018 {
3019     *this = XMMatrixMultiply(*this, M);
3020     return *this;
3021 }
3022
3023 //------------------------------------------------------------------------------
3024
3025 XMFINLINE _XMMATRIX _XMMATRIX::operator* 
3026 (
3027     CONST _XMMATRIX& M
3028 ) CONST
3029 {
3030     return XMMatrixMultiply(*this, M);
3031 }
3032
3033 #if !defined(_XBOX_VER) && defined(_XM_ISVS2005_) && defined(_XM_X64_)
3034 #pragma warning(pop)
3035 #endif
3036
3037 #endif // !XM_NO_OPERATOR_OVERLOADS
3038
3039 /****************************************************************************
3040  *
3041  * XMFLOAT3X3 operators
3042  *
3043  ****************************************************************************/
3044
3045 //------------------------------------------------------------------------------
3046
3047 XMFINLINE _XMFLOAT3X3::_XMFLOAT3X3
3048 (
3049     FLOAT m00, FLOAT m01, FLOAT m02,
3050     FLOAT m10, FLOAT m11, FLOAT m12,
3051     FLOAT m20, FLOAT m21, FLOAT m22
3052 )
3053 {
3054     m[0][0] = m00;
3055     m[0][1] = m01;
3056     m[0][2] = m02;
3057
3058     m[1][0] = m10;
3059     m[1][1] = m11;
3060     m[1][2] = m12;
3061
3062     m[2][0] = m20;
3063     m[2][1] = m21;
3064     m[2][2] = m22;
3065 }
3066
3067 //------------------------------------------------------------------------------
3068
3069 XMFINLINE _XMFLOAT3X3::_XMFLOAT3X3
3070 (
3071     CONST FLOAT* pArray
3072 )
3073 {
3074     UINT Row;
3075     UINT Column;
3076
3077     for (Row = 0; Row < 3; Row++)
3078     {
3079         for (Column = 0; Column < 3; Column++)
3080         {
3081             m[Row][Column] = pArray[Row * 3 + Column];
3082         }
3083     }
3084 }
3085
3086 //------------------------------------------------------------------------------
3087
3088 XMFINLINE _XMFLOAT3X3& _XMFLOAT3X3::operator=
3089 (
3090     CONST _XMFLOAT3X3& Float3x3
3091 )
3092 {
3093     _11 = Float3x3._11;
3094     _12 = Float3x3._12;
3095     _13 = Float3x3._13;
3096     _21 = Float3x3._21;
3097     _22 = Float3x3._22;
3098     _23 = Float3x3._23;
3099     _31 = Float3x3._31;
3100     _32 = Float3x3._32;
3101     _33 = Float3x3._33;
3102
3103     return *this;
3104 }
3105
3106 /****************************************************************************
3107  *
3108  * XMFLOAT4X3 operators
3109  *
3110  ****************************************************************************/
3111
3112 //------------------------------------------------------------------------------
3113
3114 XMFINLINE _XMFLOAT4X3::_XMFLOAT4X3
3115 (
3116     FLOAT m00, FLOAT m01, FLOAT m02,
3117     FLOAT m10, FLOAT m11, FLOAT m12,
3118     FLOAT m20, FLOAT m21, FLOAT m22,
3119     FLOAT m30, FLOAT m31, FLOAT m32
3120 )
3121 {
3122     m[0][0] = m00;
3123     m[0][1] = m01;
3124     m[0][2] = m02;
3125
3126     m[1][0] = m10;
3127     m[1][1] = m11;
3128     m[1][2] = m12;
3129
3130     m[2][0] = m20;
3131     m[2][1] = m21;
3132     m[2][2] = m22;
3133
3134     m[3][0] = m30;
3135     m[3][1] = m31;
3136     m[3][2] = m32;
3137 }
3138
3139 //------------------------------------------------------------------------------
3140
3141 XMFINLINE _XMFLOAT4X3::_XMFLOAT4X3
3142 (
3143     CONST FLOAT* pArray
3144 )
3145 {
3146     UINT Row;
3147     UINT Column;
3148
3149     for (Row = 0; Row < 4; Row++)
3150     {
3151         for (Column = 0; Column < 3; Column++)
3152         {
3153             m[Row][Column] = pArray[Row * 3 + Column];
3154         }
3155     }
3156 }
3157
3158 //------------------------------------------------------------------------------
3159
3160 XMFINLINE _XMFLOAT4X3& _XMFLOAT4X3::operator=
3161 (
3162     CONST _XMFLOAT4X3& Float4x3
3163 )
3164 {
3165     XMVECTOR V1 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._11);
3166     XMVECTOR V2 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._22);
3167     XMVECTOR V3 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._33);
3168
3169     XMStoreFloat4((XMFLOAT4*)&_11, V1);
3170     XMStoreFloat4((XMFLOAT4*)&_22, V2);
3171     XMStoreFloat4((XMFLOAT4*)&_33, V3);
3172
3173     return *this;
3174 }
3175
3176 //------------------------------------------------------------------------------
3177
3178 XMFINLINE XMFLOAT4X3A& XMFLOAT4X3A::operator=
3179 (
3180     CONST XMFLOAT4X3A& Float4x3
3181 )
3182 {
3183     XMVECTOR V1 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._11);
3184     XMVECTOR V2 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._22);
3185     XMVECTOR V3 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._33);
3186
3187     XMStoreFloat4A((XMFLOAT4A*)&_11, V1);
3188     XMStoreFloat4A((XMFLOAT4A*)&_22, V2);
3189     XMStoreFloat4A((XMFLOAT4A*)&_33, V3);
3190
3191     return *this;
3192 }
3193
3194 /****************************************************************************
3195  *
3196  * XMFLOAT4X4 operators
3197  *
3198  ****************************************************************************/
3199
3200 //------------------------------------------------------------------------------
3201
3202 XMFINLINE _XMFLOAT4X4::_XMFLOAT4X4
3203 (
3204     FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03,
3205     FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13,
3206     FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23,
3207     FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33
3208 )
3209 {
3210     m[0][0] = m00;
3211     m[0][1] = m01;
3212     m[0][2] = m02;
3213     m[0][3] = m03;
3214
3215     m[1][0] = m10;
3216     m[1][1] = m11;
3217     m[1][2] = m12;
3218     m[1][3] = m13;
3219
3220     m[2][0] = m20;
3221     m[2][1] = m21;
3222     m[2][2] = m22;
3223     m[2][3] = m23;
3224
3225     m[3][0] = m30;
3226     m[3][1] = m31;
3227     m[3][2] = m32;
3228     m[3][3] = m33;
3229 }
3230
3231 //------------------------------------------------------------------------------
3232
3233 XMFINLINE _XMFLOAT4X4::_XMFLOAT4X4
3234 (
3235     CONST FLOAT* pArray
3236 )
3237 {
3238     UINT Row;
3239     UINT Column;
3240
3241     for (Row = 0; Row < 4; Row++)
3242     {
3243         for (Column = 0; Column < 4; Column++)
3244         {
3245             m[Row][Column] = pArray[Row * 4 + Column];
3246         }
3247     }
3248 }
3249
3250 //------------------------------------------------------------------------------
3251
3252 XMFINLINE _XMFLOAT4X4& _XMFLOAT4X4::operator=
3253 (
3254     CONST _XMFLOAT4X4& Float4x4
3255 )
3256 {
3257     XMVECTOR V1 = XMLoadFloat4((const XMFLOAT4*)&Float4x4._11);
3258     XMVECTOR V2 = XMLoadFloat4((const XMFLOAT4*)&Float4x4._21);
3259     XMVECTOR V3 = XMLoadFloat4((const XMFLOAT4*)&Float4x4._31);
3260     XMVECTOR V4 = XMLoadFloat4((const XMFLOAT4*)&Float4x4._41);
3261
3262     XMStoreFloat4((XMFLOAT4*)&_11, V1);
3263     XMStoreFloat4((XMFLOAT4*)&_21, V2);
3264     XMStoreFloat4((XMFLOAT4*)&_31, V3);
3265     XMStoreFloat4((XMFLOAT4*)&_41, V4);
3266
3267     return *this;
3268 }
3269
3270 //------------------------------------------------------------------------------
3271
3272 XMFINLINE XMFLOAT4X4A& XMFLOAT4X4A::operator=
3273 (
3274     CONST XMFLOAT4X4A& Float4x4
3275 )
3276 {
3277     XMVECTOR V1 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x4._11);
3278     XMVECTOR V2 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x4._21);
3279     XMVECTOR V3 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x4._31);
3280     XMVECTOR V4 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x4._41);
3281
3282     XMStoreFloat4A((XMFLOAT4A*)&_11, V1);
3283     XMStoreFloat4A((XMFLOAT4A*)&_21, V2);
3284     XMStoreFloat4A((XMFLOAT4A*)&_31, V3);
3285     XMStoreFloat4A((XMFLOAT4A*)&_41, V4);
3286
3287     return *this;
3288 }
3289
3290 #endif // __cplusplus
3291
3292 #endif // __XNAMATHMATRIX_INL__
3293