/************************************************************************ * * * xnamathmatrix.inl -- SIMD C++ Math library for Windows and Xbox 360 * * Matrix functions * * * * Copyright (c) Microsoft Corp. All rights reserved. * * * ************************************************************************/ #if defined(_MSC_VER) && (_MSC_VER > 1000) #pragma once #endif #ifndef __XNAMATHMATRIX_INL__ #define __XNAMATHMATRIX_INL__ /**************************************************************************** * * Matrix * ****************************************************************************/ //------------------------------------------------------------------------------ // Comparison operations //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Return TRUE if any entry in the matrix is NaN XMFINLINE BOOL XMMatrixIsNaN ( CXMMATRIX M ) { #if defined(_XM_NO_INTRINSICS_) UINT i, uTest; const UINT *pWork; i = 16; pWork = (const UINT *)(&M.m[0][0]); do { // Fetch value into integer unit uTest = pWork[0]; // Remove sign uTest &= 0x7FFFFFFFU; // NaN is 0x7F800001 through 0x7FFFFFFF inclusive uTest -= 0x7F800001U; if (uTest<0x007FFFFFU) { break; // NaN found } ++pWork; // Next entry } while (--i); return (i!=0); // i == 0 if nothing matched #elif defined(_XM_SSE_INTRINSICS_) // Load in registers XMVECTOR vX = M.r[0]; XMVECTOR vY = M.r[1]; XMVECTOR vZ = M.r[2]; XMVECTOR vW = M.r[3]; // Test themselves to check for NaN vX = _mm_cmpneq_ps(vX,vX); vY = _mm_cmpneq_ps(vY,vY); vZ = _mm_cmpneq_ps(vZ,vZ); vW = _mm_cmpneq_ps(vW,vW); // Or all the results vX = _mm_or_ps(vX,vZ); vY = _mm_or_ps(vY,vW); vX = _mm_or_ps(vX,vY); // If any tested true, return true return (_mm_movemask_ps(vX)!=0); #else #endif } //------------------------------------------------------------------------------ // Return TRUE if any entry in the matrix is +/-INF XMFINLINE BOOL XMMatrixIsInfinite ( CXMMATRIX M ) { #if defined(_XM_NO_INTRINSICS_) UINT i, uTest; const UINT *pWork; i = 16; pWork = (const UINT *)(&M.m[0][0]); do { // Fetch value into integer unit uTest = pWork[0]; // Remove sign uTest &= 0x7FFFFFFFU; // INF is 0x7F800000 if (uTest==0x7F800000U) { break; // INF found } ++pWork; // Next entry } while (--i); return (i!=0); // i == 0 if nothing matched #elif defined(_XM_SSE_INTRINSICS_) // Mask off the sign bits XMVECTOR vTemp1 = _mm_and_ps(M.r[0],g_XMAbsMask); XMVECTOR vTemp2 = _mm_and_ps(M.r[1],g_XMAbsMask); XMVECTOR vTemp3 = _mm_and_ps(M.r[2],g_XMAbsMask); XMVECTOR vTemp4 = _mm_and_ps(M.r[3],g_XMAbsMask); // Compare to infinity vTemp1 = _mm_cmpeq_ps(vTemp1,g_XMInfinity); vTemp2 = _mm_cmpeq_ps(vTemp2,g_XMInfinity); vTemp3 = _mm_cmpeq_ps(vTemp3,g_XMInfinity); vTemp4 = _mm_cmpeq_ps(vTemp4,g_XMInfinity); // Or the answers together vTemp1 = _mm_or_ps(vTemp1,vTemp2); vTemp3 = _mm_or_ps(vTemp3,vTemp4); vTemp1 = _mm_or_ps(vTemp1,vTemp3); // If any are infinity, the signs are true. return (_mm_movemask_ps(vTemp1)!=0); #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ // Return TRUE if the XMMatrix is equal to identity XMFINLINE BOOL XMMatrixIsIdentity ( CXMMATRIX M ) { #if defined(_XM_NO_INTRINSICS_) unsigned int uOne, uZero; const unsigned int *pWork; // Use the integer pipeline to reduce branching to a minimum pWork = (const unsigned int*)(&M.m[0][0]); // Convert 1.0f to zero and or them together uOne = pWork[0]^0x3F800000U; // Or all the 0.0f entries together uZero = pWork[1]; uZero |= pWork[2]; uZero |= pWork[3]; // 2nd row uZero |= pWork[4]; uOne |= pWork[5]^0x3F800000U; uZero |= pWork[6]; uZero |= pWork[7]; // 3rd row uZero |= pWork[8]; uZero |= pWork[9]; uOne |= pWork[10]^0x3F800000U; uZero |= pWork[11]; // 4th row uZero |= pWork[12]; uZero |= pWork[13]; uZero |= pWork[14]; uOne |= pWork[15]^0x3F800000U; // If all zero entries are zero, the uZero==0 uZero &= 0x7FFFFFFF; // Allow -0.0f // If all 1.0f entries are 1.0f, then uOne==0 uOne |= uZero; return (uOne==0); #elif defined(_XM_SSE_INTRINSICS_) XMVECTOR vTemp1 = _mm_cmpeq_ps(M.r[0],g_XMIdentityR0); XMVECTOR vTemp2 = _mm_cmpeq_ps(M.r[1],g_XMIdentityR1); XMVECTOR vTemp3 = _mm_cmpeq_ps(M.r[2],g_XMIdentityR2); XMVECTOR vTemp4 = _mm_cmpeq_ps(M.r[3],g_XMIdentityR3); vTemp1 = _mm_and_ps(vTemp1,vTemp2); vTemp3 = _mm_and_ps(vTemp3,vTemp4); vTemp1 = _mm_and_ps(vTemp1,vTemp3); return (_mm_movemask_ps(vTemp1)==0x0f); #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ // Computation operations //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Perform a 4x4 matrix multiply by a 4x4 matrix XMFINLINE XMMATRIX XMMatrixMultiply ( CXMMATRIX M1, CXMMATRIX M2 ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX mResult; // Cache the invariants in registers float x = M1.m[0][0]; float y = M1.m[0][1]; float z = M1.m[0][2]; float w = M1.m[0][3]; // Perform the operation on the first row mResult.m[0][0] = (M2.m[0][0]*x)+(M2.m[1][0]*y)+(M2.m[2][0]*z)+(M2.m[3][0]*w); mResult.m[0][1] = (M2.m[0][1]*x)+(M2.m[1][1]*y)+(M2.m[2][1]*z)+(M2.m[3][1]*w); mResult.m[0][2] = (M2.m[0][2]*x)+(M2.m[1][2]*y)+(M2.m[2][2]*z)+(M2.m[3][2]*w); mResult.m[0][3] = (M2.m[0][3]*x)+(M2.m[1][3]*y)+(M2.m[2][3]*z)+(M2.m[3][3]*w); // Repeat for all the other rows x = M1.m[1][0]; y = M1.m[1][1]; z = M1.m[1][2]; w = M1.m[1][3]; mResult.m[1][0] = (M2.m[0][0]*x)+(M2.m[1][0]*y)+(M2.m[2][0]*z)+(M2.m[3][0]*w); mResult.m[1][1] = (M2.m[0][1]*x)+(M2.m[1][1]*y)+(M2.m[2][1]*z)+(M2.m[3][1]*w); mResult.m[1][2] = (M2.m[0][2]*x)+(M2.m[1][2]*y)+(M2.m[2][2]*z)+(M2.m[3][2]*w); mResult.m[1][3] = (M2.m[0][3]*x)+(M2.m[1][3]*y)+(M2.m[2][3]*z)+(M2.m[3][3]*w); x = M1.m[2][0]; y = M1.m[2][1]; z = M1.m[2][2]; w = M1.m[2][3]; mResult.m[2][0] = (M2.m[0][0]*x)+(M2.m[1][0]*y)+(M2.m[2][0]*z)+(M2.m[3][0]*w); mResult.m[2][1] = (M2.m[0][1]*x)+(M2.m[1][1]*y)+(M2.m[2][1]*z)+(M2.m[3][1]*w); mResult.m[2][2] = (M2.m[0][2]*x)+(M2.m[1][2]*y)+(M2.m[2][2]*z)+(M2.m[3][2]*w); mResult.m[2][3] = (M2.m[0][3]*x)+(M2.m[1][3]*y)+(M2.m[2][3]*z)+(M2.m[3][3]*w); x = M1.m[3][0]; y = M1.m[3][1]; z = M1.m[3][2]; w = M1.m[3][3]; mResult.m[3][0] = (M2.m[0][0]*x)+(M2.m[1][0]*y)+(M2.m[2][0]*z)+(M2.m[3][0]*w); mResult.m[3][1] = (M2.m[0][1]*x)+(M2.m[1][1]*y)+(M2.m[2][1]*z)+(M2.m[3][1]*w); mResult.m[3][2] = (M2.m[0][2]*x)+(M2.m[1][2]*y)+(M2.m[2][2]*z)+(M2.m[3][2]*w); mResult.m[3][3] = (M2.m[0][3]*x)+(M2.m[1][3]*y)+(M2.m[2][3]*z)+(M2.m[3][3]*w); return mResult; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX mResult; // Use vW to hold the original row XMVECTOR vW = M1.r[0]; // Splat the component X,Y,Z then W XMVECTOR vX = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(0,0,0,0)); XMVECTOR vY = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(1,1,1,1)); XMVECTOR vZ = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(2,2,2,2)); vW = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(3,3,3,3)); // Perform the opertion on the first row vX = _mm_mul_ps(vX,M2.r[0]); vY = _mm_mul_ps(vY,M2.r[1]); vZ = _mm_mul_ps(vZ,M2.r[2]); vW = _mm_mul_ps(vW,M2.r[3]); // Perform a binary add to reduce cumulative errors vX = _mm_add_ps(vX,vZ); vY = _mm_add_ps(vY,vW); vX = _mm_add_ps(vX,vY); mResult.r[0] = vX; // Repeat for the other 3 rows vW = M1.r[1]; vX = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(0,0,0,0)); vY = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(1,1,1,1)); vZ = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(2,2,2,2)); vW = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(3,3,3,3)); vX = _mm_mul_ps(vX,M2.r[0]); vY = _mm_mul_ps(vY,M2.r[1]); vZ = _mm_mul_ps(vZ,M2.r[2]); vW = _mm_mul_ps(vW,M2.r[3]); vX = _mm_add_ps(vX,vZ); vY = _mm_add_ps(vY,vW); vX = _mm_add_ps(vX,vY); mResult.r[1] = vX; vW = M1.r[2]; vX = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(0,0,0,0)); vY = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(1,1,1,1)); vZ = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(2,2,2,2)); vW = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(3,3,3,3)); vX = _mm_mul_ps(vX,M2.r[0]); vY = _mm_mul_ps(vY,M2.r[1]); vZ = _mm_mul_ps(vZ,M2.r[2]); vW = _mm_mul_ps(vW,M2.r[3]); vX = _mm_add_ps(vX,vZ); vY = _mm_add_ps(vY,vW); vX = _mm_add_ps(vX,vY); mResult.r[2] = vX; vW = M1.r[3]; vX = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(0,0,0,0)); vY = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(1,1,1,1)); vZ = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(2,2,2,2)); vW = _mm_shuffle_ps(vW,vW,_MM_SHUFFLE(3,3,3,3)); vX = _mm_mul_ps(vX,M2.r[0]); vY = _mm_mul_ps(vY,M2.r[1]); vZ = _mm_mul_ps(vZ,M2.r[2]); vW = _mm_mul_ps(vW,M2.r[3]); vX = _mm_add_ps(vX,vZ); vY = _mm_add_ps(vY,vW); vX = _mm_add_ps(vX,vY); mResult.r[3] = vX; return mResult; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixMultiplyTranspose ( CXMMATRIX M1, CXMMATRIX M2 ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX mResult; // Cache the invariants in registers float x = M2.m[0][0]; float y = M2.m[1][0]; float z = M2.m[2][0]; float w = M2.m[3][0]; // Perform the operation on the first row mResult.m[0][0] = (M1.m[0][0]*x)+(M1.m[0][1]*y)+(M1.m[0][2]*z)+(M1.m[0][3]*w); mResult.m[0][1] = (M1.m[1][0]*x)+(M1.m[1][1]*y)+(M1.m[1][2]*z)+(M1.m[1][3]*w); mResult.m[0][2] = (M1.m[2][0]*x)+(M1.m[2][1]*y)+(M1.m[2][2]*z)+(M1.m[2][3]*w); mResult.m[0][3] = (M1.m[3][0]*x)+(M1.m[3][1]*y)+(M1.m[3][2]*z)+(M1.m[3][3]*w); // Repeat for all the other rows x = M2.m[0][1]; y = M2.m[1][1]; z = M2.m[2][1]; w = M2.m[3][1]; mResult.m[1][0] = (M1.m[0][0]*x)+(M1.m[0][1]*y)+(M1.m[0][2]*z)+(M1.m[0][3]*w); mResult.m[1][1] = (M1.m[1][0]*x)+(M1.m[1][1]*y)+(M1.m[1][2]*z)+(M1.m[1][3]*w); mResult.m[1][2] = (M1.m[2][0]*x)+(M1.m[2][1]*y)+(M1.m[2][2]*z)+(M1.m[2][3]*w); mResult.m[1][3] = (M1.m[3][0]*x)+(M1.m[3][1]*y)+(M1.m[3][2]*z)+(M1.m[3][3]*w); x = M2.m[0][2]; y = M2.m[1][2]; z = M2.m[2][2]; w = M2.m[3][2]; mResult.m[2][0] = (M1.m[0][0]*x)+(M1.m[0][1]*y)+(M1.m[0][2]*z)+(M1.m[0][3]*w); mResult.m[2][1] = (M1.m[1][0]*x)+(M1.m[1][1]*y)+(M1.m[1][2]*z)+(M1.m[1][3]*w); mResult.m[2][2] = (M1.m[2][0]*x)+(M1.m[2][1]*y)+(M1.m[2][2]*z)+(M1.m[2][3]*w); mResult.m[2][3] = (M1.m[3][0]*x)+(M1.m[3][1]*y)+(M1.m[3][2]*z)+(M1.m[3][3]*w); x = M2.m[0][3]; y = M2.m[1][3]; z = M2.m[2][3]; w = M2.m[3][3]; mResult.m[3][0] = (M1.m[0][0]*x)+(M1.m[0][1]*y)+(M1.m[0][2]*z)+(M1.m[0][3]*w); mResult.m[3][1] = (M1.m[1][0]*x)+(M1.m[1][1]*y)+(M1.m[1][2]*z)+(M1.m[1][3]*w); mResult.m[3][2] = (M1.m[2][0]*x)+(M1.m[2][1]*y)+(M1.m[2][2]*z)+(M1.m[2][3]*w); mResult.m[3][3] = (M1.m[3][0]*x)+(M1.m[3][1]*y)+(M1.m[3][2]*z)+(M1.m[3][3]*w); return mResult; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX Product; XMMATRIX Result; Product = XMMatrixMultiply(M1, M2); Result = XMMatrixTranspose(Product); return Result; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixTranspose ( CXMMATRIX M ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX P; XMMATRIX MT; // Original matrix: // // m00m01m02m03 // m10m11m12m13 // m20m21m22m23 // m30m31m32m33 P.r[0] = XMVectorMergeXY(M.r[0], M.r[2]); // m00m20m01m21 P.r[1] = XMVectorMergeXY(M.r[1], M.r[3]); // m10m30m11m31 P.r[2] = XMVectorMergeZW(M.r[0], M.r[2]); // m02m22m03m23 P.r[3] = XMVectorMergeZW(M.r[1], M.r[3]); // m12m32m13m33 MT.r[0] = XMVectorMergeXY(P.r[0], P.r[1]); // m00m10m20m30 MT.r[1] = XMVectorMergeZW(P.r[0], P.r[1]); // m01m11m21m31 MT.r[2] = XMVectorMergeXY(P.r[2], P.r[3]); // m02m12m22m32 MT.r[3] = XMVectorMergeZW(P.r[2], P.r[3]); // m03m13m23m33 return MT; #elif defined(_XM_SSE_INTRINSICS_) // x.x,x.y,y.x,y.y XMVECTOR vTemp1 = _mm_shuffle_ps(M.r[0],M.r[1],_MM_SHUFFLE(1,0,1,0)); // x.z,x.w,y.z,y.w XMVECTOR vTemp3 = _mm_shuffle_ps(M.r[0],M.r[1],_MM_SHUFFLE(3,2,3,2)); // z.x,z.y,w.x,w.y XMVECTOR vTemp2 = _mm_shuffle_ps(M.r[2],M.r[3],_MM_SHUFFLE(1,0,1,0)); // z.z,z.w,w.z,w.w XMVECTOR vTemp4 = _mm_shuffle_ps(M.r[2],M.r[3],_MM_SHUFFLE(3,2,3,2)); XMMATRIX mResult; // x.x,y.x,z.x,w.x mResult.r[0] = _mm_shuffle_ps(vTemp1, vTemp2,_MM_SHUFFLE(2,0,2,0)); // x.y,y.y,z.y,w.y mResult.r[1] = _mm_shuffle_ps(vTemp1, vTemp2,_MM_SHUFFLE(3,1,3,1)); // x.z,y.z,z.z,w.z mResult.r[2] = _mm_shuffle_ps(vTemp3, vTemp4,_MM_SHUFFLE(2,0,2,0)); // x.w,y.w,z.w,w.w mResult.r[3] = _mm_shuffle_ps(vTemp3, vTemp4,_MM_SHUFFLE(3,1,3,1)); return mResult; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ // Return the inverse and the determinant of a 4x4 matrix XMINLINE XMMATRIX XMMatrixInverse ( XMVECTOR* pDeterminant, CXMMATRIX M ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX R; XMMATRIX MT; XMVECTOR D0, D1, D2; XMVECTOR C0, C1, C2, C3, C4, C5, C6, C7; XMVECTOR V0[4], V1[4]; XMVECTOR Determinant; XMVECTOR Reciprocal; XMMATRIX Result; static CONST XMVECTORU32 SwizzleXXYY = {XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_0Y}; static CONST XMVECTORU32 SwizzleZWZW = {XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_0Z, XM_PERMUTE_0W}; static CONST XMVECTORU32 SwizzleYZXY = {XM_PERMUTE_0Y, XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0Y}; static CONST XMVECTORU32 SwizzleZWYZ = {XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_0Y, XM_PERMUTE_0Z}; static CONST XMVECTORU32 SwizzleWXWX = {XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_0X}; static CONST XMVECTORU32 SwizzleZXYX = {XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_0X}; static CONST XMVECTORU32 SwizzleYWXZ = {XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0Z}; static CONST XMVECTORU32 SwizzleWZWY = {XM_PERMUTE_0W, XM_PERMUTE_0Z, XM_PERMUTE_0W, XM_PERMUTE_0Y}; static CONST XMVECTORU32 Permute0X0Z1X1Z = {XM_PERMUTE_0X, XM_PERMUTE_0Z, XM_PERMUTE_1X, XM_PERMUTE_1Z}; static CONST XMVECTORU32 Permute0Y0W1Y1W = {XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_1Y, XM_PERMUTE_1W}; static CONST XMVECTORU32 Permute1Y0Y0W0X = {XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_0X}; static CONST XMVECTORU32 Permute0W0X0Y1X = {XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_1X}; static CONST XMVECTORU32 Permute0Z1Y1X0Z = {XM_PERMUTE_0Z, XM_PERMUTE_1Y, XM_PERMUTE_1X, XM_PERMUTE_0Z}; static CONST XMVECTORU32 Permute0W1Y0Y0Z = {XM_PERMUTE_0W, XM_PERMUTE_1Y, XM_PERMUTE_0Y, XM_PERMUTE_0Z}; static CONST XMVECTORU32 Permute0Z0Y1X0X = {XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_0X}; static CONST XMVECTORU32 Permute1Y0X0W1X = {XM_PERMUTE_1Y, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_1X}; static CONST XMVECTORU32 Permute1W0Y0W0X = {XM_PERMUTE_1W, XM_PERMUTE_0Y, XM_PERMUTE_0W, XM_PERMUTE_0X}; static CONST XMVECTORU32 Permute0W0X0Y1Z = {XM_PERMUTE_0W, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_1Z}; static CONST XMVECTORU32 Permute0Z1W1Z0Z = {XM_PERMUTE_0Z, XM_PERMUTE_1W, XM_PERMUTE_1Z, XM_PERMUTE_0Z}; static CONST XMVECTORU32 Permute0W1W0Y0Z = {XM_PERMUTE_0W, XM_PERMUTE_1W, XM_PERMUTE_0Y, XM_PERMUTE_0Z}; static CONST XMVECTORU32 Permute0Z0Y1Z0X = {XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1Z, XM_PERMUTE_0X}; static CONST XMVECTORU32 Permute1W0X0W1Z = {XM_PERMUTE_1W, XM_PERMUTE_0X, XM_PERMUTE_0W, XM_PERMUTE_1Z}; MT = XMMatrixTranspose(M); V0[0] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleXXYY.v); V1[0] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleZWZW.v); V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleXXYY.v); V1[1] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleZWZW.v); V0[2] = XMVectorPermute(MT.r[2], MT.r[0], Permute0X0Z1X1Z.v); V1[2] = XMVectorPermute(MT.r[3], MT.r[1], Permute0Y0W1Y1W.v); D0 = XMVectorMultiply(V0[0], V1[0]); D1 = XMVectorMultiply(V0[1], V1[1]); D2 = XMVectorMultiply(V0[2], V1[2]); V0[0] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleZWZW.v); V1[0] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleXXYY.v); V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleZWZW.v); V1[1] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleXXYY.v); V0[2] = XMVectorPermute(MT.r[2], MT.r[0], Permute0Y0W1Y1W.v); V1[2] = XMVectorPermute(MT.r[3], MT.r[1], Permute0X0Z1X1Z.v); D0 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], D0); D1 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], D1); D2 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], D2); V0[0] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleYZXY.v); V1[0] = XMVectorPermute(D0, D2, Permute1Y0Y0W0X.v); V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleZXYX.v); V1[1] = XMVectorPermute(D0, D2, Permute0W1Y0Y0Z.v); V0[2] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleYZXY.v); V1[2] = XMVectorPermute(D1, D2, Permute1W0Y0W0X.v); V0[3] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleZXYX.v); V1[3] = XMVectorPermute(D1, D2, Permute0W1W0Y0Z.v); C0 = XMVectorMultiply(V0[0], V1[0]); C2 = XMVectorMultiply(V0[1], V1[1]); C4 = XMVectorMultiply(V0[2], V1[2]); C6 = XMVectorMultiply(V0[3], V1[3]); V0[0] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleZWYZ.v); V1[0] = XMVectorPermute(D0, D2, Permute0W0X0Y1X.v); V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleWZWY.v); V1[1] = XMVectorPermute(D0, D2, Permute0Z0Y1X0X.v); V0[2] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleZWYZ.v); V1[2] = XMVectorPermute(D1, D2, Permute0W0X0Y1Z.v); V0[3] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleWZWY.v); V1[3] = XMVectorPermute(D1, D2, Permute0Z0Y1Z0X.v); C0 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], C0); C2 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], C2); C4 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], C4); C6 = XMVectorNegativeMultiplySubtract(V0[3], V1[3], C6); V0[0] = XMVectorPermute(MT.r[1], MT.r[1], SwizzleWXWX.v); V1[0] = XMVectorPermute(D0, D2, Permute0Z1Y1X0Z.v); V0[1] = XMVectorPermute(MT.r[0], MT.r[0], SwizzleYWXZ.v); V1[1] = XMVectorPermute(D0, D2, Permute1Y0X0W1X.v); V0[2] = XMVectorPermute(MT.r[3], MT.r[3], SwizzleWXWX.v); V1[2] = XMVectorPermute(D1, D2, Permute0Z1W1Z0Z.v); V0[3] = XMVectorPermute(MT.r[2], MT.r[2], SwizzleYWXZ.v); V1[3] = XMVectorPermute(D1, D2, Permute1W0X0W1Z.v); C1 = XMVectorNegativeMultiplySubtract(V0[0], V1[0], C0); C0 = XMVectorMultiplyAdd(V0[0], V1[0], C0); C3 = XMVectorMultiplyAdd(V0[1], V1[1], C2); C2 = XMVectorNegativeMultiplySubtract(V0[1], V1[1], C2); C5 = XMVectorNegativeMultiplySubtract(V0[2], V1[2], C4); C4 = XMVectorMultiplyAdd(V0[2], V1[2], C4); C7 = XMVectorMultiplyAdd(V0[3], V1[3], C6); C6 = XMVectorNegativeMultiplySubtract(V0[3], V1[3], C6); R.r[0] = XMVectorSelect(C0, C1, g_XMSelect0101.v); R.r[1] = XMVectorSelect(C2, C3, g_XMSelect0101.v); R.r[2] = XMVectorSelect(C4, C5, g_XMSelect0101.v); R.r[3] = XMVectorSelect(C6, C7, g_XMSelect0101.v); Determinant = XMVector4Dot(R.r[0], MT.r[0]); if (pDeterminant) *pDeterminant = Determinant; Reciprocal = XMVectorReciprocal(Determinant); Result.r[0] = XMVectorMultiply(R.r[0], Reciprocal); Result.r[1] = XMVectorMultiply(R.r[1], Reciprocal); Result.r[2] = XMVectorMultiply(R.r[2], Reciprocal); Result.r[3] = XMVectorMultiply(R.r[3], Reciprocal); return Result; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX MT = XMMatrixTranspose(M); XMVECTOR V00 = _mm_shuffle_ps(MT.r[2], MT.r[2],_MM_SHUFFLE(1,1,0,0)); XMVECTOR V10 = _mm_shuffle_ps(MT.r[3], MT.r[3],_MM_SHUFFLE(3,2,3,2)); XMVECTOR V01 = _mm_shuffle_ps(MT.r[0], MT.r[0],_MM_SHUFFLE(1,1,0,0)); XMVECTOR V11 = _mm_shuffle_ps(MT.r[1], MT.r[1],_MM_SHUFFLE(3,2,3,2)); XMVECTOR V02 = _mm_shuffle_ps(MT.r[2], MT.r[0],_MM_SHUFFLE(2,0,2,0)); XMVECTOR V12 = _mm_shuffle_ps(MT.r[3], MT.r[1],_MM_SHUFFLE(3,1,3,1)); XMVECTOR D0 = _mm_mul_ps(V00,V10); XMVECTOR D1 = _mm_mul_ps(V01,V11); XMVECTOR D2 = _mm_mul_ps(V02,V12); V00 = _mm_shuffle_ps(MT.r[2],MT.r[2],_MM_SHUFFLE(3,2,3,2)); V10 = _mm_shuffle_ps(MT.r[3],MT.r[3],_MM_SHUFFLE(1,1,0,0)); V01 = _mm_shuffle_ps(MT.r[0],MT.r[0],_MM_SHUFFLE(3,2,3,2)); V11 = _mm_shuffle_ps(MT.r[1],MT.r[1],_MM_SHUFFLE(1,1,0,0)); V02 = _mm_shuffle_ps(MT.r[2],MT.r[0],_MM_SHUFFLE(3,1,3,1)); V12 = _mm_shuffle_ps(MT.r[3],MT.r[1],_MM_SHUFFLE(2,0,2,0)); V00 = _mm_mul_ps(V00,V10); V01 = _mm_mul_ps(V01,V11); V02 = _mm_mul_ps(V02,V12); D0 = _mm_sub_ps(D0,V00); D1 = _mm_sub_ps(D1,V01); D2 = _mm_sub_ps(D2,V02); // V11 = D0Y,D0W,D2Y,D2Y V11 = _mm_shuffle_ps(D0,D2,_MM_SHUFFLE(1,1,3,1)); V00 = _mm_shuffle_ps(MT.r[1], MT.r[1],_MM_SHUFFLE(1,0,2,1)); V10 = _mm_shuffle_ps(V11,D0,_MM_SHUFFLE(0,3,0,2)); V01 = _mm_shuffle_ps(MT.r[0], MT.r[0],_MM_SHUFFLE(0,1,0,2)); V11 = _mm_shuffle_ps(V11,D0,_MM_SHUFFLE(2,1,2,1)); // V13 = D1Y,D1W,D2W,D2W XMVECTOR V13 = _mm_shuffle_ps(D1,D2,_MM_SHUFFLE(3,3,3,1)); V02 = _mm_shuffle_ps(MT.r[3], MT.r[3],_MM_SHUFFLE(1,0,2,1)); V12 = _mm_shuffle_ps(V13,D1,_MM_SHUFFLE(0,3,0,2)); XMVECTOR V03 = _mm_shuffle_ps(MT.r[2], MT.r[2],_MM_SHUFFLE(0,1,0,2)); V13 = _mm_shuffle_ps(V13,D1,_MM_SHUFFLE(2,1,2,1)); XMVECTOR C0 = _mm_mul_ps(V00,V10); XMVECTOR C2 = _mm_mul_ps(V01,V11); XMVECTOR C4 = _mm_mul_ps(V02,V12); XMVECTOR C6 = _mm_mul_ps(V03,V13); // V11 = D0X,D0Y,D2X,D2X V11 = _mm_shuffle_ps(D0,D2,_MM_SHUFFLE(0,0,1,0)); V00 = _mm_shuffle_ps(MT.r[1], MT.r[1],_MM_SHUFFLE(2,1,3,2)); V10 = _mm_shuffle_ps(D0,V11,_MM_SHUFFLE(2,1,0,3)); V01 = _mm_shuffle_ps(MT.r[0], MT.r[0],_MM_SHUFFLE(1,3,2,3)); V11 = _mm_shuffle_ps(D0,V11,_MM_SHUFFLE(0,2,1,2)); // V13 = D1X,D1Y,D2Z,D2Z V13 = _mm_shuffle_ps(D1,D2,_MM_SHUFFLE(2,2,1,0)); V02 = _mm_shuffle_ps(MT.r[3], MT.r[3],_MM_SHUFFLE(2,1,3,2)); V12 = _mm_shuffle_ps(D1,V13,_MM_SHUFFLE(2,1,0,3)); V03 = _mm_shuffle_ps(MT.r[2], MT.r[2],_MM_SHUFFLE(1,3,2,3)); V13 = _mm_shuffle_ps(D1,V13,_MM_SHUFFLE(0,2,1,2)); V00 = _mm_mul_ps(V00,V10); V01 = _mm_mul_ps(V01,V11); V02 = _mm_mul_ps(V02,V12); V03 = _mm_mul_ps(V03,V13); C0 = _mm_sub_ps(C0,V00); C2 = _mm_sub_ps(C2,V01); C4 = _mm_sub_ps(C4,V02); C6 = _mm_sub_ps(C6,V03); V00 = _mm_shuffle_ps(MT.r[1],MT.r[1],_MM_SHUFFLE(0,3,0,3)); // V10 = D0Z,D0Z,D2X,D2Y V10 = _mm_shuffle_ps(D0,D2,_MM_SHUFFLE(1,0,2,2)); V10 = _mm_shuffle_ps(V10,V10,_MM_SHUFFLE(0,2,3,0)); V01 = _mm_shuffle_ps(MT.r[0],MT.r[0],_MM_SHUFFLE(2,0,3,1)); // V11 = D0X,D0W,D2X,D2Y V11 = _mm_shuffle_ps(D0,D2,_MM_SHUFFLE(1,0,3,0)); V11 = _mm_shuffle_ps(V11,V11,_MM_SHUFFLE(2,1,0,3)); V02 = _mm_shuffle_ps(MT.r[3],MT.r[3],_MM_SHUFFLE(0,3,0,3)); // V12 = D1Z,D1Z,D2Z,D2W V12 = _mm_shuffle_ps(D1,D2,_MM_SHUFFLE(3,2,2,2)); V12 = _mm_shuffle_ps(V12,V12,_MM_SHUFFLE(0,2,3,0)); V03 = _mm_shuffle_ps(MT.r[2],MT.r[2],_MM_SHUFFLE(2,0,3,1)); // V13 = D1X,D1W,D2Z,D2W V13 = _mm_shuffle_ps(D1,D2,_MM_SHUFFLE(3,2,3,0)); V13 = _mm_shuffle_ps(V13,V13,_MM_SHUFFLE(2,1,0,3)); V00 = _mm_mul_ps(V00,V10); V01 = _mm_mul_ps(V01,V11); V02 = _mm_mul_ps(V02,V12); V03 = _mm_mul_ps(V03,V13); XMVECTOR C1 = _mm_sub_ps(C0,V00); C0 = _mm_add_ps(C0,V00); XMVECTOR C3 = _mm_add_ps(C2,V01); C2 = _mm_sub_ps(C2,V01); XMVECTOR C5 = _mm_sub_ps(C4,V02); C4 = _mm_add_ps(C4,V02); XMVECTOR C7 = _mm_add_ps(C6,V03); C6 = _mm_sub_ps(C6,V03); C0 = _mm_shuffle_ps(C0,C1,_MM_SHUFFLE(3,1,2,0)); C2 = _mm_shuffle_ps(C2,C3,_MM_SHUFFLE(3,1,2,0)); C4 = _mm_shuffle_ps(C4,C5,_MM_SHUFFLE(3,1,2,0)); C6 = _mm_shuffle_ps(C6,C7,_MM_SHUFFLE(3,1,2,0)); C0 = _mm_shuffle_ps(C0,C0,_MM_SHUFFLE(3,1,2,0)); C2 = _mm_shuffle_ps(C2,C2,_MM_SHUFFLE(3,1,2,0)); C4 = _mm_shuffle_ps(C4,C4,_MM_SHUFFLE(3,1,2,0)); C6 = _mm_shuffle_ps(C6,C6,_MM_SHUFFLE(3,1,2,0)); // Get the determinate XMVECTOR vTemp = XMVector4Dot(C0,MT.r[0]); if (pDeterminant) *pDeterminant = vTemp; vTemp = _mm_div_ps(g_XMOne,vTemp); XMMATRIX mResult; mResult.r[0] = _mm_mul_ps(C0,vTemp); mResult.r[1] = _mm_mul_ps(C2,vTemp); mResult.r[2] = _mm_mul_ps(C4,vTemp); mResult.r[3] = _mm_mul_ps(C6,vTemp); return mResult; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMVECTOR XMMatrixDeterminant ( CXMMATRIX M ) { #if defined(_XM_NO_INTRINSICS_) XMVECTOR V0, V1, V2, V3, V4, V5; XMVECTOR P0, P1, P2, R, S; XMVECTOR Result; static CONST XMVECTORU32 SwizzleYXXX = {XM_PERMUTE_0Y, XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_0X}; static CONST XMVECTORU32 SwizzleZZYY = {XM_PERMUTE_0Z, XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_0Y}; static CONST XMVECTORU32 SwizzleWWWZ = {XM_PERMUTE_0W, XM_PERMUTE_0W, XM_PERMUTE_0W, XM_PERMUTE_0Z}; static CONST XMVECTOR Sign = {1.0f, -1.0f, 1.0f, -1.0f}; V0 = XMVectorPermute(M.r[2], M.r[2], SwizzleYXXX.v); V1 = XMVectorPermute(M.r[3], M.r[3], SwizzleZZYY.v); V2 = XMVectorPermute(M.r[2], M.r[2], SwizzleYXXX.v); V3 = XMVectorPermute(M.r[3], M.r[3], SwizzleWWWZ.v); V4 = XMVectorPermute(M.r[2], M.r[2], SwizzleZZYY.v); V5 = XMVectorPermute(M.r[3], M.r[3], SwizzleWWWZ.v); P0 = XMVectorMultiply(V0, V1); P1 = XMVectorMultiply(V2, V3); P2 = XMVectorMultiply(V4, V5); V0 = XMVectorPermute(M.r[2], M.r[2], SwizzleZZYY.v); V1 = XMVectorPermute(M.r[3], M.r[3], SwizzleYXXX.v); V2 = XMVectorPermute(M.r[2], M.r[2], SwizzleWWWZ.v); V3 = XMVectorPermute(M.r[3], M.r[3], SwizzleYXXX.v); V4 = XMVectorPermute(M.r[2], M.r[2], SwizzleWWWZ.v); V5 = XMVectorPermute(M.r[3], M.r[3], SwizzleZZYY.v); P0 = XMVectorNegativeMultiplySubtract(V0, V1, P0); P1 = XMVectorNegativeMultiplySubtract(V2, V3, P1); P2 = XMVectorNegativeMultiplySubtract(V4, V5, P2); V0 = XMVectorPermute(M.r[1], M.r[1], SwizzleWWWZ.v); V1 = XMVectorPermute(M.r[1], M.r[1], SwizzleZZYY.v); V2 = XMVectorPermute(M.r[1], M.r[1], SwizzleYXXX.v); S = XMVectorMultiply(M.r[0], Sign); R = XMVectorMultiply(V0, P0); R = XMVectorNegativeMultiplySubtract(V1, P1, R); R = XMVectorMultiplyAdd(V2, P2, R); Result = XMVector4Dot(S, R); return Result; #elif defined(_XM_SSE_INTRINSICS_) XMVECTOR V0, V1, V2, V3, V4, V5; XMVECTOR P0, P1, P2, R, S; XMVECTOR Result; static CONST XMVECTORU32 SwizzleYXXX = {XM_PERMUTE_0Y, XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_0X}; static CONST XMVECTORU32 SwizzleZZYY = {XM_PERMUTE_0Z, XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_0Y}; static CONST XMVECTORU32 SwizzleWWWZ = {XM_PERMUTE_0W, XM_PERMUTE_0W, XM_PERMUTE_0W, XM_PERMUTE_0Z}; static CONST XMVECTORF32 Sign = {1.0f, -1.0f, 1.0f, -1.0f}; V0 = XMVectorPermute(M.r[2], M.r[2], SwizzleYXXX); V1 = XMVectorPermute(M.r[3], M.r[3], SwizzleZZYY); V2 = XMVectorPermute(M.r[2], M.r[2], SwizzleYXXX); V3 = XMVectorPermute(M.r[3], M.r[3], SwizzleWWWZ); V4 = XMVectorPermute(M.r[2], M.r[2], SwizzleZZYY); V5 = XMVectorPermute(M.r[3], M.r[3], SwizzleWWWZ); P0 = _mm_mul_ps(V0, V1); P1 = _mm_mul_ps(V2, V3); P2 = _mm_mul_ps(V4, V5); V0 = XMVectorPermute(M.r[2], M.r[2], SwizzleZZYY); V1 = XMVectorPermute(M.r[3], M.r[3], SwizzleYXXX); V2 = XMVectorPermute(M.r[2], M.r[2], SwizzleWWWZ); V3 = XMVectorPermute(M.r[3], M.r[3], SwizzleYXXX); V4 = XMVectorPermute(M.r[2], M.r[2], SwizzleWWWZ); V5 = XMVectorPermute(M.r[3], M.r[3], SwizzleZZYY); P0 = XMVectorNegativeMultiplySubtract(V0, V1, P0); P1 = XMVectorNegativeMultiplySubtract(V2, V3, P1); P2 = XMVectorNegativeMultiplySubtract(V4, V5, P2); V0 = XMVectorPermute(M.r[1], M.r[1], SwizzleWWWZ); V1 = XMVectorPermute(M.r[1], M.r[1], SwizzleZZYY); V2 = XMVectorPermute(M.r[1], M.r[1], SwizzleYXXX); S = _mm_mul_ps(M.r[0], Sign); R = _mm_mul_ps(V0, P0); R = XMVectorNegativeMultiplySubtract(V1, P1, R); R = XMVectorMultiplyAdd(V2, P2, R); Result = XMVector4Dot(S, R); return Result; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } #undef XMRANKDECOMPOSE #undef XM_DECOMP_EPSILON #define XMRANKDECOMPOSE(a, b, c, x, y, z) \ if((x) < (y)) \ { \ if((y) < (z)) \ { \ (a) = 2; \ (b) = 1; \ (c) = 0; \ } \ else \ { \ (a) = 1; \ \ if((x) < (z)) \ { \ (b) = 2; \ (c) = 0; \ } \ else \ { \ (b) = 0; \ (c) = 2; \ } \ } \ } \ else \ { \ if((x) < (z)) \ { \ (a) = 2; \ (b) = 0; \ (c) = 1; \ } \ else \ { \ (a) = 0; \ \ if((y) < (z)) \ { \ (b) = 2; \ (c) = 1; \ } \ else \ { \ (b) = 1; \ (c) = 2; \ } \ } \ } #define XM_DECOMP_EPSILON 0.0001f XMINLINE BOOL XMMatrixDecompose ( XMVECTOR *outScale, XMVECTOR *outRotQuat, XMVECTOR *outTrans, CXMMATRIX M ) { FLOAT fDet; FLOAT *pfScales; XMVECTOR *ppvBasis[3]; XMMATRIX matTemp; UINT a, b, c; static const XMVECTOR *pvCanonicalBasis[3] = { &g_XMIdentityR0.v, &g_XMIdentityR1.v, &g_XMIdentityR2.v }; XMASSERT( outScale != NULL ); XMASSERT( outRotQuat != NULL ); XMASSERT( outTrans != NULL ); // Get the translation outTrans[0] = M.r[3]; ppvBasis[0] = &matTemp.r[0]; ppvBasis[1] = &matTemp.r[1]; ppvBasis[2] = &matTemp.r[2]; matTemp.r[0] = M.r[0]; matTemp.r[1] = M.r[1]; matTemp.r[2] = M.r[2]; matTemp.r[3] = g_XMIdentityR3.v; pfScales = (FLOAT *)outScale; XMVectorGetXPtr(&pfScales[0],XMVector3Length(ppvBasis[0][0])); XMVectorGetXPtr(&pfScales[1],XMVector3Length(ppvBasis[1][0])); XMVectorGetXPtr(&pfScales[2],XMVector3Length(ppvBasis[2][0])); pfScales[3] = 0.f; XMRANKDECOMPOSE(a, b, c, pfScales[0], pfScales[1], pfScales[2]) if(pfScales[a] < XM_DECOMP_EPSILON) { ppvBasis[a][0] = pvCanonicalBasis[a][0]; } ppvBasis[a][0] = XMVector3Normalize(ppvBasis[a][0]); if(pfScales[b] < XM_DECOMP_EPSILON) { UINT aa, bb, cc; FLOAT fAbsX, fAbsY, fAbsZ; fAbsX = fabsf(XMVectorGetX(ppvBasis[a][0])); fAbsY = fabsf(XMVectorGetY(ppvBasis[a][0])); fAbsZ = fabsf(XMVectorGetZ(ppvBasis[a][0])); XMRANKDECOMPOSE(aa, bb, cc, fAbsX, fAbsY, fAbsZ) ppvBasis[b][0] = XMVector3Cross(ppvBasis[a][0],pvCanonicalBasis[cc][0]); } ppvBasis[b][0] = XMVector3Normalize(ppvBasis[b][0]); if(pfScales[c] < XM_DECOMP_EPSILON) { ppvBasis[c][0] = XMVector3Cross(ppvBasis[a][0],ppvBasis[b][0]); } ppvBasis[c][0] = XMVector3Normalize(ppvBasis[c][0]); fDet = XMVectorGetX(XMMatrixDeterminant(matTemp)); // use Kramer's rule to check for handedness of coordinate system if(fDet < 0.0f) { // switch coordinate system by negating the scale and inverting the basis vector on the x-axis pfScales[a] = -pfScales[a]; ppvBasis[a][0] = XMVectorNegate(ppvBasis[a][0]); fDet = -fDet; } fDet -= 1.0f; fDet *= fDet; if(XM_DECOMP_EPSILON < fDet) { // Non-SRT matrix encountered return FALSE; } // generate the quaternion from the matrix outRotQuat[0] = XMQuaternionRotationMatrix(matTemp); return TRUE; } #undef XMRANKDECOMPOSE #undef XM_DECOMP_EPSILON //------------------------------------------------------------------------------ // Transformation operations //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixIdentity() { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; M.r[0] = g_XMIdentityR0.v; M.r[1] = g_XMIdentityR1.v; M.r[2] = g_XMIdentityR2.v; M.r[3] = g_XMIdentityR3.v; return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; M.r[0] = g_XMIdentityR0; M.r[1] = g_XMIdentityR1; M.r[2] = g_XMIdentityR2; M.r[3] = g_XMIdentityR3; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixSet ( FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03, FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13, FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23, FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33 ) { XMMATRIX M; M.r[0] = XMVectorSet(m00, m01, m02, m03); M.r[1] = XMVectorSet(m10, m11, m12, m13); M.r[2] = XMVectorSet(m20, m21, m22, m23); M.r[3] = XMVectorSet(m30, m31, m32, m33); return M; } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixTranslation ( FLOAT OffsetX, FLOAT OffsetY, FLOAT OffsetZ ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; M.m[0][0] = 1.0f; M.m[0][1] = 0.0f; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = 1.0f; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = 0.0f; M.m[2][1] = 0.0f; M.m[2][2] = 1.0f; M.m[2][3] = 0.0f; M.m[3][0] = OffsetX; M.m[3][1] = OffsetY; M.m[3][2] = OffsetZ; M.m[3][3] = 1.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; M.r[0] = g_XMIdentityR0; M.r[1] = g_XMIdentityR1; M.r[2] = g_XMIdentityR2; M.r[3] = _mm_set_ps(1.0f,OffsetZ,OffsetY,OffsetX); return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixTranslationFromVector ( FXMVECTOR Offset ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; M.m[0][0] = 1.0f; M.m[0][1] = 0.0f; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = 1.0f; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = 0.0f; M.m[2][1] = 0.0f; M.m[2][2] = 1.0f; M.m[2][3] = 0.0f; M.m[3][0] = Offset.vector4_f32[0]; M.m[3][1] = Offset.vector4_f32[1]; M.m[3][2] = Offset.vector4_f32[2]; M.m[3][3] = 1.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) XMVECTOR vTemp = _mm_and_ps(Offset,g_XMMask3); vTemp = _mm_or_ps(vTemp,g_XMIdentityR3); XMMATRIX M; M.r[0] = g_XMIdentityR0; M.r[1] = g_XMIdentityR1; M.r[2] = g_XMIdentityR2; M.r[3] = vTemp; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixScaling ( FLOAT ScaleX, FLOAT ScaleY, FLOAT ScaleZ ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; M.r[0] = XMVectorSet(ScaleX, 0.0f, 0.0f, 0.0f); M.r[1] = XMVectorSet(0.0f, ScaleY, 0.0f, 0.0f); M.r[2] = XMVectorSet(0.0f, 0.0f, ScaleZ, 0.0f); M.r[3] = g_XMIdentityR3.v; return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; M.r[0] = _mm_set_ps( 0, 0, 0, ScaleX ); M.r[1] = _mm_set_ps( 0, 0, ScaleY, 0 ); M.r[2] = _mm_set_ps( 0, ScaleZ, 0, 0 ); M.r[3] = g_XMIdentityR3; return M; #elif defined(XM_NO_MISALIGNED_VECTOR_ACCESS) #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixScalingFromVector ( FXMVECTOR Scale ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; M.m[0][0] = Scale.vector4_f32[0]; M.m[0][1] = 0.0f; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = Scale.vector4_f32[1]; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = 0.0f; M.m[2][1] = 0.0f; M.m[2][2] = Scale.vector4_f32[2]; M.m[2][3] = 0.0f; M.m[3][0] = 0.0f; M.m[3][1] = 0.0f; M.m[3][2] = 0.0f; M.m[3][3] = 1.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; M.r[0] = _mm_and_ps(Scale,g_XMMaskX); M.r[1] = _mm_and_ps(Scale,g_XMMaskY); M.r[2] = _mm_and_ps(Scale,g_XMMaskZ); M.r[3] = g_XMIdentityR3; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixRotationX ( FLOAT Angle ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; FLOAT fSinAngle = sinf(Angle); FLOAT fCosAngle = cosf(Angle); M.m[0][0] = 1.0f; M.m[0][1] = 0.0f; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = fCosAngle; M.m[1][2] = fSinAngle; M.m[1][3] = 0.0f; M.m[2][0] = 0.0f; M.m[2][1] = -fSinAngle; M.m[2][2] = fCosAngle; M.m[2][3] = 0.0f; M.m[3][0] = 0.0f; M.m[3][1] = 0.0f; M.m[3][2] = 0.0f; M.m[3][3] = 1.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) FLOAT SinAngle = sinf(Angle); FLOAT CosAngle = cosf(Angle); XMVECTOR vSin = _mm_set_ss(SinAngle); XMVECTOR vCos = _mm_set_ss(CosAngle); // x = 0,y = cos,z = sin, w = 0 vCos = _mm_shuffle_ps(vCos,vSin,_MM_SHUFFLE(3,0,0,3)); XMMATRIX M; M.r[0] = g_XMIdentityR0; M.r[1] = vCos; // x = 0,y = sin,z = cos, w = 0 vCos = _mm_shuffle_ps(vCos,vCos,_MM_SHUFFLE(3,1,2,0)); // x = 0,y = -sin,z = cos, w = 0 vCos = _mm_mul_ps(vCos,g_XMNegateY); M.r[2] = vCos; M.r[3] = g_XMIdentityR3; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixRotationY ( FLOAT Angle ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; FLOAT fSinAngle = sinf(Angle); FLOAT fCosAngle = cosf(Angle); M.m[0][0] = fCosAngle; M.m[0][1] = 0.0f; M.m[0][2] = -fSinAngle; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = 1.0f; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = fSinAngle; M.m[2][1] = 0.0f; M.m[2][2] = fCosAngle; M.m[2][3] = 0.0f; M.m[3][0] = 0.0f; M.m[3][1] = 0.0f; M.m[3][2] = 0.0f; M.m[3][3] = 1.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) FLOAT SinAngle = sinf(Angle); FLOAT CosAngle = cosf(Angle); XMVECTOR vSin = _mm_set_ss(SinAngle); XMVECTOR vCos = _mm_set_ss(CosAngle); // x = sin,y = 0,z = cos, w = 0 vSin = _mm_shuffle_ps(vSin,vCos,_MM_SHUFFLE(3,0,3,0)); XMMATRIX M; M.r[2] = vSin; M.r[1] = g_XMIdentityR1; // x = cos,y = 0,z = sin, w = 0 vSin = _mm_shuffle_ps(vSin,vSin,_MM_SHUFFLE(3,0,1,2)); // x = cos,y = 0,z = -sin, w = 0 vSin = _mm_mul_ps(vSin,g_XMNegateZ); M.r[0] = vSin; M.r[3] = g_XMIdentityR3; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixRotationZ ( FLOAT Angle ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; FLOAT fSinAngle = sinf(Angle); FLOAT fCosAngle = cosf(Angle); M.m[0][0] = fCosAngle; M.m[0][1] = fSinAngle; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = -fSinAngle; M.m[1][1] = fCosAngle; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = 0.0f; M.m[2][1] = 0.0f; M.m[2][2] = 1.0f; M.m[2][3] = 0.0f; M.m[3][0] = 0.0f; M.m[3][1] = 0.0f; M.m[3][2] = 0.0f; M.m[3][3] = 1.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) FLOAT SinAngle = sinf(Angle); FLOAT CosAngle = cosf(Angle); XMVECTOR vSin = _mm_set_ss(SinAngle); XMVECTOR vCos = _mm_set_ss(CosAngle); // x = cos,y = sin,z = 0, w = 0 vCos = _mm_unpacklo_ps(vCos,vSin); XMMATRIX M; M.r[0] = vCos; // x = sin,y = cos,z = 0, w = 0 vCos = _mm_shuffle_ps(vCos,vCos,_MM_SHUFFLE(3,2,0,1)); // x = cos,y = -sin,z = 0, w = 0 vCos = _mm_mul_ps(vCos,g_XMNegateX); M.r[1] = vCos; M.r[2] = g_XMIdentityR2; M.r[3] = g_XMIdentityR3; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixRotationRollPitchYaw ( FLOAT Pitch, FLOAT Yaw, FLOAT Roll ) { XMVECTOR Angles; XMMATRIX M; Angles = XMVectorSet(Pitch, Yaw, Roll, 0.0f); M = XMMatrixRotationRollPitchYawFromVector(Angles); return M; } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixRotationRollPitchYawFromVector ( FXMVECTOR Angles // ) { XMVECTOR Q; XMMATRIX M; Q = XMQuaternionRotationRollPitchYawFromVector(Angles); M = XMMatrixRotationQuaternion(Q); return M; } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixRotationNormal ( FXMVECTOR NormalAxis, FLOAT Angle ) { #if defined(_XM_NO_INTRINSICS_) XMVECTOR A; XMVECTOR N0, N1; XMVECTOR V0, V1, V2; XMVECTOR R0, R1, R2; XMVECTOR C0, C1, C2; XMMATRIX M; static CONST XMVECTORU32 SwizzleYZXW = {XM_PERMUTE_0Y, XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0W}; static CONST XMVECTORU32 SwizzleZXYW = {XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_0W}; static CONST XMVECTORU32 Permute0Z1Y1Z0X = {XM_PERMUTE_0Z, XM_PERMUTE_1Y, XM_PERMUTE_1Z, XM_PERMUTE_0X}; static CONST XMVECTORU32 Permute0Y1X0Y1X = {XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_0Y, XM_PERMUTE_1X}; static CONST XMVECTORU32 Permute0X1X1Y0W = {XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0W}; static CONST XMVECTORU32 Permute1Z0Y1W0W = {XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_1W, XM_PERMUTE_0W}; static CONST XMVECTORU32 Permute1X1Y0Z0W = {XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z, XM_PERMUTE_0W}; FLOAT fSinAngle = sinf(Angle); FLOAT fCosAngle = cosf(Angle); A = XMVectorSet(fSinAngle, fCosAngle, 1.0f - fCosAngle, 0.0f); C2 = XMVectorSplatZ(A); C1 = XMVectorSplatY(A); C0 = XMVectorSplatX(A); N0 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleYZXW.v); N1 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleZXYW.v); V0 = XMVectorMultiply(C2, N0); V0 = XMVectorMultiply(V0, N1); R0 = XMVectorMultiply(C2, NormalAxis); R0 = XMVectorMultiplyAdd(R0, NormalAxis, C1); R1 = XMVectorMultiplyAdd(C0, NormalAxis, V0); R2 = XMVectorNegativeMultiplySubtract(C0, NormalAxis, V0); V0 = XMVectorSelect(A, R0, g_XMSelect1110.v); V1 = XMVectorPermute(R1, R2, Permute0Z1Y1Z0X.v); V2 = XMVectorPermute(R1, R2, Permute0Y1X0Y1X.v); M.r[0] = XMVectorPermute(V0, V1, Permute0X1X1Y0W.v); M.r[1] = XMVectorPermute(V0, V1, Permute1Z0Y1W0W.v); M.r[2] = XMVectorPermute(V0, V2, Permute1X1Y0Z0W.v); M.r[3] = g_XMIdentityR3.v; return M; #elif defined(_XM_SSE_INTRINSICS_) XMVECTOR N0, N1; XMVECTOR V0, V1, V2; XMVECTOR R0, R1, R2; XMVECTOR C0, C1, C2; XMMATRIX M; FLOAT fSinAngle = sinf(Angle); FLOAT fCosAngle = cosf(Angle); C2 = _mm_set_ps1(1.0f - fCosAngle); C1 = _mm_set_ps1(fCosAngle); C0 = _mm_set_ps1(fSinAngle); N0 = _mm_shuffle_ps(NormalAxis,NormalAxis,_MM_SHUFFLE(3,0,2,1)); // N0 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleYZXW); N1 = _mm_shuffle_ps(NormalAxis,NormalAxis,_MM_SHUFFLE(3,1,0,2)); // N1 = XMVectorPermute(NormalAxis, NormalAxis, SwizzleZXYW); V0 = _mm_mul_ps(C2, N0); V0 = _mm_mul_ps(V0, N1); R0 = _mm_mul_ps(C2, NormalAxis); R0 = _mm_mul_ps(R0, NormalAxis); R0 = _mm_add_ps(R0, C1); R1 = _mm_mul_ps(C0, NormalAxis); R1 = _mm_add_ps(R1, V0); R2 = _mm_mul_ps(C0, NormalAxis); R2 = _mm_sub_ps(V0,R2); V0 = _mm_and_ps(R0,g_XMMask3); // V0 = XMVectorSelect(A, R0, g_XMSelect1110); V1 = _mm_shuffle_ps(R1,R2,_MM_SHUFFLE(2,1,2,0)); V1 = _mm_shuffle_ps(V1,V1,_MM_SHUFFLE(0,3,2,1)); // V1 = XMVectorPermute(R1, R2, Permute0Z1Y1Z0X); V2 = _mm_shuffle_ps(R1,R2,_MM_SHUFFLE(0,0,1,1)); V2 = _mm_shuffle_ps(V2,V2,_MM_SHUFFLE(2,0,2,0)); // V2 = XMVectorPermute(R1, R2, Permute0Y1X0Y1X); R2 = _mm_shuffle_ps(V0,V1,_MM_SHUFFLE(1,0,3,0)); R2 = _mm_shuffle_ps(R2,R2,_MM_SHUFFLE(1,3,2,0)); M.r[0] = R2; // M.r[0] = XMVectorPermute(V0, V1, Permute0X1X1Y0W); R2 = _mm_shuffle_ps(V0,V1,_MM_SHUFFLE(3,2,3,1)); R2 = _mm_shuffle_ps(R2,R2,_MM_SHUFFLE(1,3,0,2)); M.r[1] = R2; // M.r[1] = XMVectorPermute(V0, V1, Permute1Z0Y1W0W); V2 = _mm_shuffle_ps(V2,V0,_MM_SHUFFLE(3,2,1,0)); // R2 = _mm_shuffle_ps(R2,R2,_MM_SHUFFLE(3,2,1,0)); M.r[2] = V2; // M.r[2] = XMVectorPermute(V0, V2, Permute1X1Y0Z0W); M.r[3] = g_XMIdentityR3; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixRotationAxis ( FXMVECTOR Axis, FLOAT Angle ) { #if defined(_XM_NO_INTRINSICS_) XMVECTOR Normal; XMMATRIX M; XMASSERT(!XMVector3Equal(Axis, XMVectorZero())); XMASSERT(!XMVector3IsInfinite(Axis)); Normal = XMVector3Normalize(Axis); M = XMMatrixRotationNormal(Normal, Angle); return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMVector3Equal(Axis, XMVectorZero())); XMASSERT(!XMVector3IsInfinite(Axis)); XMVECTOR Normal = XMVector3Normalize(Axis); XMMATRIX M = XMMatrixRotationNormal(Normal, Angle); return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixRotationQuaternion ( FXMVECTOR Quaternion ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; XMVECTOR Q0, Q1; XMVECTOR V0, V1, V2; XMVECTOR R0, R1, R2; static CONST XMVECTOR Constant1110 = {1.0f, 1.0f, 1.0f, 0.0f}; static CONST XMVECTORU32 SwizzleXXYW = {XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_0Y, XM_PERMUTE_0W}; static CONST XMVECTORU32 SwizzleZYZW = {XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_0Z, XM_PERMUTE_0W}; static CONST XMVECTORU32 SwizzleYZXW = {XM_PERMUTE_0Y, XM_PERMUTE_0Z, XM_PERMUTE_0X, XM_PERMUTE_0W}; static CONST XMVECTORU32 Permute0Y0X0X1W = {XM_PERMUTE_0Y, XM_PERMUTE_0X, XM_PERMUTE_0X, XM_PERMUTE_1W}; static CONST XMVECTORU32 Permute0Z0Z0Y1W = {XM_PERMUTE_0Z, XM_PERMUTE_0Z, XM_PERMUTE_0Y, XM_PERMUTE_1W}; static CONST XMVECTORU32 Permute0Y1X1Y0Z = {XM_PERMUTE_0Y, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z}; static CONST XMVECTORU32 Permute0X1Z0X1Z = {XM_PERMUTE_0X, XM_PERMUTE_1Z, XM_PERMUTE_0X, XM_PERMUTE_1Z}; static CONST XMVECTORU32 Permute0X1X1Y0W = {XM_PERMUTE_0X, XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0W}; static CONST XMVECTORU32 Permute1Z0Y1W0W = {XM_PERMUTE_1Z, XM_PERMUTE_0Y, XM_PERMUTE_1W, XM_PERMUTE_0W}; static CONST XMVECTORU32 Permute1X1Y0Z0W = {XM_PERMUTE_1X, XM_PERMUTE_1Y, XM_PERMUTE_0Z, XM_PERMUTE_0W}; Q0 = XMVectorAdd(Quaternion, Quaternion); Q1 = XMVectorMultiply(Quaternion, Q0); V0 = XMVectorPermute(Q1, Constant1110, Permute0Y0X0X1W.v); V1 = XMVectorPermute(Q1, Constant1110, Permute0Z0Z0Y1W.v); R0 = XMVectorSubtract(Constant1110, V0); R0 = XMVectorSubtract(R0, V1); V0 = XMVectorPermute(Quaternion, Quaternion, SwizzleXXYW.v); V1 = XMVectorPermute(Q0, Q0, SwizzleZYZW.v); V0 = XMVectorMultiply(V0, V1); V1 = XMVectorSplatW(Quaternion); V2 = XMVectorPermute(Q0, Q0, SwizzleYZXW.v); V1 = XMVectorMultiply(V1, V2); R1 = XMVectorAdd(V0, V1); R2 = XMVectorSubtract(V0, V1); V0 = XMVectorPermute(R1, R2, Permute0Y1X1Y0Z.v); V1 = XMVectorPermute(R1, R2, Permute0X1Z0X1Z.v); M.r[0] = XMVectorPermute(R0, V0, Permute0X1X1Y0W.v); M.r[1] = XMVectorPermute(R0, V0, Permute1Z0Y1W0W.v); M.r[2] = XMVectorPermute(R0, V1, Permute1X1Y0Z0W.v); M.r[3] = g_XMIdentityR3.v; return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; XMVECTOR Q0, Q1; XMVECTOR V0, V1, V2; XMVECTOR R0, R1, R2; static CONST XMVECTORF32 Constant1110 = {1.0f, 1.0f, 1.0f, 0.0f}; Q0 = _mm_add_ps(Quaternion,Quaternion); Q1 = _mm_mul_ps(Quaternion,Q0); V0 = _mm_shuffle_ps(Q1,Q1,_MM_SHUFFLE(3,0,0,1)); V0 = _mm_and_ps(V0,g_XMMask3); // V0 = XMVectorPermute(Q1, Constant1110,Permute0Y0X0X1W); V1 = _mm_shuffle_ps(Q1,Q1,_MM_SHUFFLE(3,1,2,2)); V1 = _mm_and_ps(V1,g_XMMask3); // V1 = XMVectorPermute(Q1, Constant1110,Permute0Z0Z0Y1W); R0 = _mm_sub_ps(Constant1110,V0); R0 = _mm_sub_ps(R0, V1); V0 = _mm_shuffle_ps(Quaternion,Quaternion,_MM_SHUFFLE(3,1,0,0)); // V0 = XMVectorPermute(Quaternion, Quaternion,SwizzleXXYW); V1 = _mm_shuffle_ps(Q0,Q0,_MM_SHUFFLE(3,2,1,2)); // V1 = XMVectorPermute(Q0, Q0,SwizzleZYZW); V0 = _mm_mul_ps(V0, V1); V1 = _mm_shuffle_ps(Quaternion,Quaternion,_MM_SHUFFLE(3,3,3,3)); // V1 = XMVectorSplatW(Quaternion); V2 = _mm_shuffle_ps(Q0,Q0,_MM_SHUFFLE(3,0,2,1)); // V2 = XMVectorPermute(Q0, Q0,SwizzleYZXW); V1 = _mm_mul_ps(V1, V2); R1 = _mm_add_ps(V0, V1); R2 = _mm_sub_ps(V0, V1); V0 = _mm_shuffle_ps(R1,R2,_MM_SHUFFLE(1,0,2,1)); V0 = _mm_shuffle_ps(V0,V0,_MM_SHUFFLE(1,3,2,0)); // V0 = XMVectorPermute(R1, R2,Permute0Y1X1Y0Z); V1 = _mm_shuffle_ps(R1,R2,_MM_SHUFFLE(2,2,0,0)); V1 = _mm_shuffle_ps(V1,V1,_MM_SHUFFLE(2,0,2,0)); // V1 = XMVectorPermute(R1, R2,Permute0X1Z0X1Z); Q1 = _mm_shuffle_ps(R0,V0,_MM_SHUFFLE(1,0,3,0)); Q1 = _mm_shuffle_ps(Q1,Q1,_MM_SHUFFLE(1,3,2,0)); M.r[0] = Q1; // M.r[0] = XMVectorPermute(R0, V0,Permute0X1X1Y0W); Q1 = _mm_shuffle_ps(R0,V0,_MM_SHUFFLE(3,2,3,1)); Q1 = _mm_shuffle_ps(Q1,Q1,_MM_SHUFFLE(1,3,0,2)); M.r[1] = Q1; // M.r[1] = XMVectorPermute(R0, V0,Permute1Z0Y1W0W); Q1 = _mm_shuffle_ps(V1,R0,_MM_SHUFFLE(3,2,1,0)); M.r[2] = Q1; // M.r[2] = XMVectorPermute(R0, V1,Permute1X1Y0Z0W); M.r[3] = g_XMIdentityR3; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixTransformation2D ( FXMVECTOR ScalingOrigin, FLOAT ScalingOrientation, FXMVECTOR Scaling, FXMVECTOR RotationOrigin, FLOAT Rotation, CXMVECTOR Translation ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; XMVECTOR VScaling; XMVECTOR NegScalingOrigin; XMVECTOR VScalingOrigin; XMMATRIX MScalingOriginI; XMMATRIX MScalingOrientation; XMMATRIX MScalingOrientationT; XMMATRIX MScaling; XMVECTOR VRotationOrigin; XMMATRIX MRotation; XMVECTOR VTranslation; // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation * // MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation; VScalingOrigin = XMVectorSelect(g_XMSelect1100.v, ScalingOrigin, g_XMSelect1100.v); NegScalingOrigin = XMVectorNegate(VScalingOrigin); MScalingOriginI = XMMatrixTranslationFromVector(NegScalingOrigin); MScalingOrientation = XMMatrixRotationZ(ScalingOrientation); MScalingOrientationT = XMMatrixTranspose(MScalingOrientation); VScaling = XMVectorSelect(g_XMOne.v, Scaling, g_XMSelect1100.v); MScaling = XMMatrixScalingFromVector(VScaling); VRotationOrigin = XMVectorSelect(g_XMSelect1100.v, RotationOrigin, g_XMSelect1100.v); MRotation = XMMatrixRotationZ(Rotation); VTranslation = XMVectorSelect(g_XMSelect1100.v, Translation,g_XMSelect1100.v); M = XMMatrixMultiply(MScalingOriginI, MScalingOrientationT); M = XMMatrixMultiply(M, MScaling); M = XMMatrixMultiply(M, MScalingOrientation); M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin); M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin); M = XMMatrixMultiply(M, MRotation); M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin); M.r[3] = XMVectorAdd(M.r[3], VTranslation); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; XMVECTOR VScaling; XMVECTOR NegScalingOrigin; XMVECTOR VScalingOrigin; XMMATRIX MScalingOriginI; XMMATRIX MScalingOrientation; XMMATRIX MScalingOrientationT; XMMATRIX MScaling; XMVECTOR VRotationOrigin; XMMATRIX MRotation; XMVECTOR VTranslation; // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation * // MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation; static const XMVECTORU32 Mask2 = {0xFFFFFFFF,0xFFFFFFFF,0,0}; static const XMVECTORF32 ZWOne = {0,0,1.0f,1.0f}; VScalingOrigin = _mm_and_ps(ScalingOrigin, Mask2); NegScalingOrigin = XMVectorNegate(VScalingOrigin); MScalingOriginI = XMMatrixTranslationFromVector(NegScalingOrigin); MScalingOrientation = XMMatrixRotationZ(ScalingOrientation); MScalingOrientationT = XMMatrixTranspose(MScalingOrientation); VScaling = _mm_and_ps(Scaling, Mask2); VScaling = _mm_or_ps(VScaling,ZWOne); MScaling = XMMatrixScalingFromVector(VScaling); VRotationOrigin = _mm_and_ps(RotationOrigin, Mask2); MRotation = XMMatrixRotationZ(Rotation); VTranslation = _mm_and_ps(Translation, Mask2); M = XMMatrixMultiply(MScalingOriginI, MScalingOrientationT); M = XMMatrixMultiply(M, MScaling); M = XMMatrixMultiply(M, MScalingOrientation); M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin); M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin); M = XMMatrixMultiply(M, MRotation); M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin); M.r[3] = XMVectorAdd(M.r[3], VTranslation); return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixTransformation ( FXMVECTOR ScalingOrigin, FXMVECTOR ScalingOrientationQuaternion, FXMVECTOR Scaling, CXMVECTOR RotationOrigin, CXMVECTOR RotationQuaternion, CXMVECTOR Translation ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; XMVECTOR NegScalingOrigin; XMVECTOR VScalingOrigin; XMMATRIX MScalingOriginI; XMMATRIX MScalingOrientation; XMMATRIX MScalingOrientationT; XMMATRIX MScaling; XMVECTOR VRotationOrigin; XMMATRIX MRotation; XMVECTOR VTranslation; // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation * // MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation; VScalingOrigin = XMVectorSelect(g_XMSelect1110.v, ScalingOrigin, g_XMSelect1110.v); NegScalingOrigin = XMVectorNegate(ScalingOrigin); MScalingOriginI = XMMatrixTranslationFromVector(NegScalingOrigin); MScalingOrientation = XMMatrixRotationQuaternion(ScalingOrientationQuaternion); MScalingOrientationT = XMMatrixTranspose(MScalingOrientation); MScaling = XMMatrixScalingFromVector(Scaling); VRotationOrigin = XMVectorSelect(g_XMSelect1110.v, RotationOrigin, g_XMSelect1110.v); MRotation = XMMatrixRotationQuaternion(RotationQuaternion); VTranslation = XMVectorSelect(g_XMSelect1110.v, Translation, g_XMSelect1110.v); M = XMMatrixMultiply(MScalingOriginI, MScalingOrientationT); M = XMMatrixMultiply(M, MScaling); M = XMMatrixMultiply(M, MScalingOrientation); M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin); M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin); M = XMMatrixMultiply(M, MRotation); M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin); M.r[3] = XMVectorAdd(M.r[3], VTranslation); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; XMVECTOR NegScalingOrigin; XMVECTOR VScalingOrigin; XMMATRIX MScalingOriginI; XMMATRIX MScalingOrientation; XMMATRIX MScalingOrientationT; XMMATRIX MScaling; XMVECTOR VRotationOrigin; XMMATRIX MRotation; XMVECTOR VTranslation; // M = Inverse(MScalingOrigin) * Transpose(MScalingOrientation) * MScaling * MScalingOrientation * // MScalingOrigin * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation; VScalingOrigin = _mm_and_ps(ScalingOrigin,g_XMMask3); NegScalingOrigin = XMVectorNegate(ScalingOrigin); MScalingOriginI = XMMatrixTranslationFromVector(NegScalingOrigin); MScalingOrientation = XMMatrixRotationQuaternion(ScalingOrientationQuaternion); MScalingOrientationT = XMMatrixTranspose(MScalingOrientation); MScaling = XMMatrixScalingFromVector(Scaling); VRotationOrigin = _mm_and_ps(RotationOrigin,g_XMMask3); MRotation = XMMatrixRotationQuaternion(RotationQuaternion); VTranslation = _mm_and_ps(Translation,g_XMMask3); M = XMMatrixMultiply(MScalingOriginI, MScalingOrientationT); M = XMMatrixMultiply(M, MScaling); M = XMMatrixMultiply(M, MScalingOrientation); M.r[3] = XMVectorAdd(M.r[3], VScalingOrigin); M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin); M = XMMatrixMultiply(M, MRotation); M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin); M.r[3] = XMVectorAdd(M.r[3], VTranslation); return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixAffineTransformation2D ( FXMVECTOR Scaling, FXMVECTOR RotationOrigin, FLOAT Rotation, FXMVECTOR Translation ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; XMVECTOR VScaling; XMMATRIX MScaling; XMVECTOR VRotationOrigin; XMMATRIX MRotation; XMVECTOR VTranslation; // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation; VScaling = XMVectorSelect(g_XMOne.v, Scaling, g_XMSelect1100.v); MScaling = XMMatrixScalingFromVector(VScaling); VRotationOrigin = XMVectorSelect(g_XMSelect1100.v, RotationOrigin, g_XMSelect1100.v); MRotation = XMMatrixRotationZ(Rotation); VTranslation = XMVectorSelect(g_XMSelect1100.v, Translation,g_XMSelect1100.v); M = MScaling; M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin); M = XMMatrixMultiply(M, MRotation); M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin); M.r[3] = XMVectorAdd(M.r[3], VTranslation); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; XMVECTOR VScaling; XMMATRIX MScaling; XMVECTOR VRotationOrigin; XMMATRIX MRotation; XMVECTOR VTranslation; static const XMVECTORU32 Mask2 = {0xFFFFFFFFU,0xFFFFFFFFU,0,0}; static const XMVECTORF32 ZW1 = {0,0,1.0f,1.0f}; // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation; VScaling = _mm_and_ps(Scaling, Mask2); VScaling = _mm_or_ps(VScaling, ZW1); MScaling = XMMatrixScalingFromVector(VScaling); VRotationOrigin = _mm_and_ps(RotationOrigin, Mask2); MRotation = XMMatrixRotationZ(Rotation); VTranslation = _mm_and_ps(Translation, Mask2); M = MScaling; M.r[3] = _mm_sub_ps(M.r[3], VRotationOrigin); M = XMMatrixMultiply(M, MRotation); M.r[3] = _mm_add_ps(M.r[3], VRotationOrigin); M.r[3] = _mm_add_ps(M.r[3], VTranslation); return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixAffineTransformation ( FXMVECTOR Scaling, FXMVECTOR RotationOrigin, FXMVECTOR RotationQuaternion, CXMVECTOR Translation ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; XMMATRIX MScaling; XMVECTOR VRotationOrigin; XMMATRIX MRotation; XMVECTOR VTranslation; // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation; MScaling = XMMatrixScalingFromVector(Scaling); VRotationOrigin = XMVectorSelect(g_XMSelect1110.v, RotationOrigin,g_XMSelect1110.v); MRotation = XMMatrixRotationQuaternion(RotationQuaternion); VTranslation = XMVectorSelect(g_XMSelect1110.v, Translation,g_XMSelect1110.v); M = MScaling; M.r[3] = XMVectorSubtract(M.r[3], VRotationOrigin); M = XMMatrixMultiply(M, MRotation); M.r[3] = XMVectorAdd(M.r[3], VRotationOrigin); M.r[3] = XMVectorAdd(M.r[3], VTranslation); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; XMMATRIX MScaling; XMVECTOR VRotationOrigin; XMMATRIX MRotation; XMVECTOR VTranslation; // M = MScaling * Inverse(MRotationOrigin) * MRotation * MRotationOrigin * MTranslation; MScaling = XMMatrixScalingFromVector(Scaling); VRotationOrigin = _mm_and_ps(RotationOrigin,g_XMMask3); MRotation = XMMatrixRotationQuaternion(RotationQuaternion); VTranslation = _mm_and_ps(Translation,g_XMMask3); M = MScaling; M.r[3] = _mm_sub_ps(M.r[3], VRotationOrigin); M = XMMatrixMultiply(M, MRotation); M.r[3] = _mm_add_ps(M.r[3], VRotationOrigin); M.r[3] = _mm_add_ps(M.r[3], VTranslation); return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixReflect ( FXMVECTOR ReflectionPlane ) { #if defined(_XM_NO_INTRINSICS_) XMVECTOR P; XMVECTOR S; XMVECTOR A, B, C, D; XMMATRIX M; static CONST XMVECTOR NegativeTwo = {-2.0f, -2.0f, -2.0f, 0.0f}; XMASSERT(!XMVector3Equal(ReflectionPlane, XMVectorZero())); XMASSERT(!XMPlaneIsInfinite(ReflectionPlane)); P = XMPlaneNormalize(ReflectionPlane); S = XMVectorMultiply(P, NegativeTwo); A = XMVectorSplatX(P); B = XMVectorSplatY(P); C = XMVectorSplatZ(P); D = XMVectorSplatW(P); M.r[0] = XMVectorMultiplyAdd(A, S, g_XMIdentityR0.v); M.r[1] = XMVectorMultiplyAdd(B, S, g_XMIdentityR1.v); M.r[2] = XMVectorMultiplyAdd(C, S, g_XMIdentityR2.v); M.r[3] = XMVectorMultiplyAdd(D, S, g_XMIdentityR3.v); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; static CONST XMVECTORF32 NegativeTwo = {-2.0f, -2.0f, -2.0f, 0.0f}; XMASSERT(!XMVector3Equal(ReflectionPlane, XMVectorZero())); XMASSERT(!XMPlaneIsInfinite(ReflectionPlane)); XMVECTOR P = XMPlaneNormalize(ReflectionPlane); XMVECTOR S = _mm_mul_ps(P,NegativeTwo); XMVECTOR X = _mm_shuffle_ps(P,P,_MM_SHUFFLE(0,0,0,0)); XMVECTOR Y = _mm_shuffle_ps(P,P,_MM_SHUFFLE(1,1,1,1)); XMVECTOR Z = _mm_shuffle_ps(P,P,_MM_SHUFFLE(2,2,2,2)); P = _mm_shuffle_ps(P,P,_MM_SHUFFLE(3,3,3,3)); X = _mm_mul_ps(X,S); Y = _mm_mul_ps(Y,S); Z = _mm_mul_ps(Z,S); P = _mm_mul_ps(P,S); X = _mm_add_ps(X,g_XMIdentityR0); Y = _mm_add_ps(Y,g_XMIdentityR1); Z = _mm_add_ps(Z,g_XMIdentityR2); P = _mm_add_ps(P,g_XMIdentityR3); M.r[0] = X; M.r[1] = Y; M.r[2] = Z; M.r[3] = P; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixShadow ( FXMVECTOR ShadowPlane, FXMVECTOR LightPosition ) { #if defined(_XM_NO_INTRINSICS_) XMVECTOR P; XMVECTOR Dot; XMVECTOR A, B, C, D; XMMATRIX M; static CONST XMVECTORU32 Select0001 = {XM_SELECT_0, XM_SELECT_0, XM_SELECT_0, XM_SELECT_1}; XMASSERT(!XMVector3Equal(ShadowPlane, XMVectorZero())); XMASSERT(!XMPlaneIsInfinite(ShadowPlane)); P = XMPlaneNormalize(ShadowPlane); Dot = XMPlaneDot(P, LightPosition); P = XMVectorNegate(P); D = XMVectorSplatW(P); C = XMVectorSplatZ(P); B = XMVectorSplatY(P); A = XMVectorSplatX(P); Dot = XMVectorSelect(Select0001.v, Dot, Select0001.v); M.r[3] = XMVectorMultiplyAdd(D, LightPosition, Dot); Dot = XMVectorRotateLeft(Dot, 1); M.r[2] = XMVectorMultiplyAdd(C, LightPosition, Dot); Dot = XMVectorRotateLeft(Dot, 1); M.r[1] = XMVectorMultiplyAdd(B, LightPosition, Dot); Dot = XMVectorRotateLeft(Dot, 1); M.r[0] = XMVectorMultiplyAdd(A, LightPosition, Dot); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; XMASSERT(!XMVector3Equal(ShadowPlane, XMVectorZero())); XMASSERT(!XMPlaneIsInfinite(ShadowPlane)); XMVECTOR P = XMPlaneNormalize(ShadowPlane); XMVECTOR Dot = XMPlaneDot(P,LightPosition); // Negate P = _mm_mul_ps(P,g_XMNegativeOne); XMVECTOR X = _mm_shuffle_ps(P,P,_MM_SHUFFLE(0,0,0,0)); XMVECTOR Y = _mm_shuffle_ps(P,P,_MM_SHUFFLE(1,1,1,1)); XMVECTOR Z = _mm_shuffle_ps(P,P,_MM_SHUFFLE(2,2,2,2)); P = _mm_shuffle_ps(P,P,_MM_SHUFFLE(3,3,3,3)); Dot = _mm_and_ps(Dot,g_XMMaskW); X = _mm_mul_ps(X,LightPosition); Y = _mm_mul_ps(Y,LightPosition); Z = _mm_mul_ps(Z,LightPosition); P = _mm_mul_ps(P,LightPosition); P = _mm_add_ps(P,Dot); Dot = _mm_shuffle_ps(Dot,Dot,_MM_SHUFFLE(0,3,2,1)); Z = _mm_add_ps(Z,Dot); Dot = _mm_shuffle_ps(Dot,Dot,_MM_SHUFFLE(0,3,2,1)); Y = _mm_add_ps(Y,Dot); Dot = _mm_shuffle_ps(Dot,Dot,_MM_SHUFFLE(0,3,2,1)); X = _mm_add_ps(X,Dot); // Store the resulting matrix M.r[0] = X; M.r[1] = Y; M.r[2] = Z; M.r[3] = P; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ // View and projection initialization operations //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixLookAtLH ( FXMVECTOR EyePosition, FXMVECTOR FocusPosition, FXMVECTOR UpDirection ) { XMVECTOR EyeDirection; XMMATRIX M; EyeDirection = XMVectorSubtract(FocusPosition, EyePosition); M = XMMatrixLookToLH(EyePosition, EyeDirection, UpDirection); return M; } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixLookAtRH ( FXMVECTOR EyePosition, FXMVECTOR FocusPosition, FXMVECTOR UpDirection ) { XMVECTOR NegEyeDirection; XMMATRIX M; NegEyeDirection = XMVectorSubtract(EyePosition, FocusPosition); M = XMMatrixLookToLH(EyePosition, NegEyeDirection, UpDirection); return M; } //------------------------------------------------------------------------------ XMINLINE XMMATRIX XMMatrixLookToLH ( FXMVECTOR EyePosition, FXMVECTOR EyeDirection, FXMVECTOR UpDirection ) { #if defined(_XM_NO_INTRINSICS_) XMVECTOR NegEyePosition; XMVECTOR D0, D1, D2; XMVECTOR R0, R1, R2; XMMATRIX M; XMASSERT(!XMVector3Equal(EyeDirection, XMVectorZero())); XMASSERT(!XMVector3IsInfinite(EyeDirection)); XMASSERT(!XMVector3Equal(UpDirection, XMVectorZero())); XMASSERT(!XMVector3IsInfinite(UpDirection)); R2 = XMVector3Normalize(EyeDirection); R0 = XMVector3Cross(UpDirection, R2); R0 = XMVector3Normalize(R0); R1 = XMVector3Cross(R2, R0); NegEyePosition = XMVectorNegate(EyePosition); D0 = XMVector3Dot(R0, NegEyePosition); D1 = XMVector3Dot(R1, NegEyePosition); D2 = XMVector3Dot(R2, NegEyePosition); M.r[0] = XMVectorSelect(D0, R0, g_XMSelect1110.v); M.r[1] = XMVectorSelect(D1, R1, g_XMSelect1110.v); M.r[2] = XMVectorSelect(D2, R2, g_XMSelect1110.v); M.r[3] = g_XMIdentityR3.v; M = XMMatrixTranspose(M); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; XMASSERT(!XMVector3Equal(EyeDirection, XMVectorZero())); XMASSERT(!XMVector3IsInfinite(EyeDirection)); XMASSERT(!XMVector3Equal(UpDirection, XMVectorZero())); XMASSERT(!XMVector3IsInfinite(UpDirection)); XMVECTOR R2 = XMVector3Normalize(EyeDirection); XMVECTOR R0 = XMVector3Cross(UpDirection, R2); R0 = XMVector3Normalize(R0); XMVECTOR R1 = XMVector3Cross(R2,R0); XMVECTOR NegEyePosition = _mm_mul_ps(EyePosition,g_XMNegativeOne); XMVECTOR D0 = XMVector3Dot(R0,NegEyePosition); XMVECTOR D1 = XMVector3Dot(R1,NegEyePosition); XMVECTOR D2 = XMVector3Dot(R2,NegEyePosition); R0 = _mm_and_ps(R0,g_XMMask3); R1 = _mm_and_ps(R1,g_XMMask3); R2 = _mm_and_ps(R2,g_XMMask3); D0 = _mm_and_ps(D0,g_XMMaskW); D1 = _mm_and_ps(D1,g_XMMaskW); D2 = _mm_and_ps(D2,g_XMMaskW); D0 = _mm_or_ps(D0,R0); D1 = _mm_or_ps(D1,R1); D2 = _mm_or_ps(D2,R2); M.r[0] = D0; M.r[1] = D1; M.r[2] = D2; M.r[3] = g_XMIdentityR3; M = XMMatrixTranspose(M); return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixLookToRH ( FXMVECTOR EyePosition, FXMVECTOR EyeDirection, FXMVECTOR UpDirection ) { XMVECTOR NegEyeDirection; XMMATRIX M; NegEyeDirection = XMVectorNegate(EyeDirection); M = XMMatrixLookToLH(EyePosition, NegEyeDirection, UpDirection); return M; } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixPerspectiveLH ( FLOAT ViewWidth, FLOAT ViewHeight, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT TwoNearZ, fRange; XMMATRIX M; XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); TwoNearZ = NearZ + NearZ; fRange = FarZ / (FarZ - NearZ); M.m[0][0] = TwoNearZ / ViewWidth; M.m[0][1] = 0.0f; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = TwoNearZ / ViewHeight; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = 0.0f; M.m[2][1] = 0.0f; M.m[2][2] = fRange; M.m[2][3] = 1.0f; M.m[3][0] = 0.0f; M.m[3][1] = 0.0f; M.m[3][2] = -fRange * NearZ; M.m[3][3] = 0.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMMATRIX M; FLOAT TwoNearZ = NearZ + NearZ; FLOAT fRange = FarZ / (FarZ - NearZ); // Note: This is recorded on the stack XMVECTOR rMem = { TwoNearZ / ViewWidth, TwoNearZ / ViewHeight, fRange, -fRange * NearZ }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // TwoNearZ / ViewWidth,0,0,0 M.r[0] = vTemp; // 0,TwoNearZ / ViewHeight,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); M.r[1] = vTemp; // x=fRange,y=-fRange * NearZ,0,1.0f vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2)); // 0,0,fRange,1.0f vTemp = _mm_setzero_ps(); vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0)); M.r[2] = vTemp; // 0,0,-fRange * NearZ,0 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0)); M.r[3] = vTemp; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixPerspectiveRH ( FLOAT ViewWidth, FLOAT ViewHeight, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT TwoNearZ, fRange; XMMATRIX M; XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); TwoNearZ = NearZ + NearZ; fRange = FarZ / (NearZ - FarZ); M.m[0][0] = TwoNearZ / ViewWidth; M.m[0][1] = 0.0f; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = TwoNearZ / ViewHeight; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = 0.0f; M.m[2][1] = 0.0f; M.m[2][2] = fRange; M.m[2][3] = -1.0f; M.m[3][0] = 0.0f; M.m[3][1] = 0.0f; M.m[3][2] = fRange * NearZ; M.m[3][3] = 0.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMMATRIX M; FLOAT TwoNearZ = NearZ + NearZ; FLOAT fRange = FarZ / (NearZ-FarZ); // Note: This is recorded on the stack XMVECTOR rMem = { TwoNearZ / ViewWidth, TwoNearZ / ViewHeight, fRange, fRange * NearZ }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // TwoNearZ / ViewWidth,0,0,0 M.r[0] = vTemp; // 0,TwoNearZ / ViewHeight,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); M.r[1] = vTemp; // x=fRange,y=-fRange * NearZ,0,-1.0f vValues = _mm_shuffle_ps(vValues,g_XMNegIdentityR3,_MM_SHUFFLE(3,2,3,2)); // 0,0,fRange,-1.0f vTemp = _mm_setzero_ps(); vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0)); M.r[2] = vTemp; // 0,0,-fRange * NearZ,0 vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0)); M.r[3] = vTemp; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixPerspectiveFovLH ( FLOAT FovAngleY, FLOAT AspectHByW, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT SinFov; FLOAT CosFov; FLOAT Height; FLOAT Width; XMMATRIX M; XMASSERT(!XMScalarNearEqual(FovAngleY, 0.0f, 0.00001f * 2.0f)); XMASSERT(!XMScalarNearEqual(AspectHByW, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY); Height = CosFov / SinFov; Width = Height / AspectHByW; M.r[0] = XMVectorSet(Width, 0.0f, 0.0f, 0.0f); M.r[1] = XMVectorSet(0.0f, Height, 0.0f, 0.0f); M.r[2] = XMVectorSet(0.0f, 0.0f, FarZ / (FarZ - NearZ), 1.0f); M.r[3] = XMVectorSet(0.0f, 0.0f, -M.r[2].vector4_f32[2] * NearZ, 0.0f); return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMScalarNearEqual(FovAngleY, 0.0f, 0.00001f * 2.0f)); XMASSERT(!XMScalarNearEqual(AspectHByW, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMMATRIX M; FLOAT SinFov; FLOAT CosFov; XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY); FLOAT fRange = FarZ / (FarZ-NearZ); // Note: This is recorded on the stack FLOAT Height = CosFov / SinFov; XMVECTOR rMem = { Height / AspectHByW, Height, fRange, -fRange * NearZ }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // CosFov / SinFov,0,0,0 M.r[0] = vTemp; // 0,Height / AspectHByW,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); M.r[1] = vTemp; // x=fRange,y=-fRange * NearZ,0,1.0f vTemp = _mm_setzero_ps(); vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2)); // 0,0,fRange,1.0f vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0)); M.r[2] = vTemp; // 0,0,-fRange * NearZ,0.0f vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0)); M.r[3] = vTemp; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixPerspectiveFovRH ( FLOAT FovAngleY, FLOAT AspectHByW, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT SinFov; FLOAT CosFov; FLOAT Height; FLOAT Width; XMMATRIX M; XMASSERT(!XMScalarNearEqual(FovAngleY, 0.0f, 0.00001f * 2.0f)); XMASSERT(!XMScalarNearEqual(AspectHByW, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY); Height = CosFov / SinFov; Width = Height / AspectHByW; M.r[0] = XMVectorSet(Width, 0.0f, 0.0f, 0.0f); M.r[1] = XMVectorSet(0.0f, Height, 0.0f, 0.0f); M.r[2] = XMVectorSet(0.0f, 0.0f, FarZ / (NearZ - FarZ), -1.0f); M.r[3] = XMVectorSet(0.0f, 0.0f, M.r[2].vector4_f32[2] * NearZ, 0.0f); return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMScalarNearEqual(FovAngleY, 0.0f, 0.00001f * 2.0f)); XMASSERT(!XMScalarNearEqual(AspectHByW, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMMATRIX M; FLOAT SinFov; FLOAT CosFov; XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY); FLOAT fRange = FarZ / (NearZ-FarZ); // Note: This is recorded on the stack FLOAT Height = CosFov / SinFov; XMVECTOR rMem = { Height / AspectHByW, Height, fRange, fRange * NearZ }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // CosFov / SinFov,0,0,0 M.r[0] = vTemp; // 0,Height / AspectHByW,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); M.r[1] = vTemp; // x=fRange,y=-fRange * NearZ,0,-1.0f vTemp = _mm_setzero_ps(); vValues = _mm_shuffle_ps(vValues,g_XMNegIdentityR3,_MM_SHUFFLE(3,2,3,2)); // 0,0,fRange,-1.0f vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,0,0,0)); M.r[2] = vTemp; // 0,0,fRange * NearZ,0.0f vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,1,0,0)); M.r[3] = vTemp; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixPerspectiveOffCenterLH ( FLOAT ViewLeft, FLOAT ViewRight, FLOAT ViewBottom, FLOAT ViewTop, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT TwoNearZ; FLOAT ReciprocalWidth; FLOAT ReciprocalHeight; FLOAT fRange; XMMATRIX M; XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); TwoNearZ = NearZ + NearZ; ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); fRange = FarZ / (FarZ-NearZ); M.m[0][0] = TwoNearZ * ReciprocalWidth; M.m[0][1] = 0.0f; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = TwoNearZ * ReciprocalHeight; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = -(ViewLeft + ViewRight) * ReciprocalWidth; M.m[2][1] = -(ViewTop + ViewBottom) * ReciprocalHeight; M.m[2][2] = fRange; M.m[2][3] = 1.0f; M.m[3][0] = 0.0f; M.m[3][1] = 0.0f; M.m[3][2] = -fRange * NearZ; M.m[3][3] = 0.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMMATRIX M; FLOAT TwoNearZ = NearZ+NearZ; FLOAT ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); FLOAT ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); FLOAT fRange = FarZ / (FarZ-NearZ); // Note: This is recorded on the stack XMVECTOR rMem = { TwoNearZ*ReciprocalWidth, TwoNearZ*ReciprocalHeight, -fRange * NearZ, 0 }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // TwoNearZ*ReciprocalWidth,0,0,0 M.r[0] = vTemp; // 0,TwoNearZ*ReciprocalHeight,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); M.r[1] = vTemp; // 0,0,fRange,1.0f M.r[2] = XMVectorSet( -(ViewLeft + ViewRight) * ReciprocalWidth, -(ViewTop + ViewBottom) * ReciprocalHeight, fRange, 1.0f ); // 0,0,-fRange * NearZ,0.0f vValues = _mm_and_ps(vValues,g_XMMaskZ); M.r[3] = vValues; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixPerspectiveOffCenterRH ( FLOAT ViewLeft, FLOAT ViewRight, FLOAT ViewBottom, FLOAT ViewTop, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT TwoNearZ; FLOAT ReciprocalWidth; FLOAT ReciprocalHeight; FLOAT fRange; XMMATRIX M; XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); TwoNearZ = NearZ + NearZ; ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); fRange = FarZ / (NearZ-FarZ); M.m[0][0] = TwoNearZ * ReciprocalWidth; M.m[0][1] = 0.0f; M.m[0][2] = 0.0f; M.m[0][3] = 0.0f; M.m[1][0] = 0.0f; M.m[1][1] = TwoNearZ * ReciprocalHeight; M.m[1][2] = 0.0f; M.m[1][3] = 0.0f; M.m[2][0] = (ViewLeft + ViewRight) * ReciprocalWidth; M.m[2][1] = (ViewTop + ViewBottom) * ReciprocalHeight; M.m[2][2] = fRange; M.m[2][3] = -1.0f; M.m[3][0] = 0.0f; M.m[3][1] = 0.0f; M.m[3][2] = fRange * NearZ; M.m[3][3] = 0.0f; return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMMATRIX M; FLOAT TwoNearZ = NearZ+NearZ; FLOAT ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); FLOAT ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); FLOAT fRange = FarZ / (NearZ-FarZ); // Note: This is recorded on the stack XMVECTOR rMem = { TwoNearZ*ReciprocalWidth, TwoNearZ*ReciprocalHeight, fRange * NearZ, 0 }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // TwoNearZ*ReciprocalWidth,0,0,0 M.r[0] = vTemp; // 0,TwoNearZ*ReciprocalHeight,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); M.r[1] = vTemp; // 0,0,fRange,1.0f M.r[2] = XMVectorSet((ViewLeft + ViewRight) * ReciprocalWidth, (ViewTop + ViewBottom) * ReciprocalHeight, fRange, -1.0f); // 0,0,-fRange * NearZ,0.0f vValues = _mm_and_ps(vValues,g_XMMaskZ); M.r[3] = vValues; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixOrthographicLH ( FLOAT ViewWidth, FLOAT ViewHeight, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT fRange; XMMATRIX M; XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); fRange = 1.0f / (FarZ-NearZ); M.r[0] = XMVectorSet(2.0f / ViewWidth, 0.0f, 0.0f, 0.0f); M.r[1] = XMVectorSet(0.0f, 2.0f / ViewHeight, 0.0f, 0.0f); M.r[2] = XMVectorSet(0.0f, 0.0f, fRange, 0.0f); M.r[3] = XMVectorSet(0.0f, 0.0f, -fRange * NearZ, 1.0f); return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMMATRIX M; FLOAT fRange = 1.0f / (FarZ-NearZ); // Note: This is recorded on the stack XMVECTOR rMem = { 2.0f / ViewWidth, 2.0f / ViewHeight, fRange, -fRange * NearZ }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // 2.0f / ViewWidth,0,0,0 M.r[0] = vTemp; // 0,2.0f / ViewHeight,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); M.r[1] = vTemp; // x=fRange,y=-fRange * NearZ,0,1.0f vTemp = _mm_setzero_ps(); vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2)); // 0,0,fRange,0.0f vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,0,0,0)); M.r[2] = vTemp; // 0,0,-fRange * NearZ,1.0f vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,1,0,0)); M.r[3] = vTemp; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixOrthographicRH ( FLOAT ViewWidth, FLOAT ViewHeight, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) XMMATRIX M; XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); M.r[0] = XMVectorSet(2.0f / ViewWidth, 0.0f, 0.0f, 0.0f); M.r[1] = XMVectorSet(0.0f, 2.0f / ViewHeight, 0.0f, 0.0f); M.r[2] = XMVectorSet(0.0f, 0.0f, 1.0f / (NearZ - FarZ), 0.0f); M.r[3] = XMVectorSet(0.0f, 0.0f, M.r[2].vector4_f32[2] * NearZ, 1.0f); return M; #elif defined(_XM_SSE_INTRINSICS_) XMASSERT(!XMScalarNearEqual(ViewWidth, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewHeight, 0.0f, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); XMMATRIX M; FLOAT fRange = 1.0f / (NearZ-FarZ); // Note: This is recorded on the stack XMVECTOR rMem = { 2.0f / ViewWidth, 2.0f / ViewHeight, fRange, fRange * NearZ }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // 2.0f / ViewWidth,0,0,0 M.r[0] = vTemp; // 0,2.0f / ViewHeight,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); M.r[1] = vTemp; // x=fRange,y=fRange * NearZ,0,1.0f vTemp = _mm_setzero_ps(); vValues = _mm_shuffle_ps(vValues,g_XMIdentityR3,_MM_SHUFFLE(3,2,3,2)); // 0,0,fRange,0.0f vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(2,0,0,0)); M.r[2] = vTemp; // 0,0,fRange * NearZ,1.0f vTemp = _mm_shuffle_ps(vTemp,vValues,_MM_SHUFFLE(3,1,0,0)); M.r[3] = vTemp; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixOrthographicOffCenterLH ( FLOAT ViewLeft, FLOAT ViewRight, FLOAT ViewBottom, FLOAT ViewTop, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT ReciprocalWidth; FLOAT ReciprocalHeight; XMMATRIX M; XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); M.r[0] = XMVectorSet(ReciprocalWidth + ReciprocalWidth, 0.0f, 0.0f, 0.0f); M.r[1] = XMVectorSet(0.0f, ReciprocalHeight + ReciprocalHeight, 0.0f, 0.0f); M.r[2] = XMVectorSet(0.0f, 0.0f, 1.0f / (FarZ - NearZ), 0.0f); M.r[3] = XMVectorSet(-(ViewLeft + ViewRight) * ReciprocalWidth, -(ViewTop + ViewBottom) * ReciprocalHeight, -M.r[2].vector4_f32[2] * NearZ, 1.0f); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; FLOAT fReciprocalWidth = 1.0f / (ViewRight - ViewLeft); FLOAT fReciprocalHeight = 1.0f / (ViewTop - ViewBottom); FLOAT fRange = 1.0f / (FarZ-NearZ); // Note: This is recorded on the stack XMVECTOR rMem = { fReciprocalWidth, fReciprocalHeight, fRange, 1.0f }; XMVECTOR rMem2 = { -(ViewLeft + ViewRight), -(ViewTop + ViewBottom), -NearZ, 1.0f }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // fReciprocalWidth*2,0,0,0 vTemp = _mm_add_ss(vTemp,vTemp); M.r[0] = vTemp; // 0,fReciprocalHeight*2,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); vTemp = _mm_add_ps(vTemp,vTemp); M.r[1] = vTemp; // 0,0,fRange,0.0f vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskZ); M.r[2] = vTemp; // -(ViewLeft + ViewRight)*fReciprocalWidth,-(ViewTop + ViewBottom)*fReciprocalHeight,fRange*-NearZ,1.0f vValues = _mm_mul_ps(vValues,rMem2); M.r[3] = vValues; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } //------------------------------------------------------------------------------ XMFINLINE XMMATRIX XMMatrixOrthographicOffCenterRH ( FLOAT ViewLeft, FLOAT ViewRight, FLOAT ViewBottom, FLOAT ViewTop, FLOAT NearZ, FLOAT FarZ ) { #if defined(_XM_NO_INTRINSICS_) FLOAT ReciprocalWidth; FLOAT ReciprocalHeight; XMMATRIX M; XMASSERT(!XMScalarNearEqual(ViewRight, ViewLeft, 0.00001f)); XMASSERT(!XMScalarNearEqual(ViewTop, ViewBottom, 0.00001f)); XMASSERT(!XMScalarNearEqual(FarZ, NearZ, 0.00001f)); ReciprocalWidth = 1.0f / (ViewRight - ViewLeft); ReciprocalHeight = 1.0f / (ViewTop - ViewBottom); M.r[0] = XMVectorSet(ReciprocalWidth + ReciprocalWidth, 0.0f, 0.0f, 0.0f); M.r[1] = XMVectorSet(0.0f, ReciprocalHeight + ReciprocalHeight, 0.0f, 0.0f); M.r[2] = XMVectorSet(0.0f, 0.0f, 1.0f / (NearZ - FarZ), 0.0f); M.r[3] = XMVectorSet(-(ViewLeft + ViewRight) * ReciprocalWidth, -(ViewTop + ViewBottom) * ReciprocalHeight, M.r[2].vector4_f32[2] * NearZ, 1.0f); return M; #elif defined(_XM_SSE_INTRINSICS_) XMMATRIX M; FLOAT fReciprocalWidth = 1.0f / (ViewRight - ViewLeft); FLOAT fReciprocalHeight = 1.0f / (ViewTop - ViewBottom); FLOAT fRange = 1.0f / (NearZ-FarZ); // Note: This is recorded on the stack XMVECTOR rMem = { fReciprocalWidth, fReciprocalHeight, fRange, 1.0f }; XMVECTOR rMem2 = { -(ViewLeft + ViewRight), -(ViewTop + ViewBottom), NearZ, 1.0f }; // Copy from memory to SSE register XMVECTOR vValues = rMem; XMVECTOR vTemp = _mm_setzero_ps(); // Copy x only vTemp = _mm_move_ss(vTemp,vValues); // fReciprocalWidth*2,0,0,0 vTemp = _mm_add_ss(vTemp,vTemp); M.r[0] = vTemp; // 0,fReciprocalHeight*2,0,0 vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskY); vTemp = _mm_add_ps(vTemp,vTemp); M.r[1] = vTemp; // 0,0,fRange,0.0f vTemp = vValues; vTemp = _mm_and_ps(vTemp,g_XMMaskZ); M.r[2] = vTemp; // -(ViewLeft + ViewRight)*fReciprocalWidth,-(ViewTop + ViewBottom)*fReciprocalHeight,fRange*-NearZ,1.0f vValues = _mm_mul_ps(vValues,rMem2); M.r[3] = vValues; return M; #else // _XM_VMX128_INTRINSICS_ #endif // _XM_VMX128_INTRINSICS_ } #ifdef __cplusplus /**************************************************************************** * * XMMATRIX operators and methods * ****************************************************************************/ //------------------------------------------------------------------------------ XMFINLINE _XMMATRIX::_XMMATRIX ( FXMVECTOR R0, FXMVECTOR R1, FXMVECTOR R2, CXMVECTOR R3 ) { r[0] = R0; r[1] = R1; r[2] = R2; r[3] = R3; } //------------------------------------------------------------------------------ XMFINLINE _XMMATRIX::_XMMATRIX ( FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03, FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13, FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23, FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33 ) { r[0] = XMVectorSet(m00, m01, m02, m03); r[1] = XMVectorSet(m10, m11, m12, m13); r[2] = XMVectorSet(m20, m21, m22, m23); r[3] = XMVectorSet(m30, m31, m32, m33); } //------------------------------------------------------------------------------ XMFINLINE _XMMATRIX::_XMMATRIX ( CONST FLOAT* pArray ) { r[0] = XMLoadFloat4((const XMFLOAT4*)pArray); r[1] = XMLoadFloat4((const XMFLOAT4*)(pArray + 4)); r[2] = XMLoadFloat4((const XMFLOAT4*)(pArray + 8)); r[3] = XMLoadFloat4((const XMFLOAT4*)(pArray + 12)); } //------------------------------------------------------------------------------ XMFINLINE _XMMATRIX& _XMMATRIX::operator= ( CONST _XMMATRIX& M ) { r[0] = M.r[0]; r[1] = M.r[1]; r[2] = M.r[2]; r[3] = M.r[3]; return *this; } //------------------------------------------------------------------------------ #ifndef XM_NO_OPERATOR_OVERLOADS #if !defined(_XBOX_VER) && defined(_XM_ISVS2005_) && defined(_XM_X64_) #pragma warning(push) #pragma warning(disable : 4328) #endif XMFINLINE _XMMATRIX& _XMMATRIX::operator*= ( CONST _XMMATRIX& M ) { *this = XMMatrixMultiply(*this, M); return *this; } //------------------------------------------------------------------------------ XMFINLINE _XMMATRIX _XMMATRIX::operator* ( CONST _XMMATRIX& M ) CONST { return XMMatrixMultiply(*this, M); } #if !defined(_XBOX_VER) && defined(_XM_ISVS2005_) && defined(_XM_X64_) #pragma warning(pop) #endif #endif // !XM_NO_OPERATOR_OVERLOADS /**************************************************************************** * * XMFLOAT3X3 operators * ****************************************************************************/ //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT3X3::_XMFLOAT3X3 ( FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m20, FLOAT m21, FLOAT m22 ) { m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; } //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT3X3::_XMFLOAT3X3 ( CONST FLOAT* pArray ) { UINT Row; UINT Column; for (Row = 0; Row < 3; Row++) { for (Column = 0; Column < 3; Column++) { m[Row][Column] = pArray[Row * 3 + Column]; } } } //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT3X3& _XMFLOAT3X3::operator= ( CONST _XMFLOAT3X3& Float3x3 ) { _11 = Float3x3._11; _12 = Float3x3._12; _13 = Float3x3._13; _21 = Float3x3._21; _22 = Float3x3._22; _23 = Float3x3._23; _31 = Float3x3._31; _32 = Float3x3._32; _33 = Float3x3._33; return *this; } /**************************************************************************** * * XMFLOAT4X3 operators * ****************************************************************************/ //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT4X3::_XMFLOAT4X3 ( FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m30, FLOAT m31, FLOAT m32 ) { m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; } //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT4X3::_XMFLOAT4X3 ( CONST FLOAT* pArray ) { UINT Row; UINT Column; for (Row = 0; Row < 4; Row++) { for (Column = 0; Column < 3; Column++) { m[Row][Column] = pArray[Row * 3 + Column]; } } } //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT4X3& _XMFLOAT4X3::operator= ( CONST _XMFLOAT4X3& Float4x3 ) { XMVECTOR V1 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._11); XMVECTOR V2 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._22); XMVECTOR V3 = XMLoadFloat4((const XMFLOAT4*)&Float4x3._33); XMStoreFloat4((XMFLOAT4*)&_11, V1); XMStoreFloat4((XMFLOAT4*)&_22, V2); XMStoreFloat4((XMFLOAT4*)&_33, V3); return *this; } //------------------------------------------------------------------------------ XMFINLINE XMFLOAT4X3A& XMFLOAT4X3A::operator= ( CONST XMFLOAT4X3A& Float4x3 ) { XMVECTOR V1 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._11); XMVECTOR V2 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._22); XMVECTOR V3 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x3._33); XMStoreFloat4A((XMFLOAT4A*)&_11, V1); XMStoreFloat4A((XMFLOAT4A*)&_22, V2); XMStoreFloat4A((XMFLOAT4A*)&_33, V3); return *this; } /**************************************************************************** * * XMFLOAT4X4 operators * ****************************************************************************/ //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT4X4::_XMFLOAT4X4 ( FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03, FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13, FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23, FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33 ) { m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; } //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT4X4::_XMFLOAT4X4 ( CONST FLOAT* pArray ) { UINT Row; UINT Column; for (Row = 0; Row < 4; Row++) { for (Column = 0; Column < 4; Column++) { m[Row][Column] = pArray[Row * 4 + Column]; } } } //------------------------------------------------------------------------------ XMFINLINE _XMFLOAT4X4& _XMFLOAT4X4::operator= ( CONST _XMFLOAT4X4& Float4x4 ) { XMVECTOR V1 = XMLoadFloat4((const XMFLOAT4*)&Float4x4._11); XMVECTOR V2 = XMLoadFloat4((const XMFLOAT4*)&Float4x4._21); XMVECTOR V3 = XMLoadFloat4((const XMFLOAT4*)&Float4x4._31); XMVECTOR V4 = XMLoadFloat4((const XMFLOAT4*)&Float4x4._41); XMStoreFloat4((XMFLOAT4*)&_11, V1); XMStoreFloat4((XMFLOAT4*)&_21, V2); XMStoreFloat4((XMFLOAT4*)&_31, V3); XMStoreFloat4((XMFLOAT4*)&_41, V4); return *this; } //------------------------------------------------------------------------------ XMFINLINE XMFLOAT4X4A& XMFLOAT4X4A::operator= ( CONST XMFLOAT4X4A& Float4x4 ) { XMVECTOR V1 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x4._11); XMVECTOR V2 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x4._21); XMVECTOR V3 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x4._31); XMVECTOR V4 = XMLoadFloat4A((const XMFLOAT4A*)&Float4x4._41); XMStoreFloat4A((XMFLOAT4A*)&_11, V1); XMStoreFloat4A((XMFLOAT4A*)&_21, V2); XMStoreFloat4A((XMFLOAT4A*)&_31, V3); XMStoreFloat4A((XMFLOAT4A*)&_41, V4); return *this; } #endif // __cplusplus #endif // __XNAMATHMATRIX_INL__