1 /************************************************************************
3 * xnamathmatrix.inl -- SIMD C++ Math library for Windows and Xbox 360 *
6 * Copyright (c) Microsoft Corp. All rights reserved. *
8 ************************************************************************/
10 #if defined(_MSC_VER) && (_MSC_VER > 1000)
14 #ifndef __XNAMATHMATRIX_INL__
15 #define __XNAMATHMATRIX_INL__
17 /****************************************************************************
21 ****************************************************************************/
23 //------------------------------------------------------------------------------
24 // Comparison operations
25 //------------------------------------------------------------------------------
27 //------------------------------------------------------------------------------
29 // Return TRUE if any entry in the matrix is NaN
30 XMFINLINE BOOL XMMatrixIsNaN
35 #if defined(_XM_NO_INTRINSICS_)
40 pWork = (const UINT *)(&M.m[0][0]);
42 // Fetch value into integer unit
46 // NaN is 0x7F800001 through 0x7FFFFFFF inclusive
48 if (uTest<0x007FFFFFU) {
51 ++pWork; // Next entry
53 return (i!=0); // i == 0 if nothing matched
54 #elif defined(_XM_SSE_INTRINSICS_)
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);
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);
75 //------------------------------------------------------------------------------
77 // Return TRUE if any entry in the matrix is +/-INF
78 XMFINLINE BOOL XMMatrixIsInfinite
83 #if defined(_XM_NO_INTRINSICS_)
88 pWork = (const UINT *)(&M.m[0][0]);
90 // Fetch value into integer unit
95 if (uTest==0x7F800000U) {
98 ++pWork; // Next entry
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_
122 //------------------------------------------------------------------------------
124 // Return TRUE if the XMMatrix is equal to identity
125 XMFINLINE BOOL XMMatrixIsIdentity
130 #if defined(_XM_NO_INTRINSICS_)
131 unsigned int uOne, uZero;
132 const unsigned int *pWork;
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
144 uOne |= pWork[5]^0x3F800000U;
150 uOne |= pWork[10]^0x3F800000U;
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
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_
175 //------------------------------------------------------------------------------
176 // Computation operations
177 //------------------------------------------------------------------------------
179 //------------------------------------------------------------------------------
180 // Perform a 4x4 matrix multiply by a 4x4 matrix
181 XMFINLINE XMMATRIX XMMatrixMultiply
187 #if defined(_XM_NO_INTRINSICS_)
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
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);
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);
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);
225 #elif defined(_XM_SSE_INTRINSICS_)
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);
244 // Repeat for the other 3 rows
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);
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);
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);
285 #else // _XM_VMX128_INTRINSICS_
286 #endif // _XM_VMX128_INTRINSICS_
289 //------------------------------------------------------------------------------
291 XMFINLINE XMMATRIX XMMatrixMultiplyTranspose
297 #if defined(_XM_NO_INTRINSICS_)
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
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);
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);
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);
335 #elif defined(_XM_SSE_INTRINSICS_)
338 Product = XMMatrixMultiply(M1, M2);
339 Result = XMMatrixTranspose(Product);
341 #else // _XM_VMX128_INTRINSICS_
342 #endif // _XM_VMX128_INTRINSICS_
345 //------------------------------------------------------------------------------
347 XMFINLINE XMMATRIX XMMatrixTranspose
352 #if defined(_XM_NO_INTRINSICS_)
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
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
376 #elif defined(_XM_SSE_INTRINSICS_)
378 XMVECTOR vTemp1 = _mm_shuffle_ps(M.r[0],M.r[1],_MM_SHUFFLE(1,0,1,0));
380 XMVECTOR vTemp3 = _mm_shuffle_ps(M.r[0],M.r[1],_MM_SHUFFLE(3,2,3,2));
382 XMVECTOR vTemp2 = _mm_shuffle_ps(M.r[2],M.r[3],_MM_SHUFFLE(1,0,1,0));
384 XMVECTOR vTemp4 = _mm_shuffle_ps(M.r[2],M.r[3],_MM_SHUFFLE(3,2,3,2));
388 mResult.r[0] = _mm_shuffle_ps(vTemp1, vTemp2,_MM_SHUFFLE(2,0,2,0));
390 mResult.r[1] = _mm_shuffle_ps(vTemp1, vTemp2,_MM_SHUFFLE(3,1,3,1));
392 mResult.r[2] = _mm_shuffle_ps(vTemp3, vTemp4,_MM_SHUFFLE(2,0,2,0));
394 mResult.r[3] = _mm_shuffle_ps(vTemp3, vTemp4,_MM_SHUFFLE(3,1,3,1));
396 #else // _XM_VMX128_INTRINSICS_
397 #endif // _XM_VMX128_INTRINSICS_
400 //------------------------------------------------------------------------------
401 // Return the inverse and the determinant of a 4x4 matrix
402 XMINLINE XMMATRIX XMMatrixInverse
404 XMVECTOR* pDeterminant,
408 #if defined(_XM_NO_INTRINSICS_)
413 XMVECTOR C0, C1, C2, C3, C4, C5, C6, C7;
414 XMVECTOR V0[4], V1[4];
415 XMVECTOR Determinant;
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};
441 MT = XMMatrixTranspose(M);
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);
450 D0 = XMVectorMultiply(V0[0], V1[0]);
451 D1 = XMVectorMultiply(V0[1], V1[1]);
452 D2 = XMVectorMultiply(V0[2], V1[2]);
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);
461 D0 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], D0);
462 D1 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], D1);
463 D2 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], D2);
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);
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]);
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);
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);
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);
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);
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);
516 Determinant = XMVector4Dot(R.r[0], MT.r[0]);
519 *pDeterminant = Determinant;
521 Reciprocal = XMVectorReciprocal(Determinant);
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);
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));
539 XMVECTOR D0 = _mm_mul_ps(V00,V10);
540 XMVECTOR D1 = _mm_mul_ps(V01,V11);
541 XMVECTOR D2 = _mm_mul_ps(V02,V12);
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));
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));
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);
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));
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);
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));
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);
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]);
637 *pDeterminant = vTemp;
638 vTemp = _mm_div_ps(g_XMOne,vTemp);
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);
645 #else // _XM_VMX128_INTRINSICS_
646 #endif // _XM_VMX128_INTRINSICS_
649 //------------------------------------------------------------------------------
651 XMINLINE XMVECTOR XMMatrixDeterminant
656 #if defined(_XM_NO_INTRINSICS_)
658 XMVECTOR V0, V1, V2, V3, V4, V5;
659 XMVECTOR P0, P1, P2, R, S;
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};
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);
673 P0 = XMVectorMultiply(V0, V1);
674 P1 = XMVectorMultiply(V2, V3);
675 P2 = XMVectorMultiply(V4, V5);
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);
684 P0 = XMVectorNegativeMultiplySubtract(V0, V1, P0);
685 P1 = XMVectorNegativeMultiplySubtract(V2, V3, P1);
686 P2 = XMVectorNegativeMultiplySubtract(V4, V5, P2);
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);
692 S = XMVectorMultiply(M.r[0], Sign);
693 R = XMVectorMultiply(V0, P0);
694 R = XMVectorNegativeMultiplySubtract(V1, P1, R);
695 R = XMVectorMultiplyAdd(V2, P2, R);
697 Result = XMVector4Dot(S, R);
701 #elif defined(_XM_SSE_INTRINSICS_)
702 XMVECTOR V0, V1, V2, V3, V4, V5;
703 XMVECTOR P0, P1, P2, R, S;
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};
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);
717 P0 = _mm_mul_ps(V0, V1);
718 P1 = _mm_mul_ps(V2, V3);
719 P2 = _mm_mul_ps(V4, V5);
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);
728 P0 = XMVectorNegativeMultiplySubtract(V0, V1, P0);
729 P1 = XMVectorNegativeMultiplySubtract(V2, V3, P1);
730 P2 = XMVectorNegativeMultiplySubtract(V4, V5, P2);
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);
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);
741 Result = XMVector4Dot(S, R);
745 #else // _XM_VMX128_INTRINSICS_
746 #endif // _XM_VMX128_INTRINSICS_
749 #undef XMRANKDECOMPOSE
750 #undef XM_DECOMP_EPSILON
752 #define XMRANKDECOMPOSE(a, b, c, x, y, z) \
802 #define XM_DECOMP_EPSILON 0.0001f
804 XMINLINE BOOL XMMatrixDecompose
807 XMVECTOR *outRotQuat,
814 XMVECTOR *ppvBasis[3];
817 static const XMVECTOR *pvCanonicalBasis[3] = {
823 XMASSERT( outScale != NULL );
824 XMASSERT( outRotQuat != NULL );
825 XMASSERT( outTrans != NULL );
827 // Get the translation
828 outTrans[0] = M.r[3];
830 ppvBasis[0] = &matTemp.r[0];
831 ppvBasis[1] = &matTemp.r[1];
832 ppvBasis[2] = &matTemp.r[2];
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;
839 pfScales = (FLOAT *)outScale;
841 XMVectorGetXPtr(&pfScales[0],XMVector3Length(ppvBasis[0][0]));
842 XMVectorGetXPtr(&pfScales[1],XMVector3Length(ppvBasis[1][0]));
843 XMVectorGetXPtr(&pfScales[2],XMVector3Length(ppvBasis[2][0]));
846 XMRANKDECOMPOSE(a, b, c, pfScales[0], pfScales[1], pfScales[2])
848 if(pfScales[a] < XM_DECOMP_EPSILON)
850 ppvBasis[a][0] = pvCanonicalBasis[a][0];
852 ppvBasis[a][0] = XMVector3Normalize(ppvBasis[a][0]);
854 if(pfScales[b] < XM_DECOMP_EPSILON)
857 FLOAT fAbsX, fAbsY, fAbsZ;
859 fAbsX = fabsf(XMVectorGetX(ppvBasis[a][0]));
860 fAbsY = fabsf(XMVectorGetY(ppvBasis[a][0]));
861 fAbsZ = fabsf(XMVectorGetZ(ppvBasis[a][0]));
863 XMRANKDECOMPOSE(aa, bb, cc, fAbsX, fAbsY, fAbsZ)
865 ppvBasis[b][0] = XMVector3Cross(ppvBasis[a][0],pvCanonicalBasis[cc][0]);
868 ppvBasis[b][0] = XMVector3Normalize(ppvBasis[b][0]);
870 if(pfScales[c] < XM_DECOMP_EPSILON)
872 ppvBasis[c][0] = XMVector3Cross(ppvBasis[a][0],ppvBasis[b][0]);
875 ppvBasis[c][0] = XMVector3Normalize(ppvBasis[c][0]);
877 fDet = XMVectorGetX(XMMatrixDeterminant(matTemp));
879 // use Kramer's rule to check for handedness of coordinate system
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]);
892 if(XM_DECOMP_EPSILON < fDet)
894 // Non-SRT matrix encountered
898 // generate the quaternion from the matrix
899 outRotQuat[0] = XMQuaternionRotationMatrix(matTemp);
903 #undef XMRANKDECOMPOSE
904 #undef XM_DECOMP_EPSILON
906 //------------------------------------------------------------------------------
907 // Transformation operations
908 //------------------------------------------------------------------------------
910 //------------------------------------------------------------------------------
912 XMFINLINE XMMATRIX XMMatrixIdentity()
914 #if defined(_XM_NO_INTRINSICS_)
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;
923 #elif defined(_XM_SSE_INTRINSICS_)
925 M.r[0] = g_XMIdentityR0;
926 M.r[1] = g_XMIdentityR1;
927 M.r[2] = g_XMIdentityR2;
928 M.r[3] = g_XMIdentityR3;
930 #else // _XM_VMX128_INTRINSICS_
931 #endif // _XM_VMX128_INTRINSICS_
934 //------------------------------------------------------------------------------
936 XMFINLINE XMMATRIX XMMatrixSet
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
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);
954 //------------------------------------------------------------------------------
956 XMFINLINE XMMATRIX XMMatrixTranslation
963 #if defined(_XM_NO_INTRINSICS_)
988 #elif defined(_XM_SSE_INTRINSICS_)
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);
995 #else // _XM_VMX128_INTRINSICS_
996 #endif // _XM_VMX128_INTRINSICS_
1000 //------------------------------------------------------------------------------
1002 XMFINLINE XMMATRIX XMMatrixTranslationFromVector
1007 #if defined(_XM_NO_INTRINSICS_)
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];
1031 #elif defined(_XM_SSE_INTRINSICS_)
1032 XMVECTOR vTemp = _mm_and_ps(Offset,g_XMMask3);
1033 vTemp = _mm_or_ps(vTemp,g_XMIdentityR3);
1035 M.r[0] = g_XMIdentityR0;
1036 M.r[1] = g_XMIdentityR1;
1037 M.r[2] = g_XMIdentityR2;
1040 #else // _XM_VMX128_INTRINSICS_
1041 #endif // _XM_VMX128_INTRINSICS_
1044 //------------------------------------------------------------------------------
1046 XMFINLINE XMMATRIX XMMatrixScaling
1053 #if defined(_XM_NO_INTRINSICS_)
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);
1061 M.r[3] = g_XMIdentityR3.v;
1065 #elif defined(_XM_SSE_INTRINSICS_)
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;
1072 #elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS)
1073 #endif // _XM_VMX128_INTRINSICS_
1076 //------------------------------------------------------------------------------
1078 XMFINLINE XMMATRIX XMMatrixScalingFromVector
1083 #if defined(_XM_NO_INTRINSICS_)
1085 M.m[0][0] = Scale.vector4_f32[0];
1091 M.m[1][1] = Scale.vector4_f32[1];
1097 M.m[2][2] = Scale.vector4_f32[2];
1106 #elif defined(_XM_SSE_INTRINSICS_)
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;
1113 #else // _XM_VMX128_INTRINSICS_
1114 #endif // _XM_VMX128_INTRINSICS_
1117 //------------------------------------------------------------------------------
1119 XMINLINE XMMATRIX XMMatrixRotationX
1124 #if defined(_XM_NO_INTRINSICS_)
1127 FLOAT fSinAngle = sinf(Angle);
1128 FLOAT fCosAngle = cosf(Angle);
1136 M.m[1][1] = fCosAngle;
1137 M.m[1][2] = fSinAngle;
1141 M.m[2][1] = -fSinAngle;
1142 M.m[2][2] = fCosAngle;
1151 #elif defined(_XM_SSE_INTRINSICS_)
1152 FLOAT SinAngle = sinf(Angle);
1153 FLOAT CosAngle = cosf(Angle);
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));
1160 M.r[0] = g_XMIdentityR0;
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);
1167 M.r[3] = g_XMIdentityR3;
1169 #else // _XM_VMX128_INTRINSICS_
1170 #endif // _XM_VMX128_INTRINSICS_
1173 //------------------------------------------------------------------------------
1175 XMINLINE XMMATRIX XMMatrixRotationY
1180 #if defined(_XM_NO_INTRINSICS_)
1183 FLOAT fSinAngle = sinf(Angle);
1184 FLOAT fCosAngle = cosf(Angle);
1186 M.m[0][0] = fCosAngle;
1188 M.m[0][2] = -fSinAngle;
1196 M.m[2][0] = fSinAngle;
1198 M.m[2][2] = fCosAngle;
1206 #elif defined(_XM_SSE_INTRINSICS_)
1207 FLOAT SinAngle = sinf(Angle);
1208 FLOAT CosAngle = cosf(Angle);
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));
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);
1222 M.r[3] = g_XMIdentityR3;
1224 #else // _XM_VMX128_INTRINSICS_
1225 #endif // _XM_VMX128_INTRINSICS_
1228 //------------------------------------------------------------------------------
1230 XMINLINE XMMATRIX XMMatrixRotationZ
1235 #if defined(_XM_NO_INTRINSICS_)
1238 FLOAT fSinAngle = sinf(Angle);
1239 FLOAT fCosAngle = cosf(Angle);
1241 M.m[0][0] = fCosAngle;
1242 M.m[0][1] = fSinAngle;
1246 M.m[1][0] = -fSinAngle;
1247 M.m[1][1] = fCosAngle;
1262 #elif defined(_XM_SSE_INTRINSICS_)
1263 FLOAT SinAngle = sinf(Angle);
1264 FLOAT CosAngle = cosf(Angle);
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);
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);
1277 M.r[2] = g_XMIdentityR2;
1278 M.r[3] = g_XMIdentityR3;
1280 #else // _XM_VMX128_INTRINSICS_
1281 #endif // _XM_VMX128_INTRINSICS_
1284 //------------------------------------------------------------------------------
1286 XMINLINE XMMATRIX XMMatrixRotationRollPitchYaw
1296 Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f);
1297 M = XMMatrixRotationRollPitchYawFromVector(Angles);
1302 //------------------------------------------------------------------------------
1304 XMINLINE XMMATRIX XMMatrixRotationRollPitchYawFromVector
1306 FXMVECTOR Angles // <Pitch, Yaw, Roll, undefined>
1312 Q = XMQuaternionRotationRollPitchYawFromVector(Angles);
1313 M = XMMatrixRotationQuaternion(Q);
1318 //------------------------------------------------------------------------------
1320 XMINLINE XMMATRIX XMMatrixRotationNormal
1322 FXMVECTOR NormalAxis,
1326 #if defined(_XM_NO_INTRINSICS_)
1329 XMVECTOR V0, V1, V2;
1330 XMVECTOR R0, R1, R2;
1331 XMVECTOR C0, C1, C2;
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};
1341 FLOAT fSinAngle = sinf(Angle);
1342 FLOAT fCosAngle = cosf(Angle);
1344 A = XMVectorSet(fSinAngle, fCosAngle, 1.0f - fCosAngle, 0.0f);
1346 C2 = XMVectorSplatZ(A);
1347 C1 = XMVectorSplatY(A);
1348 C0 = XMVectorSplatX(A);
1350 N0 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleYZXW.v);
1351 N1 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleZXYW.v);
1353 V0 = XMVectorMultiply(C2, N0);
1354 V0 = XMVectorMultiply(V0, N1);
1356 R0 = XMVectorMultiply(C2, NormalAxis);
1357 R0 = XMVectorMultiplyAdd(R0, NormalAxis, C1);
1359 R1 = XMVectorMultiplyAdd(C0, NormalAxis, V0);
1360 R2 = XMVectorNegativeMultiplySubtract(C0, NormalAxis, V0);
1362 V0 = XMVectorSelect(A, R0, g_XMSelect1110.v);
1363 V1 = XMVectorPermute(R1, R2, Permute0Z1Y1Z0X.v);
1364 V2 = XMVectorPermute(R1, R2, Permute0Y1X0Y1X.v);
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;
1373 #elif defined(_XM_SSE_INTRINSICS_)
1375 XMVECTOR V0, V1, V2;
1376 XMVECTOR R0, R1, R2;
1377 XMVECTOR C0, C1, C2;
1380 FLOAT fSinAngle = sinf(Angle);
1381 FLOAT fCosAngle = cosf(Angle);
1383 C2 = _mm_set_ps1(1.0f - fCosAngle);
1384 C1 = _mm_set_ps1(fCosAngle);
1385 C0 = _mm_set_ps1(fSinAngle);
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);
1392 V0 = _mm_mul_ps(C2, N0);
1393 V0 = _mm_mul_ps(V0, N1);
1395 R0 = _mm_mul_ps(C2, NormalAxis);
1396 R0 = _mm_mul_ps(R0, NormalAxis);
1397 R0 = _mm_add_ps(R0, C1);
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);
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);
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));
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));
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));
1424 // M.r[2] = XMVectorPermute(V0, V2, Permute1X1Y0Z0W);
1425 M.r[3] = g_XMIdentityR3;
1427 #else // _XM_VMX128_INTRINSICS_
1428 #endif // _XM_VMX128_INTRINSICS_
1431 //------------------------------------------------------------------------------
1433 XMINLINE XMMATRIX XMMatrixRotationAxis
1439 #if defined(_XM_NO_INTRINSICS_)
1444 XMASSERT(!XMVector3Equal(Axis, XMVectorZero()));
1445 XMASSERT(!XMVector3IsInfinite(Axis));
1447 Normal = XMVector3Normalize(Axis);
1448 M = XMMatrixRotationNormal(Normal, Angle);
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);
1458 #else // _XM_VMX128_INTRINSICS_
1459 #endif // _XM_VMX128_INTRINSICS_
1462 //------------------------------------------------------------------------------
1464 XMFINLINE XMMATRIX XMMatrixRotationQuaternion
1466 FXMVECTOR Quaternion
1469 #if defined(_XM_NO_INTRINSICS_)
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};
1487 Q0 = XMVectorAdd(Quaternion, Quaternion);
1488 Q1 = XMVectorMultiply(Quaternion, Q0);
1490 V0 = XMVectorPermute(Q1, Constant1110, Permute0Y0X0X1W.v);
1491 V1 = XMVectorPermute(Q1, Constant1110, Permute0Z0Z0Y1W.v);
1492 R0 = XMVectorSubtract(Constant1110, V0);
1493 R0 = XMVectorSubtract(R0, V1);
1495 V0 = XMVectorPermute(Quaternion, Quaternion, SwizzleXXYW.v);
1496 V1 = XMVectorPermute(Q0, Q0, SwizzleZYZW.v);
1497 V0 = XMVectorMultiply(V0, V1);
1499 V1 = XMVectorSplatW(Quaternion);
1500 V2 = XMVectorPermute(Q0, Q0, SwizzleYZXW.v);
1501 V1 = XMVectorMultiply(V1, V2);
1503 R1 = XMVectorAdd(V0, V1);
1504 R2 = XMVectorSubtract(V0, V1);
1506 V0 = XMVectorPermute(R1, R2, Permute0Y1X1Y0Z.v);
1507 V1 = XMVectorPermute(R1, R2, Permute0X1Z0X1Z.v);
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;
1516 #elif defined(_XM_SSE_INTRINSICS_)
1519 XMVECTOR V0, V1, V2;
1520 XMVECTOR R0, R1, R2;
1521 static CONST XMVECTORF32 Constant1110 = {1.0f, 1.0f, 1.0f, 0.0f};
1523 Q0 = _mm_add_ps(Quaternion,Quaternion);
1524 Q1 = _mm_mul_ps(Quaternion,Q0);
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);
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);
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);
1547 R1 = _mm_add_ps(V0, V1);
1548 R2 = _mm_sub_ps(V0, V1);
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);
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));
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));
1564 // M.r[1] = XMVectorPermute(R0, V0,Permute1Z0Y1W0W);
1565 Q1 = _mm_shuffle_ps(V1,R0,_MM_SHUFFLE(3,2,1,0));
1567 // M.r[2] = XMVectorPermute(R0, V1,Permute1X1Y0Z0W);
1568 M.r[3] = g_XMIdentityR3;
1570 #else // _XM_VMX128_INTRINSICS_
1571 #endif // _XM_VMX128_INTRINSICS_
1574 //------------------------------------------------------------------------------
1576 XMINLINE XMMATRIX XMMatrixTransformation2D
1578 FXMVECTOR ScalingOrigin,
1579 FLOAT ScalingOrientation,
1581 FXMVECTOR RotationOrigin,
1583 CXMVECTOR Translation
1586 #if defined(_XM_NO_INTRINSICS_)
1590 XMVECTOR NegScalingOrigin;
1591 XMVECTOR VScalingOrigin;
1592 XMMATRIX MScalingOriginI;
1593 XMMATRIX MScalingOrientation;
1594 XMMATRIX MScalingOrientationT;
1596 XMVECTOR VRotationOrigin;
1598 XMVECTOR VTranslation;
1600 // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation *
1601 // MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1603 VScalingOrigin = XMVectorSelect(g_XMSelect1100.v, ScalingOrigin, g_XMSelect1100.v);
1604 NegScalingOrigin = XMVectorNegate(VScalingOrigin);
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);
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);
1626 #elif defined(_XM_SSE_INTRINSICS_)
1629 XMVECTOR NegScalingOrigin;
1630 XMVECTOR VScalingOrigin;
1631 XMMATRIX MScalingOriginI;
1632 XMMATRIX MScalingOrientation;
1633 XMMATRIX MScalingOrientationT;
1635 XMVECTOR VRotationOrigin;
1637 XMVECTOR VTranslation;
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};
1644 VScalingOrigin = _mm_and_ps(ScalingOrigin, Mask2);
1645 NegScalingOrigin = XMVectorNegate(VScalingOrigin);
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);
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);
1667 #else // _XM_VMX128_INTRINSICS_
1668 #endif // _XM_VMX128_INTRINSICS_
1671 //------------------------------------------------------------------------------
1673 XMINLINE XMMATRIX XMMatrixTransformation
1675 FXMVECTOR ScalingOrigin,
1676 FXMVECTOR ScalingOrientationQuaternion,
1678 CXMVECTOR RotationOrigin,
1679 CXMVECTOR RotationQuaternion,
1680 CXMVECTOR Translation
1683 #if defined(_XM_NO_INTRINSICS_)
1686 XMVECTOR NegScalingOrigin;
1687 XMVECTOR VScalingOrigin;
1688 XMMATRIX MScalingOriginI;
1689 XMMATRIX MScalingOrientation;
1690 XMMATRIX MScalingOrientationT;
1692 XMVECTOR VRotationOrigin;
1694 XMVECTOR VTranslation;
1696 // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation *
1697 // MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1699 VScalingOrigin = XMVectorSelect(g_XMSelect1110.v, ScalingOrigin, g_XMSelect1110.v);
1700 NegScalingOrigin = XMVectorNegate(ScalingOrigin);
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);
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);
1721 #elif defined(_XM_SSE_INTRINSICS_)
1723 XMVECTOR NegScalingOrigin;
1724 XMVECTOR VScalingOrigin;
1725 XMMATRIX MScalingOriginI;
1726 XMMATRIX MScalingOrientation;
1727 XMMATRIX MScalingOrientationT;
1729 XMVECTOR VRotationOrigin;
1731 XMVECTOR VTranslation;
1733 // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation *
1734 // MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1736 VScalingOrigin = _mm_and_ps(ScalingOrigin,g_XMMask3);
1737 NegScalingOrigin = XMVectorNegate(ScalingOrigin);
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);
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);
1757 #else // _XM_VMX128_INTRINSICS_
1758 #endif // _XM_VMX128_INTRINSICS_
1761 //------------------------------------------------------------------------------
1763 XMINLINE XMMATRIX XMMatrixAffineTransformation2D
1766 FXMVECTOR RotationOrigin,
1768 FXMVECTOR Translation
1771 #if defined(_XM_NO_INTRINSICS_)
1776 XMVECTOR VRotationOrigin;
1778 XMVECTOR VTranslation;
1780 // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
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);
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);
1796 #elif defined(_XM_SSE_INTRINSICS_)
1800 XMVECTOR VRotationOrigin;
1802 XMVECTOR VTranslation;
1803 static const XMVECTORU32 Mask2 = {0xFFFFFFFFU,0xFFFFFFFFU,0,0};
1804 static const XMVECTORF32 ZW1 = {0,0,1.0f,1.0f};
1806 // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
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);
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);
1821 #else // _XM_VMX128_INTRINSICS_
1822 #endif // _XM_VMX128_INTRINSICS_
1825 //------------------------------------------------------------------------------
1827 XMINLINE XMMATRIX XMMatrixAffineTransformation
1830 FXMVECTOR RotationOrigin,
1831 FXMVECTOR RotationQuaternion,
1832 CXMVECTOR Translation
1835 #if defined(_XM_NO_INTRINSICS_)
1839 XMVECTOR VRotationOrigin;
1841 XMVECTOR VTranslation;
1843 // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
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);
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);
1858 #elif defined(_XM_SSE_INTRINSICS_)
1861 XMVECTOR VRotationOrigin;
1863 XMVECTOR VTranslation;
1865 // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation;
1867 MScaling = XMMatrixScalingFromVector(Scaling);
1868 VRotationOrigin = _mm_and_ps(RotationOrigin,g_XMMask3);
1869 MRotation = XMMatrixRotationQuaternion(RotationQuaternion);
1870 VTranslation = _mm_and_ps(Translation,g_XMMask3);
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);
1879 #else // _XM_VMX128_INTRINSICS_
1880 #endif // _XM_VMX128_INTRINSICS_
1883 //------------------------------------------------------------------------------
1885 XMFINLINE XMMATRIX XMMatrixReflect
1887 FXMVECTOR ReflectionPlane
1890 #if defined(_XM_NO_INTRINSICS_)
1894 XMVECTOR A, B, C, D;
1896 static CONST XMVECTOR NegativeTwo = {-2.0f, -2.0f, -2.0f, 0.0f};
1898 XMASSERT(!XMVector3Equal(ReflectionPlane, XMVectorZero()));
1899 XMASSERT(!XMPlaneIsInfinite(ReflectionPlane));
1901 P = XMPlaneNormalize(ReflectionPlane);
1902 S = XMVectorMultiply(P, NegativeTwo);
1904 A = XMVectorSplatX(P);
1905 B = XMVectorSplatY(P);
1906 C = XMVectorSplatZ(P);
1907 D = XMVectorSplatW(P);
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);
1916 #elif defined(_XM_SSE_INTRINSICS_)
1918 static CONST XMVECTORF32 NegativeTwo = {-2.0f, -2.0f, -2.0f, 0.0f};
1920 XMASSERT(!XMVector3Equal(ReflectionPlane, XMVectorZero()));
1921 XMASSERT(!XMPlaneIsInfinite(ReflectionPlane));
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);
1942 #else // _XM_VMX128_INTRINSICS_
1943 #endif // _XM_VMX128_INTRINSICS_
1946 //------------------------------------------------------------------------------
1948 XMFINLINE XMMATRIX XMMatrixShadow
1950 FXMVECTOR ShadowPlane,
1951 FXMVECTOR LightPosition
1954 #if defined(_XM_NO_INTRINSICS_)
1958 XMVECTOR A, B, C, D;
1960 static CONST XMVECTORU32 Select0001 = {XM_SELECT_0, XM_SELECT_0, XM_SELECT_0, XM_SELECT_1};
1962 XMASSERT(!XMVector3Equal(ShadowPlane, XMVectorZero()));
1963 XMASSERT(!XMPlaneIsInfinite(ShadowPlane));
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);
1982 #elif defined(_XM_SSE_INTRINSICS_)
1984 XMASSERT(!XMVector3Equal(ShadowPlane, XMVectorZero()));
1985 XMASSERT(!XMPlaneIsInfinite(ShadowPlane));
1986 XMVECTOR P = XMPlaneNormalize(ShadowPlane);
1987 XMVECTOR Dot = XMPlaneDot(P,LightPosition);
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
2012 #else // _XM_VMX128_INTRINSICS_
2013 #endif // _XM_VMX128_INTRINSICS_
2016 //------------------------------------------------------------------------------
2017 // View and projection initialization operations
2018 //------------------------------------------------------------------------------
2021 //------------------------------------------------------------------------------
2023 XMFINLINE XMMATRIX XMMatrixLookAtLH
2025 FXMVECTOR EyePosition,
2026 FXMVECTOR FocusPosition,
2027 FXMVECTOR UpDirection
2030 XMVECTOR EyeDirection;
2033 EyeDirection = XMVectorSubtract(FocusPosition, EyePosition);
2034 M = XMMatrixLookToLH(EyePosition, EyeDirection, UpDirection);
2039 //------------------------------------------------------------------------------
2041 XMFINLINE XMMATRIX XMMatrixLookAtRH
2043 FXMVECTOR EyePosition,
2044 FXMVECTOR FocusPosition,
2045 FXMVECTOR UpDirection
2048 XMVECTOR NegEyeDirection;
2051 NegEyeDirection = XMVectorSubtract(EyePosition, FocusPosition);
2052 M = XMMatrixLookToLH(EyePosition, NegEyeDirection, UpDirection);
2057 //------------------------------------------------------------------------------
2059 XMINLINE XMMATRIX XMMatrixLookToLH
2061 FXMVECTOR EyePosition,
2062 FXMVECTOR EyeDirection,
2063 FXMVECTOR UpDirection
2066 #if defined(_XM_NO_INTRINSICS_)
2068 XMVECTOR NegEyePosition;
2069 XMVECTOR D0, D1, D2;
2070 XMVECTOR R0, R1, R2;
2073 XMASSERT(!XMVector3Equal(EyeDirection, XMVectorZero()));
2074 XMASSERT(!XMVector3IsInfinite(EyeDirection));
2075 XMASSERT(!XMVector3Equal(UpDirection, XMVectorZero()));
2076 XMASSERT(!XMVector3IsInfinite(UpDirection));
2078 R2 = XMVector3Normalize(EyeDirection);
2080 R0 = XMVector3Cross(UpDirection, R2);
2081 R0 = XMVector3Normalize(R0);
2083 R1 = XMVector3Cross(R2, R0);
2085 NegEyePosition = XMVectorNegate(EyePosition);
2087 D0 = XMVector3Dot(R0, NegEyePosition);
2088 D1 = XMVector3Dot(R1, NegEyePosition);
2089 D2 = XMVector3Dot(R2, NegEyePosition);
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;
2096 M = XMMatrixTranspose(M);
2100 #elif defined(_XM_SSE_INTRINSICS_)
2103 XMASSERT(!XMVector3Equal(EyeDirection, XMVectorZero()));
2104 XMASSERT(!XMVector3IsInfinite(EyeDirection));
2105 XMASSERT(!XMVector3Equal(UpDirection, XMVectorZero()));
2106 XMASSERT(!XMVector3IsInfinite(UpDirection));
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);
2128 M.r[3] = g_XMIdentityR3;
2129 M = XMMatrixTranspose(M);
2131 #else // _XM_VMX128_INTRINSICS_
2132 #endif // _XM_VMX128_INTRINSICS_
2135 //------------------------------------------------------------------------------
2137 XMFINLINE XMMATRIX XMMatrixLookToRH
2139 FXMVECTOR EyePosition,
2140 FXMVECTOR EyeDirection,
2141 FXMVECTOR UpDirection
2144 XMVECTOR NegEyeDirection;
2147 NegEyeDirection = XMVectorNegate(EyeDirection);
2148 M = XMMatrixLookToLH(EyePosition, NegEyeDirection, UpDirection);
2153 //------------------------------------------------------------------------------
2155 XMFINLINE XMMATRIX XMMatrixPerspectiveLH
2163 #if defined(_XM_NO_INTRINSICS_)
2165 FLOAT TwoNearZ, fRange;
2168 XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2169 XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2170 XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2172 TwoNearZ = NearZ + NearZ;
2173 fRange = FarZ / (FarZ - NearZ);
2174 M.m[0][0] = TwoNearZ / ViewWidth;
2180 M.m[1][1] = TwoNearZ / ViewHeight;
2191 M.m[3][2] = -fRange * NearZ;
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));
2202 FLOAT TwoNearZ = NearZ + NearZ;
2203 FLOAT fRange = FarZ / (FarZ - NearZ);
2204 // Note: This is recorded on the stack
2206 TwoNearZ / ViewWidth,
2207 TwoNearZ / ViewHeight,
2211 // Copy from memory to SSE register
2212 XMVECTOR vValues = rMem;
2213 XMVECTOR vTemp = _mm_setzero_ps();
2215 vTemp = _mm_move_ss(vTemp,vValues);
2216 // TwoNearZ / ViewWidth,0,0,0
2218 // 0,TwoNearZ / ViewHeight,0,0
2220 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2222 // x=fRange,y=-fRange * NearZ,0,1.0f
2223 vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2));
2225 vTemp = _mm_setzero_ps();
2226 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0));
2228 // 0,0,-fRange * NearZ,0
2229 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0));
2233 #else // _XM_VMX128_INTRINSICS_
2234 #endif // _XM_VMX128_INTRINSICS_
2237 //------------------------------------------------------------------------------
2239 XMFINLINE XMMATRIX XMMatrixPerspectiveRH
2247 #if defined(_XM_NO_INTRINSICS_)
2249 FLOAT TwoNearZ, fRange;
2252 XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2253 XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2254 XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2256 TwoNearZ = NearZ + NearZ;
2257 fRange = FarZ / (NearZ - FarZ);
2258 M.m[0][0] = TwoNearZ / ViewWidth;
2264 M.m[1][1] = TwoNearZ / ViewHeight;
2275 M.m[3][2] = fRange * NearZ;
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));
2286 FLOAT TwoNearZ = NearZ + NearZ;
2287 FLOAT fRange = FarZ / (NearZ-FarZ);
2288 // Note: This is recorded on the stack
2290 TwoNearZ / ViewWidth,
2291 TwoNearZ / ViewHeight,
2295 // Copy from memory to SSE register
2296 XMVECTOR vValues = rMem;
2297 XMVECTOR vTemp = _mm_setzero_ps();
2299 vTemp = _mm_move_ss(vTemp,vValues);
2300 // TwoNearZ / ViewWidth,0,0,0
2302 // 0,TwoNearZ / ViewHeight,0,0
2304 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2306 // x=fRange,y=-fRange * NearZ,0,-1.0f
2307 vValues = _mm_shuffle_ps(vValues,g_XMNegIdentityR3,_MM_SHUFFLE(3,2,3,2));
2309 vTemp = _mm_setzero_ps();
2310 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0));
2312 // 0,0,-fRange * NearZ,0
2313 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0));
2316 #else // _XM_VMX128_INTRINSICS_
2317 #endif // _XM_VMX128_INTRINSICS_
2320 //------------------------------------------------------------------------------
2322 XMFINLINE XMMATRIX XMMatrixPerspectiveFovLH
2330 #if defined(_XM_NO_INTRINSICS_)
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));
2342 XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY);
2344 Height = CosFov / SinFov;
2345 Width = Height / AspectHByW;
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);
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));
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;
2366 Height / AspectHByW,
2371 // Copy from memory to SSE register
2372 XMVECTOR vValues = rMem;
2373 XMVECTOR vTemp = _mm_setzero_ps();
2375 vTemp = _mm_move_ss(vTemp,vValues);
2376 // CosFov / SinFov,0,0,0
2378 // 0,Height / AspectHByW,0,0
2380 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
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));
2386 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0));
2388 // 0,0,-fRange * NearZ,0.0f
2389 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0));
2392 #else // _XM_VMX128_INTRINSICS_
2393 #endif // _XM_VMX128_INTRINSICS_
2396 //------------------------------------------------------------------------------
2398 XMFINLINE XMMATRIX XMMatrixPerspectiveFovRH
2406 #if defined(_XM_NO_INTRINSICS_)
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));
2418 XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY);
2420 Height = CosFov / SinFov;
2421 Width = Height / AspectHByW;
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);
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));
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;
2442 Height / AspectHByW,
2447 // Copy from memory to SSE register
2448 XMVECTOR vValues = rMem;
2449 XMVECTOR vTemp = _mm_setzero_ps();
2451 vTemp = _mm_move_ss(vTemp,vValues);
2452 // CosFov / SinFov,0,0,0
2454 // 0,Height / AspectHByW,0,0
2456 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
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));
2462 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0));
2464 // 0,0,fRange * NearZ,0.0f
2465 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0));
2468 #else // _XM_VMX128_INTRINSICS_
2469 #endif // _XM_VMX128_INTRINSICS_
2472 //------------------------------------------------------------------------------
2474 XMFINLINE XMMATRIX XMMatrixPerspectiveOffCenterLH
2484 #if defined(_XM_NO_INTRINSICS_)
2487 FLOAT ReciprocalWidth;
2488 FLOAT ReciprocalHeight;
2492 XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2493 XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2494 XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2496 TwoNearZ = NearZ + NearZ;
2497 ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2498 ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2499 fRange = FarZ / (FarZ-NearZ);
2501 M.m[0][0] = TwoNearZ * ReciprocalWidth;
2507 M.m[1][1] = TwoNearZ * ReciprocalHeight;
2511 M.m[2][0] = -(ViewLeft + ViewRight) * ReciprocalWidth;
2512 M.m[2][1] = -(ViewTop + ViewBottom) * ReciprocalHeight;
2518 M.m[3][2] = -fRange * NearZ;
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));
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
2533 TwoNearZ*ReciprocalWidth,
2534 TwoNearZ*ReciprocalHeight,
2538 // Copy from memory to SSE register
2539 XMVECTOR vValues = rMem;
2540 XMVECTOR vTemp = _mm_setzero_ps();
2542 vTemp = _mm_move_ss(vTemp,vValues);
2543 // TwoNearZ*ReciprocalWidth,0,0,0
2545 // 0,TwoNearZ*ReciprocalHeight,0,0
2547 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2550 M.r[2] = XMVectorSet( -(ViewLeft + ViewRight) * ReciprocalWidth,
2551 -(ViewTop + ViewBottom) * ReciprocalHeight,
2554 // 0,0,-fRange * NearZ,0.0f
2555 vValues = _mm_and_ps(vValues,g_XMMaskZ);
2558 #else // _XM_VMX128_INTRINSICS_
2559 #endif // _XM_VMX128_INTRINSICS_
2562 //------------------------------------------------------------------------------
2564 XMFINLINE XMMATRIX XMMatrixPerspectiveOffCenterRH
2574 #if defined(_XM_NO_INTRINSICS_)
2577 FLOAT ReciprocalWidth;
2578 FLOAT ReciprocalHeight;
2582 XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2583 XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2584 XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2586 TwoNearZ = NearZ + NearZ;
2587 ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2588 ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
2589 fRange = FarZ / (NearZ-FarZ);
2591 M.m[0][0] = TwoNearZ * ReciprocalWidth;
2597 M.m[1][1] = TwoNearZ * ReciprocalHeight;
2601 M.m[2][0] = (ViewLeft + ViewRight) * ReciprocalWidth;
2602 M.m[2][1] = (ViewTop + ViewBottom) * ReciprocalHeight;
2608 M.m[3][2] = fRange * NearZ;
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));
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
2624 TwoNearZ*ReciprocalWidth,
2625 TwoNearZ*ReciprocalHeight,
2629 // Copy from memory to SSE register
2630 XMVECTOR vValues = rMem;
2631 XMVECTOR vTemp = _mm_setzero_ps();
2633 vTemp = _mm_move_ss(vTemp,vValues);
2634 // TwoNearZ*ReciprocalWidth,0,0,0
2636 // 0,TwoNearZ*ReciprocalHeight,0,0
2638 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2641 M.r[2] = XMVectorSet((ViewLeft + ViewRight) * ReciprocalWidth,
2642 (ViewTop + ViewBottom) * ReciprocalHeight,
2645 // 0,0,-fRange * NearZ,0.0f
2646 vValues = _mm_and_ps(vValues,g_XMMaskZ);
2649 #else // _XM_VMX128_INTRINSICS_
2650 #endif // _XM_VMX128_INTRINSICS_
2653 //------------------------------------------------------------------------------
2655 XMFINLINE XMMATRIX XMMatrixOrthographicLH
2663 #if defined(_XM_NO_INTRINSICS_)
2668 XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2669 XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2670 XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
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);
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));
2685 FLOAT fRange = 1.0f / (FarZ-NearZ);
2686 // Note: This is recorded on the stack
2693 // Copy from memory to SSE register
2694 XMVECTOR vValues = rMem;
2695 XMVECTOR vTemp = _mm_setzero_ps();
2697 vTemp = _mm_move_ss(vTemp,vValues);
2698 // 2.0f / ViewWidth,0,0,0
2700 // 0,2.0f / ViewHeight,0,0
2702 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
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));
2708 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,0,0,0));
2710 // 0,0,-fRange * NearZ,1.0f
2711 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,1,0,0));
2714 #else // _XM_VMX128_INTRINSICS_
2715 #endif // _XM_VMX128_INTRINSICS_
2718 //------------------------------------------------------------------------------
2720 XMFINLINE XMMATRIX XMMatrixOrthographicRH
2728 #if defined(_XM_NO_INTRINSICS_)
2732 XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f));
2733 XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f));
2734 XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
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);
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));
2748 FLOAT fRange = 1.0f / (NearZ-FarZ);
2749 // Note: This is recorded on the stack
2756 // Copy from memory to SSE register
2757 XMVECTOR vValues = rMem;
2758 XMVECTOR vTemp = _mm_setzero_ps();
2760 vTemp = _mm_move_ss(vTemp,vValues);
2761 // 2.0f / ViewWidth,0,0,0
2763 // 0,2.0f / ViewHeight,0,0
2765 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
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));
2771 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,0,0,0));
2773 // 0,0,fRange * NearZ,1.0f
2774 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,1,0,0));
2777 #else // _XM_VMX128_INTRINSICS_
2778 #endif // _XM_VMX128_INTRINSICS_
2781 //------------------------------------------------------------------------------
2783 XMFINLINE XMMATRIX XMMatrixOrthographicOffCenterLH
2793 #if defined(_XM_NO_INTRINSICS_)
2795 FLOAT ReciprocalWidth;
2796 FLOAT ReciprocalHeight;
2799 XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2800 XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2801 XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2803 ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2804 ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
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,
2816 #elif defined(_XM_SSE_INTRINSICS_)
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
2829 -(ViewLeft + ViewRight),
2830 -(ViewTop + ViewBottom),
2834 // Copy from memory to SSE register
2835 XMVECTOR vValues = rMem;
2836 XMVECTOR vTemp = _mm_setzero_ps();
2838 vTemp = _mm_move_ss(vTemp,vValues);
2839 // fReciprocalWidth*2,0,0,0
2840 vTemp = _mm_add_ss(vTemp,vTemp);
2842 // 0,fReciprocalHeight*2,0,0
2844 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2845 vTemp = _mm_add_ps(vTemp,vTemp);
2849 vTemp = _mm_and_ps(vTemp,g_XMMaskZ);
2851 // -(ViewLeft + ViewRight)*fReciprocalWidth,-(ViewTop + ViewBottom)*fReciprocalHeight,fRange*-NearZ,1.0f
2852 vValues = _mm_mul_ps(vValues,rMem2);
2855 #else // _XM_VMX128_INTRINSICS_
2856 #endif // _XM_VMX128_INTRINSICS_
2859 //------------------------------------------------------------------------------
2861 XMFINLINE XMMATRIX XMMatrixOrthographicOffCenterRH
2871 #if defined(_XM_NO_INTRINSICS_)
2873 FLOAT ReciprocalWidth;
2874 FLOAT ReciprocalHeight;
2877 XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f));
2878 XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f));
2879 XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f));
2881 ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
2882 ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
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,
2894 #elif defined(_XM_SSE_INTRINSICS_)
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
2907 -(ViewLeft + ViewRight),
2908 -(ViewTop + ViewBottom),
2912 // Copy from memory to SSE register
2913 XMVECTOR vValues = rMem;
2914 XMVECTOR vTemp = _mm_setzero_ps();
2916 vTemp = _mm_move_ss(vTemp,vValues);
2917 // fReciprocalWidth*2,0,0,0
2918 vTemp = _mm_add_ss(vTemp,vTemp);
2920 // 0,fReciprocalHeight*2,0,0
2922 vTemp = _mm_and_ps(vTemp,g_XMMaskY);
2923 vTemp = _mm_add_ps(vTemp,vTemp);
2927 vTemp = _mm_and_ps(vTemp,g_XMMaskZ);
2929 // -(ViewLeft + ViewRight)*fReciprocalWidth,-(ViewTop + ViewBottom)*fReciprocalHeight,fRange*-NearZ,1.0f
2930 vValues = _mm_mul_ps(vValues,rMem2);
2933 #else // _XM_VMX128_INTRINSICS_
2934 #endif // _XM_VMX128_INTRINSICS_
2940 /****************************************************************************
2942 * XMMATRIX operators and methods
2944 ****************************************************************************/
2946 //------------------------------------------------------------------------------
2948 XMFINLINE _XMMATRIX::_XMMATRIX
2962 //------------------------------------------------------------------------------
2964 XMFINLINE _XMMATRIX::_XMMATRIX
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
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);
2978 //------------------------------------------------------------------------------
2980 XMFINLINE _XMMATRIX::_XMMATRIX
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));
2991 //------------------------------------------------------------------------------
2993 XMFINLINE _XMMATRIX& _XMMATRIX::operator=
3005 //------------------------------------------------------------------------------
3007 #ifndef XM_NO_OPERATOR_OVERLOADS
3009 #if !defined(_XBOX_VER) && defined(_XM_ISVS2005_) && defined(_XM_X64_)
3010 #pragma warning(push)
3011 #pragma warning(disable : 4328)
3014 XMFINLINE _XMMATRIX& _XMMATRIX::operator*=
3019 *this = XMMatrixMultiply(*this, M);
3023 //------------------------------------------------------------------------------
3025 XMFINLINE _XMMATRIX _XMMATRIX::operator*
3030 return XMMatrixMultiply(*this, M);
3033 #if !defined(_XBOX_VER) && defined(_XM_ISVS2005_) && defined(_XM_X64_)
3034 #pragma warning(pop)
3037 #endif // !XM_NO_OPERATOR_OVERLOADS
3039 /****************************************************************************
3041 * XMFLOAT3X3 operators
3043 ****************************************************************************/
3045 //------------------------------------------------------------------------------
3047 XMFINLINE _XMFLOAT3X3::_XMFLOAT3X3
3049 FLOAT m00, FLOAT m01, FLOAT m02,
3050 FLOAT m10, FLOAT m11, FLOAT m12,
3051 FLOAT m20, FLOAT m21, FLOAT m22
3067 //------------------------------------------------------------------------------
3069 XMFINLINE _XMFLOAT3X3::_XMFLOAT3X3
3077 for (Row = 0; Row < 3; Row++)
3079 for (Column = 0; Column < 3; Column++)
3081 m[Row][Column] = pArray[Row * 3 + Column];
3086 //------------------------------------------------------------------------------
3088 XMFINLINE _XMFLOAT3X3& _XMFLOAT3X3::operator=
3090 CONST _XMFLOAT3X3& Float3x3
3106 /****************************************************************************
3108 * XMFLOAT4X3 operators
3110 ****************************************************************************/
3112 //------------------------------------------------------------------------------
3114 XMFINLINE _XMFLOAT4X3::_XMFLOAT4X3
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
3139 //------------------------------------------------------------------------------
3141 XMFINLINE _XMFLOAT4X3::_XMFLOAT4X3
3149 for (Row = 0; Row < 4; Row++)
3151 for (Column = 0; Column < 3; Column++)
3153 m[Row][Column] = pArray[Row * 3 + Column];
3158 //------------------------------------------------------------------------------
3160 XMFINLINE _XMFLOAT4X3& _XMFLOAT4X3::operator=
3162 CONST _XMFLOAT4X3& Float4x3
3165 XMVECTOR V1 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._11);
3166 XMVECTOR V2 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._22);
3167 XMVECTOR V3 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._33);
3169 XMStoreFloat4((XMFLOAT4*)&_11, V1);
3170 XMStoreFloat4((XMFLOAT4*)&_22, V2);
3171 XMStoreFloat4((XMFLOAT4*)&_33, V3);
3176 //------------------------------------------------------------------------------
3178 XMFINLINE XMFLOAT4X3A& XMFLOAT4X3A::operator=
3180 CONST XMFLOAT4X3A& Float4x3
3183 XMVECTOR V1 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._11);
3184 XMVECTOR V2 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._22);
3185 XMVECTOR V3 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._33);
3187 XMStoreFloat4A((XMFLOAT4A*)&_11, V1);
3188 XMStoreFloat4A((XMFLOAT4A*)&_22, V2);
3189 XMStoreFloat4A((XMFLOAT4A*)&_33, V3);
3194 /****************************************************************************
3196 * XMFLOAT4X4 operators
3198 ****************************************************************************/
3200 //------------------------------------------------------------------------------
3202 XMFINLINE _XMFLOAT4X4::_XMFLOAT4X4
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
3231 //------------------------------------------------------------------------------
3233 XMFINLINE _XMFLOAT4X4::_XMFLOAT4X4
3241 for (Row = 0; Row < 4; Row++)
3243 for (Column = 0; Column < 4; Column++)
3245 m[Row][Column] = pArray[Row * 4 + Column];
3250 //------------------------------------------------------------------------------
3252 XMFINLINE _XMFLOAT4X4& _XMFLOAT4X4::operator=
3254 CONST _XMFLOAT4X4& Float4x4
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);
3262 XMStoreFloat4((XMFLOAT4*)&_11, V1);
3263 XMStoreFloat4((XMFLOAT4*)&_21, V2);
3264 XMStoreFloat4((XMFLOAT4*)&_31, V3);
3265 XMStoreFloat4((XMFLOAT4*)&_41, V4);
3270 //------------------------------------------------------------------------------
3272 XMFINLINE XMFLOAT4X4A& XMFLOAT4X4A::operator=
3274 CONST XMFLOAT4X4A& Float4x4
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);
3282 XMStoreFloat4A((XMFLOAT4A*)&_11, V1);
3283 XMStoreFloat4A((XMFLOAT4A*)&_21, V2);
3284 XMStoreFloat4A((XMFLOAT4A*)&_31, V3);
3285 XMStoreFloat4A((XMFLOAT4A*)&_41, V4);
3290 #endif // __cplusplus
3292 #endif // __XNAMATHMATRIX_INL__