Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

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