d3dx9: Avoid LPD3DXMATRIXSTACK.
[wine] / dlls / d3dx9_36 / math.c
1 /*
2  * Mathematical operations specific to D3DX9.
3  *
4  * Copyright (C) 2008 David Adam
5  * Copyright (C) 2008 Luis Busquets
6  * Copyright (C) 2008 Jérôme Gardou
7  * Copyright (C) 2008 Philip Nilsson
8  * Copyright (C) 2008 Henri Verbeet
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24
25 #define NONAMELESSUNION
26
27 #include "config.h"
28 #include "wine/port.h"
29
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "d3dx9_36_private.h"
33
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
37
38 static const ID3DXMatrixStackVtbl ID3DXMatrixStack_Vtbl;
39
40 struct ID3DXMatrixStackImpl
41 {
42   ID3DXMatrixStack ID3DXMatrixStack_iface;
43   LONG ref;
44
45   unsigned int current;
46   unsigned int stack_size;
47   D3DXMATRIX *stack;
48 };
49
50
51 /*_________________D3DXColor____________________*/
52
53 D3DXCOLOR* WINAPI D3DXColorAdjustContrast(D3DXCOLOR *pout, CONST D3DXCOLOR *pc, FLOAT s)
54 {
55     TRACE("(%p, %p, %f)\n", pout, pc, s);
56
57     pout->r = 0.5f + s * (pc->r - 0.5f);
58     pout->g = 0.5f + s * (pc->g - 0.5f);
59     pout->b = 0.5f + s * (pc->b - 0.5f);
60     pout->a = pc->a;
61     return pout;
62 }
63
64 D3DXCOLOR* WINAPI D3DXColorAdjustSaturation(D3DXCOLOR *pout, CONST D3DXCOLOR *pc, FLOAT s)
65 {
66     FLOAT grey;
67
68     TRACE("(%p, %p, %f)\n", pout, pc, s);
69
70     grey = pc->r * 0.2125f + pc->g * 0.7154f + pc->b * 0.0721f;
71     pout->r = grey + s * (pc->r - grey);
72     pout->g = grey + s * (pc->g - grey);
73     pout->b = grey + s * (pc->b - grey);
74     pout->a = pc->a;
75     return pout;
76 }
77
78 /*_________________Misc__________________________*/
79
80 FLOAT WINAPI D3DXFresnelTerm(FLOAT costheta, FLOAT refractionindex)
81 {
82     FLOAT a, d, g, result;
83
84     TRACE("costheta %f, refractionindex %f\n", costheta, refractionindex);
85
86     g = sqrtf(refractionindex * refractionindex + costheta * costheta - 1.0f);
87     a = g + costheta;
88     d = g - costheta;
89     result = (costheta * a - 1.0f) * (costheta * a - 1.0f) / ((costheta * d + 1.0f) * (costheta * d + 1.0f)) + 1.0f;
90     result *= 0.5f * d * d / (a * a);
91
92     return result;
93 }
94
95 /*_________________D3DXMatrix____________________*/
96
97 D3DXMATRIX * WINAPI D3DXMatrixAffineTransformation(D3DXMATRIX *out, FLOAT scaling, const D3DXVECTOR3 *rotationcenter,
98         const D3DXQUATERNION *rotation, const D3DXVECTOR3 *translation)
99 {
100     TRACE("out %p, scaling %f, rotationcenter %p, rotation %p, translation %p\n",
101             out, scaling, rotationcenter, rotation, translation);
102
103     D3DXMatrixIdentity(out);
104
105     if (rotationcenter)
106     {
107         out->u.m[3][0] = -rotationcenter->x;
108         out->u.m[3][1] = -rotationcenter->y;
109         out->u.m[3][2] = -rotationcenter->z;
110     }
111
112     if (rotation)
113     {
114         FLOAT temp00, temp01, temp02, temp10, temp11, temp12, temp20, temp21, temp22;
115
116         temp00 = 1.0f - 2.0f * (rotation->y * rotation->y + rotation->z * rotation->z);
117         temp01 = 2.0f * (rotation->x * rotation->y + rotation->z * rotation->w);
118         temp02 = 2.0f * (rotation->x * rotation->z - rotation->y * rotation->w);
119         temp10 = 2.0f * (rotation->x * rotation->y - rotation->z * rotation->w);
120         temp11 = 1.0f - 2.0f * (rotation->x * rotation->x + rotation->z * rotation->z);
121         temp12 = 2.0f * (rotation->y * rotation->z + rotation->x * rotation->w);
122         temp20 = 2.0f * (rotation->x * rotation->z + rotation->y * rotation->w);
123         temp21 = 2.0f * (rotation->y * rotation->z - rotation->x * rotation->w);
124         temp22 = 1.0f - 2.0f * (rotation->x * rotation->x + rotation->y * rotation->y);
125
126         out->u.m[0][0] = scaling * temp00;
127         out->u.m[0][1] = scaling * temp01;
128         out->u.m[0][2] = scaling * temp02;
129         out->u.m[1][0] = scaling * temp10;
130         out->u.m[1][1] = scaling * temp11;
131         out->u.m[1][2] = scaling * temp12;
132         out->u.m[2][0] = scaling * temp20;
133         out->u.m[2][1] = scaling * temp21;
134         out->u.m[2][2] = scaling * temp22;
135
136         if (rotationcenter)
137         {
138             FLOAT x, y, z;
139
140             x = out->u.m[3][0];
141             y = out->u.m[3][1];
142             z = out->u.m[3][2];
143
144             out->u.m[3][0] = x * temp00 + y * temp10 + z * temp20;
145             out->u.m[3][1] = x * temp01 + y * temp11 + z * temp21;
146             out->u.m[3][2] = x * temp02 + y * temp12 + z * temp22;
147         }
148     }
149     else
150     {
151         out->u.m[0][0] = scaling;
152         out->u.m[1][1] = scaling;
153         out->u.m[2][2] = scaling;
154     }
155
156     if (rotationcenter)
157     {
158         out->u.m[3][0] += rotationcenter->x;
159         out->u.m[3][1] += rotationcenter->y;
160         out->u.m[3][2] += rotationcenter->z;
161     }
162
163     if (translation)
164     {
165         out->u.m[3][0] += translation->x;
166         out->u.m[3][1] += translation->y;
167         out->u.m[3][2] += translation->z;
168     }
169
170     return out;
171 }
172
173 D3DXMATRIX * WINAPI D3DXMatrixAffineTransformation2D(D3DXMATRIX *out, FLOAT scaling,
174         const D3DXVECTOR2 *rotationcenter, FLOAT rotation, const D3DXVECTOR2 *translation)
175 {
176     FLOAT tmp1, tmp2, s;
177
178     TRACE("out %p, scaling %f, rotationcenter %p, rotation %f, translation %p\n",
179             out, scaling, rotationcenter, rotation, translation);
180
181     s = sinf(rotation / 2.0f);
182     tmp1 = 1.0f - 2.0f * s * s;
183     tmp2 = 2.0 * s * cosf(rotation / 2.0f);
184
185     D3DXMatrixIdentity(out);
186     out->u.m[0][0] = scaling * tmp1;
187     out->u.m[0][1] = scaling * tmp2;
188     out->u.m[1][0] = -scaling * tmp2;
189     out->u.m[1][1] = scaling * tmp1;
190
191     if (rotationcenter)
192     {
193         FLOAT x, y;
194
195         x = rotationcenter->x;
196         y = rotationcenter->y;
197
198         out->u.m[3][0] = y * tmp2 - x * tmp1 + x;
199         out->u.m[3][1] = -x * tmp2 - y * tmp1 + y;
200     }
201
202     if (translation)
203     {
204         out->u.m[3][0] += translation->x;
205         out->u.m[3][1] += translation->y;
206     }
207
208     return out;
209 }
210
211 HRESULT WINAPI D3DXMatrixDecompose(D3DXVECTOR3 *poutscale, D3DXQUATERNION *poutrotation, D3DXVECTOR3 *pouttranslation, CONST D3DXMATRIX *pm)
212 {
213     D3DXMATRIX normalized;
214     D3DXVECTOR3 vec;
215
216     TRACE("(%p, %p, %p, %p)\n", poutscale, poutrotation, pouttranslation, pm);
217
218     /*Compute the scaling part.*/
219     vec.x=pm->u.m[0][0];
220     vec.y=pm->u.m[0][1];
221     vec.z=pm->u.m[0][2];
222     poutscale->x=D3DXVec3Length(&vec);
223
224     vec.x=pm->u.m[1][0];
225     vec.y=pm->u.m[1][1];
226     vec.z=pm->u.m[1][2];
227     poutscale->y=D3DXVec3Length(&vec);
228
229     vec.x=pm->u.m[2][0];
230     vec.y=pm->u.m[2][1];
231     vec.z=pm->u.m[2][2];
232     poutscale->z=D3DXVec3Length(&vec);
233
234     /*Compute the translation part.*/
235     pouttranslation->x=pm->u.m[3][0];
236     pouttranslation->y=pm->u.m[3][1];
237     pouttranslation->z=pm->u.m[3][2];
238
239     /*Let's calculate the rotation now*/
240     if ( (poutscale->x == 0.0f) || (poutscale->y == 0.0f) || (poutscale->z == 0.0f) ) return D3DERR_INVALIDCALL;
241
242     normalized.u.m[0][0]=pm->u.m[0][0]/poutscale->x;
243     normalized.u.m[0][1]=pm->u.m[0][1]/poutscale->x;
244     normalized.u.m[0][2]=pm->u.m[0][2]/poutscale->x;
245     normalized.u.m[1][0]=pm->u.m[1][0]/poutscale->y;
246     normalized.u.m[1][1]=pm->u.m[1][1]/poutscale->y;
247     normalized.u.m[1][2]=pm->u.m[1][2]/poutscale->y;
248     normalized.u.m[2][0]=pm->u.m[2][0]/poutscale->z;
249     normalized.u.m[2][1]=pm->u.m[2][1]/poutscale->z;
250     normalized.u.m[2][2]=pm->u.m[2][2]/poutscale->z;
251
252     D3DXQuaternionRotationMatrix(poutrotation,&normalized);
253     return S_OK;
254 }
255
256 FLOAT WINAPI D3DXMatrixDeterminant(CONST D3DXMATRIX *pm)
257 {
258     D3DXVECTOR4 minor, v1, v2, v3;
259     FLOAT det;
260
261     TRACE("(%p)\n", pm);
262
263     v1.x = pm->u.m[0][0]; v1.y = pm->u.m[1][0]; v1.z = pm->u.m[2][0]; v1.w = pm->u.m[3][0];
264     v2.x = pm->u.m[0][1]; v2.y = pm->u.m[1][1]; v2.z = pm->u.m[2][1]; v2.w = pm->u.m[3][1];
265     v3.x = pm->u.m[0][2]; v3.y = pm->u.m[1][2]; v3.z = pm->u.m[2][2]; v3.w = pm->u.m[3][2];
266     D3DXVec4Cross(&minor, &v1, &v2, &v3);
267     det =  - (pm->u.m[0][3] * minor.x + pm->u.m[1][3] * minor.y + pm->u.m[2][3] * minor.z + pm->u.m[3][3] * minor.w);
268     return det;
269 }
270
271 D3DXMATRIX* WINAPI D3DXMatrixInverse(D3DXMATRIX *pout, FLOAT *pdeterminant, CONST D3DXMATRIX *pm)
272 {
273     int a, i, j;
274     D3DXMATRIX out;
275     D3DXVECTOR4 v, vec[3];
276     FLOAT det;
277
278     TRACE("(%p, %p, %p)\n", pout, pdeterminant, pm);
279
280     det = D3DXMatrixDeterminant(pm);
281     if ( !det ) return NULL;
282     if ( pdeterminant ) *pdeterminant = det;
283     for (i=0; i<4; i++)
284     {
285         for (j=0; j<4; j++)
286         {
287             if (j != i )
288             {
289                 a = j;
290                 if ( j > i ) a = a-1;
291                 vec[a].x = pm->u.m[j][0];
292                 vec[a].y = pm->u.m[j][1];
293                 vec[a].z = pm->u.m[j][2];
294                 vec[a].w = pm->u.m[j][3];
295             }
296         }
297     D3DXVec4Cross(&v, &vec[0], &vec[1], &vec[2]);
298     out.u.m[0][i] = pow(-1.0f, i) * v.x / det;
299     out.u.m[1][i] = pow(-1.0f, i) * v.y / det;
300     out.u.m[2][i] = pow(-1.0f, i) * v.z / det;
301     out.u.m[3][i] = pow(-1.0f, i) * v.w / det;
302    }
303
304    *pout = out;
305    return pout;
306 }
307
308 D3DXMATRIX* WINAPI D3DXMatrixLookAtLH(D3DXMATRIX *pout, CONST D3DXVECTOR3 *peye, CONST D3DXVECTOR3 *pat, CONST D3DXVECTOR3 *pup)
309 {
310     D3DXVECTOR3 right, rightn, up, upn, vec, vec2;
311
312     TRACE("(%p, %p, %p, %p)\n", pout, peye, pat, pup);
313
314     D3DXVec3Subtract(&vec2, pat, peye);
315     D3DXVec3Normalize(&vec, &vec2);
316     D3DXVec3Cross(&right, pup, &vec);
317     D3DXVec3Cross(&up, &vec, &right);
318     D3DXVec3Normalize(&rightn, &right);
319     D3DXVec3Normalize(&upn, &up);
320     pout->u.m[0][0] = rightn.x;
321     pout->u.m[1][0] = rightn.y;
322     pout->u.m[2][0] = rightn.z;
323     pout->u.m[3][0] = -D3DXVec3Dot(&rightn,peye);
324     pout->u.m[0][1] = upn.x;
325     pout->u.m[1][1] = upn.y;
326     pout->u.m[2][1] = upn.z;
327     pout->u.m[3][1] = -D3DXVec3Dot(&upn, peye);
328     pout->u.m[0][2] = vec.x;
329     pout->u.m[1][2] = vec.y;
330     pout->u.m[2][2] = vec.z;
331     pout->u.m[3][2] = -D3DXVec3Dot(&vec, peye);
332     pout->u.m[0][3] = 0.0f;
333     pout->u.m[1][3] = 0.0f;
334     pout->u.m[2][3] = 0.0f;
335     pout->u.m[3][3] = 1.0f;
336     return pout;
337 }
338
339 D3DXMATRIX* WINAPI D3DXMatrixLookAtRH(D3DXMATRIX *pout, CONST D3DXVECTOR3 *peye, CONST D3DXVECTOR3 *pat, CONST D3DXVECTOR3 *pup)
340 {
341     D3DXVECTOR3 right, rightn, up, upn, vec, vec2;
342
343     TRACE("(%p, %p, %p, %p)\n", pout, peye, pat, pup);
344
345     D3DXVec3Subtract(&vec2, pat, peye);
346     D3DXVec3Normalize(&vec, &vec2);
347     D3DXVec3Cross(&right, pup, &vec);
348     D3DXVec3Cross(&up, &vec, &right);
349     D3DXVec3Normalize(&rightn, &right);
350     D3DXVec3Normalize(&upn, &up);
351     pout->u.m[0][0] = -rightn.x;
352     pout->u.m[1][0] = -rightn.y;
353     pout->u.m[2][0] = -rightn.z;
354     pout->u.m[3][0] = D3DXVec3Dot(&rightn,peye);
355     pout->u.m[0][1] = upn.x;
356     pout->u.m[1][1] = upn.y;
357     pout->u.m[2][1] = upn.z;
358     pout->u.m[3][1] = -D3DXVec3Dot(&upn, peye);
359     pout->u.m[0][2] = -vec.x;
360     pout->u.m[1][2] = -vec.y;
361     pout->u.m[2][2] = -vec.z;
362     pout->u.m[3][2] = D3DXVec3Dot(&vec, peye);
363     pout->u.m[0][3] = 0.0f;
364     pout->u.m[1][3] = 0.0f;
365     pout->u.m[2][3] = 0.0f;
366     pout->u.m[3][3] = 1.0f;
367     return pout;
368 }
369
370 D3DXMATRIX* WINAPI D3DXMatrixMultiply(D3DXMATRIX *pout, CONST D3DXMATRIX *pm1, CONST D3DXMATRIX *pm2)
371 {
372     D3DXMATRIX out;
373     int i,j;
374
375     TRACE("(%p, %p, %p)\n", pout, pm1, pm2);
376
377     for (i=0; i<4; i++)
378     {
379         for (j=0; j<4; j++)
380         {
381             out.u.m[i][j] = pm1->u.m[i][0] * pm2->u.m[0][j] + pm1->u.m[i][1] * pm2->u.m[1][j] + pm1->u.m[i][2] * pm2->u.m[2][j] + pm1->u.m[i][3] * pm2->u.m[3][j];
382         }
383     }
384
385     *pout = out;
386     return pout;
387 }
388
389 D3DXMATRIX* WINAPI D3DXMatrixMultiplyTranspose(D3DXMATRIX *pout, CONST D3DXMATRIX *pm1, CONST D3DXMATRIX *pm2)
390 {
391     TRACE("%p, %p, %p)\n", pout, pm1, pm2);
392
393     D3DXMatrixMultiply(pout, pm1, pm2);
394     D3DXMatrixTranspose(pout, pout);
395     return pout;
396 }
397
398 D3DXMATRIX* WINAPI D3DXMatrixOrthoLH(D3DXMATRIX *pout, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf)
399 {
400     TRACE("(%p, %f, %f, %f, %f)\n", pout, w, h, zn, zf);
401
402     D3DXMatrixIdentity(pout);
403     pout->u.m[0][0] = 2.0f / w;
404     pout->u.m[1][1] = 2.0f / h;
405     pout->u.m[2][2] = 1.0f / (zf - zn);
406     pout->u.m[3][2] = zn / (zn - zf);
407     return pout;
408 }
409
410 D3DXMATRIX* WINAPI D3DXMatrixOrthoOffCenterLH(D3DXMATRIX *pout, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf)
411 {
412     TRACE("(%p, %f, %f, %f, %f, %f, %f)\n", pout, l, r, b, t, zn, zf);
413
414     D3DXMatrixIdentity(pout);
415     pout->u.m[0][0] = 2.0f / (r - l);
416     pout->u.m[1][1] = 2.0f / (t - b);
417     pout->u.m[2][2] = 1.0f / (zf -zn);
418     pout->u.m[3][0] = -1.0f -2.0f *l / (r - l);
419     pout->u.m[3][1] = 1.0f + 2.0f * t / (b - t);
420     pout->u.m[3][2] = zn / (zn -zf);
421     return pout;
422 }
423
424 D3DXMATRIX* WINAPI D3DXMatrixOrthoOffCenterRH(D3DXMATRIX *pout, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf)
425 {
426     TRACE("(%p, %f, %f, %f, %f, %f, %f)\n", pout, l, r, b, t, zn, zf);
427
428     D3DXMatrixIdentity(pout);
429     pout->u.m[0][0] = 2.0f / (r - l);
430     pout->u.m[1][1] = 2.0f / (t - b);
431     pout->u.m[2][2] = 1.0f / (zn -zf);
432     pout->u.m[3][0] = -1.0f -2.0f *l / (r - l);
433     pout->u.m[3][1] = 1.0f + 2.0f * t / (b - t);
434     pout->u.m[3][2] = zn / (zn -zf);
435     return pout;
436 }
437
438 D3DXMATRIX* WINAPI D3DXMatrixOrthoRH(D3DXMATRIX *pout, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf)
439 {
440     TRACE("(%p, %f, %f, %f, %f)\n", pout, w, h, zn, zf);
441
442     D3DXMatrixIdentity(pout);
443     pout->u.m[0][0] = 2.0f / w;
444     pout->u.m[1][1] = 2.0f / h;
445     pout->u.m[2][2] = 1.0f / (zn - zf);
446     pout->u.m[3][2] = zn / (zn - zf);
447     return pout;
448 }
449
450 D3DXMATRIX* WINAPI D3DXMatrixPerspectiveFovLH(D3DXMATRIX *pout, FLOAT fovy, FLOAT aspect, FLOAT zn, FLOAT zf)
451 {
452     TRACE("(%p, %f, %f, %f, %f)\n", pout, fovy, aspect, zn, zf);
453
454     D3DXMatrixIdentity(pout);
455     pout->u.m[0][0] = 1.0f / (aspect * tan(fovy/2.0f));
456     pout->u.m[1][1] = 1.0f / tan(fovy/2.0f);
457     pout->u.m[2][2] = zf / (zf - zn);
458     pout->u.m[2][3] = 1.0f;
459     pout->u.m[3][2] = (zf * zn) / (zn - zf);
460     pout->u.m[3][3] = 0.0f;
461     return pout;
462 }
463
464 D3DXMATRIX* WINAPI D3DXMatrixPerspectiveFovRH(D3DXMATRIX *pout, FLOAT fovy, FLOAT aspect, FLOAT zn, FLOAT zf)
465 {
466     TRACE("(%p, %f, %f, %f, %f)\n", pout, fovy, aspect, zn, zf);
467
468     D3DXMatrixIdentity(pout);
469     pout->u.m[0][0] = 1.0f / (aspect * tan(fovy/2.0f));
470     pout->u.m[1][1] = 1.0f / tan(fovy/2.0f);
471     pout->u.m[2][2] = zf / (zn - zf);
472     pout->u.m[2][3] = -1.0f;
473     pout->u.m[3][2] = (zf * zn) / (zn - zf);
474     pout->u.m[3][3] = 0.0f;
475     return pout;
476 }
477
478 D3DXMATRIX* WINAPI D3DXMatrixPerspectiveLH(D3DXMATRIX *pout, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf)
479 {
480     TRACE("(%p, %f, %f, %f, %f)\n", pout, w, h, zn, zf);
481
482     D3DXMatrixIdentity(pout);
483     pout->u.m[0][0] = 2.0f * zn / w;
484     pout->u.m[1][1] = 2.0f * zn / h;
485     pout->u.m[2][2] = zf / (zf - zn);
486     pout->u.m[3][2] = (zn * zf) / (zn - zf);
487     pout->u.m[2][3] = 1.0f;
488     pout->u.m[3][3] = 0.0f;
489     return pout;
490 }
491
492 D3DXMATRIX* WINAPI D3DXMatrixPerspectiveOffCenterLH(D3DXMATRIX *pout, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf)
493 {
494     TRACE("(%p, %f, %f, %f, %f, %f, %f)\n", pout, l, r, b, t, zn, zf);
495
496     D3DXMatrixIdentity(pout);
497     pout->u.m[0][0] = 2.0f * zn / (r - l);
498     pout->u.m[1][1] = -2.0f * zn / (b - t);
499     pout->u.m[2][0] = -1.0f - 2.0f * l / (r - l);
500     pout->u.m[2][1] = 1.0f + 2.0f * t / (b - t);
501     pout->u.m[2][2] = - zf / (zn - zf);
502     pout->u.m[3][2] = (zn * zf) / (zn -zf);
503     pout->u.m[2][3] = 1.0f;
504     pout->u.m[3][3] = 0.0f;
505     return pout;
506 }
507
508 D3DXMATRIX* WINAPI D3DXMatrixPerspectiveOffCenterRH(D3DXMATRIX *pout, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf)
509 {
510     TRACE("(%p, %f, %f, %f, %f, %f, %f)\n", pout, l, r, b, t, zn, zf);
511
512     D3DXMatrixIdentity(pout);
513     pout->u.m[0][0] = 2.0f * zn / (r - l);
514     pout->u.m[1][1] = -2.0f * zn / (b - t);
515     pout->u.m[2][0] = 1.0f + 2.0f * l / (r - l);
516     pout->u.m[2][1] = -1.0f -2.0f * t / (b - t);
517     pout->u.m[2][2] = zf / (zn - zf);
518     pout->u.m[3][2] = (zn * zf) / (zn -zf);
519     pout->u.m[2][3] = -1.0f;
520     pout->u.m[3][3] = 0.0f;
521     return pout;
522 }
523
524 D3DXMATRIX* WINAPI D3DXMatrixPerspectiveRH(D3DXMATRIX *pout, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf)
525 {
526     TRACE("(%p, %f, %f, %f, %f)\n", pout, w, h, zn, zf);
527
528     D3DXMatrixIdentity(pout);
529     pout->u.m[0][0] = 2.0f * zn / w;
530     pout->u.m[1][1] = 2.0f * zn / h;
531     pout->u.m[2][2] = zf / (zn - zf);
532     pout->u.m[3][2] = (zn * zf) / (zn - zf);
533     pout->u.m[2][3] = -1.0f;
534     pout->u.m[3][3] = 0.0f;
535     return pout;
536 }
537
538 D3DXMATRIX* WINAPI D3DXMatrixReflect(D3DXMATRIX *pout, CONST D3DXPLANE *pplane)
539 {
540     D3DXPLANE Nplane;
541
542     TRACE("(%p, %p)\n", pout, pplane);
543
544     D3DXPlaneNormalize(&Nplane, pplane);
545     D3DXMatrixIdentity(pout);
546     pout->u.m[0][0] = 1.0f - 2.0f * Nplane.a * Nplane.a;
547     pout->u.m[0][1] = -2.0f * Nplane.a * Nplane.b;
548     pout->u.m[0][2] = -2.0f * Nplane.a * Nplane.c;
549     pout->u.m[1][0] = -2.0f * Nplane.a * Nplane.b;
550     pout->u.m[1][1] = 1.0f - 2.0f * Nplane.b * Nplane.b;
551     pout->u.m[1][2] = -2.0f * Nplane.b * Nplane.c;
552     pout->u.m[2][0] = -2.0f * Nplane.c * Nplane.a;
553     pout->u.m[2][1] = -2.0f * Nplane.c * Nplane.b;
554     pout->u.m[2][2] = 1.0f - 2.0f * Nplane.c * Nplane.c;
555     pout->u.m[3][0] = -2.0f * Nplane.d * Nplane.a;
556     pout->u.m[3][1] = -2.0f * Nplane.d * Nplane.b;
557     pout->u.m[3][2] = -2.0f * Nplane.d * Nplane.c;
558     return pout;
559 }
560
561 D3DXMATRIX * WINAPI D3DXMatrixRotationAxis(D3DXMATRIX *out, const D3DXVECTOR3 *v, FLOAT angle)
562 {
563     D3DXVECTOR3 nv;
564     FLOAT sangle, cangle, cdiff;
565
566     TRACE("out %p, v %p, angle %f\n", out, v, angle);
567
568     D3DXVec3Normalize(&nv, v);
569     sangle = sinf(angle);
570     cangle = cosf(angle);
571     cdiff = 1.0f - cangle;
572
573     out->u.m[0][0] = cdiff * nv.x * nv.x + cangle;
574     out->u.m[1][0] = cdiff * nv.x * nv.y - sangle * nv.z;
575     out->u.m[2][0] = cdiff * nv.x * nv.z + sangle * nv.y;
576     out->u.m[3][0] = 0.0f;
577     out->u.m[0][1] = cdiff * nv.y * nv.x + sangle * nv.z;
578     out->u.m[1][1] = cdiff * nv.y * nv.y + cangle;
579     out->u.m[2][1] = cdiff * nv.y * nv.z - sangle * nv.x;
580     out->u.m[3][1] = 0.0f;
581     out->u.m[0][2] = cdiff * nv.z * nv.x - sangle * nv.y;
582     out->u.m[1][2] = cdiff * nv.z * nv.y + sangle * nv.x;
583     out->u.m[2][2] = cdiff * nv.z * nv.z + cangle;
584     out->u.m[3][2] = 0.0f;
585     out->u.m[0][3] = 0.0f;
586     out->u.m[1][3] = 0.0f;
587     out->u.m[2][3] = 0.0f;
588     out->u.m[3][3] = 1.0f;
589
590     return out;
591 }
592
593 D3DXMATRIX* WINAPI D3DXMatrixRotationQuaternion(D3DXMATRIX *pout, CONST D3DXQUATERNION *pq)
594 {
595     TRACE("(%p, %p)\n", pout, pq);
596
597     D3DXMatrixIdentity(pout);
598     pout->u.m[0][0] = 1.0f - 2.0f * (pq->y * pq->y + pq->z * pq->z);
599     pout->u.m[0][1] = 2.0f * (pq->x *pq->y + pq->z * pq->w);
600     pout->u.m[0][2] = 2.0f * (pq->x * pq->z - pq->y * pq->w);
601     pout->u.m[1][0] = 2.0f * (pq->x * pq->y - pq->z * pq->w);
602     pout->u.m[1][1] = 1.0f - 2.0f * (pq->x * pq->x + pq->z * pq->z);
603     pout->u.m[1][2] = 2.0f * (pq->y *pq->z + pq->x *pq->w);
604     pout->u.m[2][0] = 2.0f * (pq->x * pq->z + pq->y * pq->w);
605     pout->u.m[2][1] = 2.0f * (pq->y *pq->z - pq->x *pq->w);
606     pout->u.m[2][2] = 1.0f - 2.0f * (pq->x * pq->x + pq->y * pq->y);
607     return pout;
608 }
609
610 D3DXMATRIX* WINAPI D3DXMatrixRotationX(D3DXMATRIX *pout, FLOAT angle)
611 {
612     TRACE("(%p, %f)\n", pout, angle);
613
614     D3DXMatrixIdentity(pout);
615     pout->u.m[1][1] = cos(angle);
616     pout->u.m[2][2] = cos(angle);
617     pout->u.m[1][2] = sin(angle);
618     pout->u.m[2][1] = -sin(angle);
619     return pout;
620 }
621
622 D3DXMATRIX* WINAPI D3DXMatrixRotationY(D3DXMATRIX *pout, FLOAT angle)
623 {
624     TRACE("(%p, %f)\n", pout, angle);
625
626     D3DXMatrixIdentity(pout);
627     pout->u.m[0][0] = cos(angle);
628     pout->u.m[2][2] = cos(angle);
629     pout->u.m[0][2] = -sin(angle);
630     pout->u.m[2][0] = sin(angle);
631     return pout;
632 }
633
634 D3DXMATRIX* WINAPI D3DXMatrixRotationYawPitchRoll(D3DXMATRIX *pout, FLOAT yaw, FLOAT pitch, FLOAT roll)
635 {
636     D3DXMATRIX m;
637
638     TRACE("(%p, %f, %f, %f)\n", pout, yaw, pitch, roll);
639
640     D3DXMatrixIdentity(pout);
641     D3DXMatrixRotationZ(&m, roll);
642     D3DXMatrixMultiply(pout, pout, &m);
643     D3DXMatrixRotationX(&m, pitch);
644     D3DXMatrixMultiply(pout, pout, &m);
645     D3DXMatrixRotationY(&m, yaw);
646     D3DXMatrixMultiply(pout, pout, &m);
647     return pout;
648 }
649
650 D3DXMATRIX* WINAPI D3DXMatrixRotationZ(D3DXMATRIX *pout, FLOAT angle)
651 {
652     TRACE("(%p, %f)\n", pout, angle);
653
654     D3DXMatrixIdentity(pout);
655     pout->u.m[0][0] = cos(angle);
656     pout->u.m[1][1] = cos(angle);
657     pout->u.m[0][1] = sin(angle);
658     pout->u.m[1][0] = -sin(angle);
659     return pout;
660 }
661
662 D3DXMATRIX* WINAPI D3DXMatrixScaling(D3DXMATRIX *pout, FLOAT sx, FLOAT sy, FLOAT sz)
663 {
664     TRACE("(%p, %f, %f, %f)\n", pout, sx, sy, sz);
665
666     D3DXMatrixIdentity(pout);
667     pout->u.m[0][0] = sx;
668     pout->u.m[1][1] = sy;
669     pout->u.m[2][2] = sz;
670     return pout;
671 }
672
673 D3DXMATRIX* WINAPI D3DXMatrixShadow(D3DXMATRIX *pout, CONST D3DXVECTOR4 *plight, CONST D3DXPLANE *pplane)
674 {
675     D3DXPLANE Nplane;
676     FLOAT dot;
677
678     TRACE("(%p, %p, %p)\n", pout, plight, pplane);
679
680     D3DXPlaneNormalize(&Nplane, pplane);
681     dot = D3DXPlaneDot(&Nplane, plight);
682     pout->u.m[0][0] = dot - Nplane.a * plight->x;
683     pout->u.m[0][1] = -Nplane.a * plight->y;
684     pout->u.m[0][2] = -Nplane.a * plight->z;
685     pout->u.m[0][3] = -Nplane.a * plight->w;
686     pout->u.m[1][0] = -Nplane.b * plight->x;
687     pout->u.m[1][1] = dot - Nplane.b * plight->y;
688     pout->u.m[1][2] = -Nplane.b * plight->z;
689     pout->u.m[1][3] = -Nplane.b * plight->w;
690     pout->u.m[2][0] = -Nplane.c * plight->x;
691     pout->u.m[2][1] = -Nplane.c * plight->y;
692     pout->u.m[2][2] = dot - Nplane.c * plight->z;
693     pout->u.m[2][3] = -Nplane.c * plight->w;
694     pout->u.m[3][0] = -Nplane.d * plight->x;
695     pout->u.m[3][1] = -Nplane.d * plight->y;
696     pout->u.m[3][2] = -Nplane.d * plight->z;
697     pout->u.m[3][3] = dot - Nplane.d * plight->w;
698     return pout;
699 }
700
701 D3DXMATRIX* WINAPI D3DXMatrixTransformation(D3DXMATRIX *pout, CONST D3DXVECTOR3 *pscalingcenter, CONST D3DXQUATERNION *pscalingrotation, CONST D3DXVECTOR3 *pscaling, CONST D3DXVECTOR3 *protationcenter, CONST D3DXQUATERNION *protation, CONST D3DXVECTOR3 *ptranslation)
702 {
703     D3DXMATRIX m1, m2, m3, m4, m5, m6, m7;
704     D3DXQUATERNION prc;
705     D3DXVECTOR3 psc, pt;
706
707     TRACE("(%p, %p, %p, %p, %p, %p, %p)\n", pout, pscalingcenter, pscalingrotation, pscaling, protationcenter, protation, ptranslation);
708
709     if ( !pscalingcenter )
710     {
711         psc.x = 0.0f;
712         psc.y = 0.0f;
713         psc.z = 0.0f;
714     }
715     else
716     {
717         psc.x = pscalingcenter->x;
718         psc.y = pscalingcenter->y;
719         psc.z = pscalingcenter->z;
720     }
721
722     if ( !protationcenter )
723     {
724         prc.x = 0.0f;
725         prc.y = 0.0f;
726         prc.z = 0.0f;
727     }
728     else
729     {
730         prc.x = protationcenter->x;
731         prc.y = protationcenter->y;
732         prc.z = protationcenter->z;
733     }
734
735     if ( !ptranslation )
736     {
737         pt.x = 0.0f;
738         pt.y = 0.0f;
739         pt.z = 0.0f;
740     }
741     else
742     {
743         pt.x = ptranslation->x;
744         pt.y = ptranslation->y;
745         pt.z = ptranslation->z;
746     }
747
748     D3DXMatrixTranslation(&m1, -psc.x, -psc.y, -psc.z);
749
750     if ( !pscalingrotation )
751     {
752         D3DXMatrixIdentity(&m2);
753         D3DXMatrixIdentity(&m4);
754     }
755     else
756     {
757         D3DXMatrixRotationQuaternion(&m4, pscalingrotation);
758         D3DXMatrixInverse(&m2, NULL, &m4);
759     }
760
761     if ( !pscaling ) D3DXMatrixIdentity(&m3);
762     else D3DXMatrixScaling(&m3, pscaling->x, pscaling->y, pscaling->z);
763
764     if ( !protation ) D3DXMatrixIdentity(&m6);
765     else D3DXMatrixRotationQuaternion(&m6, protation);
766
767     D3DXMatrixTranslation(&m5, psc.x - prc.x,  psc.y - prc.y,  psc.z - prc.z);
768     D3DXMatrixTranslation(&m7, prc.x + pt.x, prc.y + pt.y, prc.z + pt.z);
769     D3DXMatrixMultiply(&m1, &m1, &m2);
770     D3DXMatrixMultiply(&m1, &m1, &m3);
771     D3DXMatrixMultiply(&m1, &m1, &m4);
772     D3DXMatrixMultiply(&m1, &m1, &m5);
773     D3DXMatrixMultiply(&m1, &m1, &m6);
774     D3DXMatrixMultiply(pout, &m1, &m7);
775     return pout;
776 }
777
778 D3DXMATRIX* WINAPI D3DXMatrixTransformation2D(D3DXMATRIX *pout, CONST D3DXVECTOR2 *pscalingcenter, FLOAT scalingrotation, CONST D3DXVECTOR2 *pscaling, CONST D3DXVECTOR2 *protationcenter, FLOAT rotation, CONST D3DXVECTOR2 *ptranslation)
779 {
780     D3DXQUATERNION rot, sca_rot;
781     D3DXVECTOR3 rot_center, sca, sca_center, trans;
782
783     TRACE("(%p, %p, %f, %p, %p, %f, %p)\n", pout, pscalingcenter, scalingrotation, pscaling, protationcenter, rotation, ptranslation);
784
785     if ( pscalingcenter )
786     {
787         sca_center.x=pscalingcenter->x;
788         sca_center.y=pscalingcenter->y;
789         sca_center.z=0.0f;
790     }
791     else
792     {
793         sca_center.x=0.0f;
794         sca_center.y=0.0f;
795         sca_center.z=0.0f;
796     }
797
798     if ( pscaling )
799     {
800         sca.x=pscaling->x;
801         sca.y=pscaling->y;
802         sca.z=1.0f;
803     }
804     else
805     {
806         sca.x=1.0f;
807         sca.y=1.0f;
808         sca.z=1.0f;
809     }
810
811     if ( protationcenter )
812     {
813         rot_center.x=protationcenter->x;
814         rot_center.y=protationcenter->y;
815         rot_center.z=0.0f;
816     }
817     else
818     {
819         rot_center.x=0.0f;
820         rot_center.y=0.0f;
821         rot_center.z=0.0f;
822     }
823
824     if ( ptranslation )
825     {
826         trans.x=ptranslation->x;
827         trans.y=ptranslation->y;
828         trans.z=0.0f;
829     }
830     else
831     {
832         trans.x=0.0f;
833         trans.y=0.0f;
834         trans.z=0.0f;
835     }
836
837     rot.w=cos(rotation/2.0f);
838     rot.x=0.0f;
839     rot.y=0.0f;
840     rot.z=sin(rotation/2.0f);
841
842     sca_rot.w=cos(scalingrotation/2.0f);
843     sca_rot.x=0.0f;
844     sca_rot.y=0.0f;
845     sca_rot.z=sin(scalingrotation/2.0f);
846
847     D3DXMatrixTransformation(pout, &sca_center, &sca_rot, &sca, &rot_center, &rot, &trans);
848
849     return pout;
850 }
851
852 D3DXMATRIX* WINAPI D3DXMatrixTranslation(D3DXMATRIX *pout, FLOAT x, FLOAT y, FLOAT z)
853 {
854     TRACE("(%p, %f, %f, %f)\n", pout, x, y, z);
855
856     D3DXMatrixIdentity(pout);
857     pout->u.m[3][0] = x;
858     pout->u.m[3][1] = y;
859     pout->u.m[3][2] = z;
860     return pout;
861 }
862
863 D3DXMATRIX* WINAPI D3DXMatrixTranspose(D3DXMATRIX *pout, CONST D3DXMATRIX *pm)
864 {
865     CONST D3DXMATRIX m = *pm;
866     int i,j;
867
868     TRACE("(%p, %p)\n", pout, pm);
869
870     for (i=0; i<4; i++)
871         for (j=0; j<4; j++) pout->u.m[i][j] = m.u.m[j][i];
872
873     return pout;
874 }
875
876 /*_________________D3DXMatrixStack____________________*/
877
878 static const unsigned int INITIAL_STACK_SIZE = 32;
879
880 HRESULT WINAPI D3DXCreateMatrixStack(DWORD flags, ID3DXMatrixStack **ppstack)
881 {
882     struct ID3DXMatrixStackImpl *object;
883
884     TRACE("flags %#x, ppstack %p\n", flags, ppstack);
885
886     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
887     if (object == NULL)
888     {
889         *ppstack = NULL;
890         return E_OUTOFMEMORY;
891     }
892     object->ID3DXMatrixStack_iface.lpVtbl = &ID3DXMatrixStack_Vtbl;
893     object->ref = 1;
894
895     object->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_STACK_SIZE * sizeof(*object->stack));
896     if (!object->stack)
897     {
898         HeapFree(GetProcessHeap(), 0, object);
899         *ppstack = NULL;
900         return E_OUTOFMEMORY;
901     }
902
903     object->current = 0;
904     object->stack_size = INITIAL_STACK_SIZE;
905     D3DXMatrixIdentity(&object->stack[0]);
906
907     TRACE("Created matrix stack %p\n", object);
908
909     *ppstack = &object->ID3DXMatrixStack_iface;
910     return D3D_OK;
911 }
912
913 static inline struct ID3DXMatrixStackImpl *impl_from_ID3DXMatrixStack(ID3DXMatrixStack *iface)
914 {
915   return CONTAINING_RECORD(iface, struct ID3DXMatrixStackImpl, ID3DXMatrixStack_iface);
916 }
917
918 static HRESULT WINAPI ID3DXMatrixStackImpl_QueryInterface(ID3DXMatrixStack *iface, REFIID riid, void **out)
919 {
920     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
921
922     if (IsEqualGUID(riid, &IID_ID3DXMatrixStack)
923             || IsEqualGUID(riid, &IID_IUnknown))
924     {
925         ID3DXMatrixStack_AddRef(iface);
926         *out = iface;
927         return S_OK;
928     }
929
930     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
931
932     *out = NULL;
933     return E_NOINTERFACE;
934 }
935
936 static ULONG WINAPI ID3DXMatrixStackImpl_AddRef(ID3DXMatrixStack *iface)
937 {
938     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
939     ULONG ref = InterlockedIncrement(&This->ref);
940     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
941     return ref;
942 }
943
944 static ULONG WINAPI ID3DXMatrixStackImpl_Release(ID3DXMatrixStack *iface)
945 {
946     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
947     ULONG ref = InterlockedDecrement(&This->ref);
948     if (!ref)
949     {
950         HeapFree(GetProcessHeap(), 0, This->stack);
951         HeapFree(GetProcessHeap(), 0, This);
952     }
953     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
954     return ref;
955 }
956
957 static D3DXMATRIX* WINAPI ID3DXMatrixStackImpl_GetTop(ID3DXMatrixStack *iface)
958 {
959     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
960
961     TRACE("iface %p\n", iface);
962
963     return &This->stack[This->current];
964 }
965
966 static HRESULT WINAPI ID3DXMatrixStackImpl_LoadIdentity(ID3DXMatrixStack *iface)
967 {
968     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
969
970     TRACE("iface %p\n", iface);
971
972     D3DXMatrixIdentity(&This->stack[This->current]);
973
974     return D3D_OK;
975 }
976
977 static HRESULT WINAPI ID3DXMatrixStackImpl_LoadMatrix(ID3DXMatrixStack *iface, CONST D3DXMATRIX *pm)
978 {
979     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
980
981     TRACE("iface %p\n", iface);
982
983     This->stack[This->current] = *pm;
984
985     return D3D_OK;
986 }
987
988 static HRESULT WINAPI ID3DXMatrixStackImpl_MultMatrix(ID3DXMatrixStack *iface, CONST D3DXMATRIX *pm)
989 {
990     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
991
992     TRACE("iface %p\n", iface);
993
994     D3DXMatrixMultiply(&This->stack[This->current], &This->stack[This->current], pm);
995
996     return D3D_OK;
997 }
998
999 static HRESULT WINAPI ID3DXMatrixStackImpl_MultMatrixLocal(ID3DXMatrixStack *iface, CONST D3DXMATRIX *pm)
1000 {
1001     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1002
1003     TRACE("iface %p\n", iface);
1004
1005     D3DXMatrixMultiply(&This->stack[This->current], pm, &This->stack[This->current]);
1006
1007     return D3D_OK;
1008 }
1009
1010 static HRESULT WINAPI ID3DXMatrixStackImpl_Pop(ID3DXMatrixStack *iface)
1011 {
1012     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1013
1014     TRACE("iface %p\n", iface);
1015
1016     /* Popping the last element on the stack returns D3D_OK, but does nothing. */
1017     if (!This->current) return D3D_OK;
1018
1019     if (This->current <= This->stack_size / 4 && This->stack_size >= INITIAL_STACK_SIZE * 2)
1020     {
1021         unsigned int new_size;
1022         D3DXMATRIX *new_stack;
1023
1024         new_size = This->stack_size / 2;
1025         new_stack = HeapReAlloc(GetProcessHeap(), 0, This->stack, new_size * sizeof(*new_stack));
1026         if (new_stack)
1027         {
1028             This->stack_size = new_size;
1029             This->stack = new_stack;
1030         }
1031     }
1032
1033     --This->current;
1034
1035     return D3D_OK;
1036 }
1037
1038 static HRESULT WINAPI ID3DXMatrixStackImpl_Push(ID3DXMatrixStack *iface)
1039 {
1040     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1041
1042     TRACE("iface %p\n", iface);
1043
1044     if (This->current == This->stack_size - 1)
1045     {
1046         unsigned int new_size;
1047         D3DXMATRIX *new_stack;
1048
1049         if (This->stack_size > UINT_MAX / 2) return E_OUTOFMEMORY;
1050
1051         new_size = This->stack_size * 2;
1052         new_stack = HeapReAlloc(GetProcessHeap(), 0, This->stack, new_size * sizeof(*new_stack));
1053         if (!new_stack) return E_OUTOFMEMORY;
1054
1055         This->stack_size = new_size;
1056         This->stack = new_stack;
1057     }
1058
1059     ++This->current;
1060     This->stack[This->current] = This->stack[This->current - 1];
1061
1062     return D3D_OK;
1063 }
1064
1065 static HRESULT WINAPI ID3DXMatrixStackImpl_RotateAxis(ID3DXMatrixStack *iface, CONST D3DXVECTOR3 *pv, FLOAT angle)
1066 {
1067     D3DXMATRIX temp;
1068     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1069
1070     TRACE("iface %p\n", iface);
1071
1072     D3DXMatrixRotationAxis(&temp, pv, angle);
1073     D3DXMatrixMultiply(&This->stack[This->current], &This->stack[This->current], &temp);
1074
1075     return D3D_OK;
1076 }
1077
1078 static HRESULT WINAPI ID3DXMatrixStackImpl_RotateAxisLocal(ID3DXMatrixStack *iface, CONST D3DXVECTOR3 *pv, FLOAT angle)
1079 {
1080     D3DXMATRIX temp;
1081     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1082
1083     TRACE("iface %p\n", iface);
1084
1085     D3DXMatrixRotationAxis(&temp, pv, angle);
1086     D3DXMatrixMultiply(&This->stack[This->current], &temp, &This->stack[This->current]);
1087
1088     return D3D_OK;
1089 }
1090
1091 static HRESULT WINAPI ID3DXMatrixStackImpl_RotateYawPitchRoll(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
1092 {
1093     D3DXMATRIX temp;
1094     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1095
1096     TRACE("iface %p\n", iface);
1097
1098     D3DXMatrixRotationYawPitchRoll(&temp, x, y, z);
1099     D3DXMatrixMultiply(&This->stack[This->current], &This->stack[This->current], &temp);
1100
1101     return D3D_OK;
1102 }
1103
1104 static HRESULT WINAPI ID3DXMatrixStackImpl_RotateYawPitchRollLocal(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
1105 {
1106     D3DXMATRIX temp;
1107     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1108
1109     TRACE("iface %p\n", iface);
1110
1111     D3DXMatrixRotationYawPitchRoll(&temp, x, y, z);
1112     D3DXMatrixMultiply(&This->stack[This->current], &temp, &This->stack[This->current]);
1113
1114     return D3D_OK;
1115 }
1116
1117 static HRESULT WINAPI ID3DXMatrixStackImpl_Scale(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
1118 {
1119     D3DXMATRIX temp;
1120     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1121
1122     TRACE("iface %p\n", iface);
1123
1124     D3DXMatrixScaling(&temp, x, y, z);
1125     D3DXMatrixMultiply(&This->stack[This->current], &This->stack[This->current], &temp);
1126
1127     return D3D_OK;
1128 }
1129
1130 static HRESULT WINAPI ID3DXMatrixStackImpl_ScaleLocal(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
1131 {
1132     D3DXMATRIX temp;
1133     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1134
1135     TRACE("iface %p\n", iface);
1136
1137     D3DXMatrixScaling(&temp, x, y, z);
1138     D3DXMatrixMultiply(&This->stack[This->current], &temp, &This->stack[This->current]);
1139
1140     return D3D_OK;
1141 }
1142
1143 static HRESULT WINAPI ID3DXMatrixStackImpl_Translate(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
1144 {
1145     D3DXMATRIX temp;
1146     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1147
1148     TRACE("iface %p\n", iface);
1149
1150     D3DXMatrixTranslation(&temp, x, y, z);
1151     D3DXMatrixMultiply(&This->stack[This->current], &This->stack[This->current], &temp);
1152
1153     return D3D_OK;
1154 }
1155
1156 static HRESULT WINAPI ID3DXMatrixStackImpl_TranslateLocal(ID3DXMatrixStack *iface, FLOAT x, FLOAT y, FLOAT z)
1157 {
1158     D3DXMATRIX temp;
1159     struct ID3DXMatrixStackImpl *This = impl_from_ID3DXMatrixStack(iface);
1160
1161     TRACE("iface %p\n", iface);
1162
1163     D3DXMatrixTranslation(&temp, x, y, z);
1164     D3DXMatrixMultiply(&This->stack[This->current], &temp,&This->stack[This->current]);
1165
1166     return D3D_OK;
1167 }
1168
1169 static const ID3DXMatrixStackVtbl ID3DXMatrixStack_Vtbl =
1170 {
1171     ID3DXMatrixStackImpl_QueryInterface,
1172     ID3DXMatrixStackImpl_AddRef,
1173     ID3DXMatrixStackImpl_Release,
1174     ID3DXMatrixStackImpl_Pop,
1175     ID3DXMatrixStackImpl_Push,
1176     ID3DXMatrixStackImpl_LoadIdentity,
1177     ID3DXMatrixStackImpl_LoadMatrix,
1178     ID3DXMatrixStackImpl_MultMatrix,
1179     ID3DXMatrixStackImpl_MultMatrixLocal,
1180     ID3DXMatrixStackImpl_RotateAxis,
1181     ID3DXMatrixStackImpl_RotateAxisLocal,
1182     ID3DXMatrixStackImpl_RotateYawPitchRoll,
1183     ID3DXMatrixStackImpl_RotateYawPitchRollLocal,
1184     ID3DXMatrixStackImpl_Scale,
1185     ID3DXMatrixStackImpl_ScaleLocal,
1186     ID3DXMatrixStackImpl_Translate,
1187     ID3DXMatrixStackImpl_TranslateLocal,
1188     ID3DXMatrixStackImpl_GetTop
1189 };
1190
1191 /*_________________D3DXPLANE________________*/
1192
1193 D3DXPLANE* WINAPI D3DXPlaneFromPointNormal(D3DXPLANE *pout, CONST D3DXVECTOR3 *pvpoint, CONST D3DXVECTOR3 *pvnormal)
1194 {
1195     TRACE("(%p, %p, %p)\n", pout, pvpoint, pvnormal);
1196
1197     pout->a = pvnormal->x;
1198     pout->b = pvnormal->y;
1199     pout->c = pvnormal->z;
1200     pout->d = -D3DXVec3Dot(pvpoint, pvnormal);
1201     return pout;
1202 }
1203
1204 D3DXPLANE* WINAPI D3DXPlaneFromPoints(D3DXPLANE *pout, CONST D3DXVECTOR3 *pv1, CONST D3DXVECTOR3 *pv2, CONST D3DXVECTOR3 *pv3)
1205 {
1206     D3DXVECTOR3 edge1, edge2, normal, Nnormal;
1207
1208     TRACE("(%p, %p, %p, %p)\n", pout, pv1, pv2, pv3);
1209
1210     edge1.x = 0.0f; edge1.y = 0.0f; edge1.z = 0.0f;
1211     edge2.x = 0.0f; edge2.y = 0.0f; edge2.z = 0.0f;
1212     D3DXVec3Subtract(&edge1, pv2, pv1);
1213     D3DXVec3Subtract(&edge2, pv3, pv1);
1214     D3DXVec3Cross(&normal, &edge1, &edge2);
1215     D3DXVec3Normalize(&Nnormal, &normal);
1216     D3DXPlaneFromPointNormal(pout, pv1, &Nnormal);
1217     return pout;
1218 }
1219
1220 D3DXVECTOR3* WINAPI D3DXPlaneIntersectLine(D3DXVECTOR3 *pout, CONST D3DXPLANE *pp, CONST D3DXVECTOR3 *pv1, CONST D3DXVECTOR3 *pv2)
1221 {
1222     D3DXVECTOR3 direction, normal;
1223     FLOAT dot, temp;
1224
1225     TRACE("(%p, %p, %p, %p)\n", pout, pp, pv1, pv2);
1226
1227     normal.x = pp->a;
1228     normal.y = pp->b;
1229     normal.z = pp->c;
1230     direction.x = pv2->x - pv1->x;
1231     direction.y = pv2->y - pv1->y;
1232     direction.z = pv2->z - pv1->z;
1233     dot = D3DXVec3Dot(&normal, &direction);
1234     if ( !dot ) return NULL;
1235     temp = ( pp->d + D3DXVec3Dot(&normal, pv1) ) / dot;
1236     pout->x = pv1->x - temp * direction.x;
1237     pout->y = pv1->y - temp * direction.y;
1238     pout->z = pv1->z - temp * direction.z;
1239     return pout;
1240 }
1241
1242 D3DXPLANE * WINAPI D3DXPlaneNormalize(D3DXPLANE *out, const D3DXPLANE *p)
1243 {
1244     FLOAT norm;
1245
1246     TRACE("out %p, p %p\n", out, p);
1247
1248     norm = sqrtf(p->a * p->a + p->b * p->b + p->c * p->c);
1249     if (norm)
1250     {
1251         out->a = p->a / norm;
1252         out->b = p->b / norm;
1253         out->c = p->c / norm;
1254         out->d = p->d / norm;
1255     }
1256     else
1257     {
1258         out->a = 0.0f;
1259         out->b = 0.0f;
1260         out->c = 0.0f;
1261         out->d = 0.0f;
1262     }
1263
1264     return out;
1265 }
1266
1267 D3DXPLANE* WINAPI D3DXPlaneTransform(D3DXPLANE *pout, CONST D3DXPLANE *pplane, CONST D3DXMATRIX *pm)
1268 {
1269     CONST D3DXPLANE plane = *pplane;
1270
1271     TRACE("(%p, %p, %p)\n", pout, pplane, pm);
1272
1273     pout->a = pm->u.m[0][0] * plane.a + pm->u.m[1][0] * plane.b + pm->u.m[2][0] * plane.c + pm->u.m[3][0] * plane.d;
1274     pout->b = pm->u.m[0][1] * plane.a + pm->u.m[1][1] * plane.b + pm->u.m[2][1] * plane.c + pm->u.m[3][1] * plane.d;
1275     pout->c = pm->u.m[0][2] * plane.a + pm->u.m[1][2] * plane.b + pm->u.m[2][2] * plane.c + pm->u.m[3][2] * plane.d;
1276     pout->d = pm->u.m[0][3] * plane.a + pm->u.m[1][3] * plane.b + pm->u.m[2][3] * plane.c + pm->u.m[3][3] * plane.d;
1277     return pout;
1278 }
1279
1280 D3DXPLANE* WINAPI D3DXPlaneTransformArray(D3DXPLANE* out, UINT outstride, CONST D3DXPLANE* in, UINT instride, CONST D3DXMATRIX* matrix, UINT elements)
1281 {
1282     UINT i;
1283
1284     TRACE("(%p, %u, %p, %u, %p, %u)\n", out, outstride, in, instride, matrix, elements);
1285
1286     for (i = 0; i < elements; ++i) {
1287         D3DXPlaneTransform(
1288             (D3DXPLANE*)((char*)out + outstride * i),
1289             (CONST D3DXPLANE*)((const char*)in + instride * i),
1290             matrix);
1291     }
1292     return out;
1293 }
1294
1295 /*_________________D3DXQUATERNION________________*/
1296
1297 D3DXQUATERNION* WINAPI D3DXQuaternionBaryCentric(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq1, CONST D3DXQUATERNION *pq2, CONST D3DXQUATERNION *pq3, FLOAT f, FLOAT g)
1298 {
1299     D3DXQUATERNION temp1, temp2;
1300
1301     TRACE("(%p, %p, %p, %p, %f, %f)\n", pout, pq1, pq2, pq3, f, g);
1302
1303     D3DXQuaternionSlerp(pout, D3DXQuaternionSlerp(&temp1, pq1, pq2, f + g), D3DXQuaternionSlerp(&temp2, pq1, pq3, f+g), g / (f + g));
1304     return pout;
1305 }
1306
1307 D3DXQUATERNION * WINAPI D3DXQuaternionExp(D3DXQUATERNION *out, const D3DXQUATERNION *q)
1308 {
1309     FLOAT norm;
1310
1311     TRACE("out %p, q %p\n", out, q);
1312
1313     norm = sqrtf(q->x * q->x + q->y * q->y + q->z * q->z);
1314     if (norm)
1315     {
1316         out->x = sinf(norm) * q->x / norm;
1317         out->y = sinf(norm) * q->y / norm;
1318         out->z = sinf(norm) * q->z / norm;
1319         out->w = cosf(norm);
1320     }
1321     else
1322     {
1323         out->x = 0.0f;
1324         out->y = 0.0f;
1325         out->z = 0.0f;
1326         out->w = 1.0f;
1327     }
1328
1329     return out;
1330 }
1331
1332 D3DXQUATERNION* WINAPI D3DXQuaternionInverse(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq)
1333 {
1334     D3DXQUATERNION out;
1335     FLOAT norm;
1336
1337     TRACE("(%p, %p)\n", pout, pq);
1338
1339     norm = D3DXQuaternionLengthSq(pq);
1340
1341     out.x = -pq->x / norm;
1342     out.y = -pq->y / norm;
1343     out.z = -pq->z / norm;
1344     out.w = pq->w / norm;
1345
1346     *pout =out;
1347     return pout;
1348 }
1349
1350 D3DXQUATERNION * WINAPI D3DXQuaternionLn(D3DXQUATERNION *out, const D3DXQUATERNION *q)
1351 {
1352     FLOAT t;
1353
1354     TRACE("out %p, q %p\n", out, q);
1355
1356     if ((q->w >= 1.0f) || (q->w == -1.0f))
1357         t = 1.0f;
1358     else
1359         t = acosf(q->w) / sqrtf(1.0f - q->w * q->w);
1360
1361     out->x = t * q->x;
1362     out->y = t * q->y;
1363     out->z = t * q->z;
1364     out->w = 0.0f;
1365
1366     return out;
1367 }
1368
1369 D3DXQUATERNION* WINAPI D3DXQuaternionMultiply(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq1, CONST D3DXQUATERNION *pq2)
1370 {
1371     D3DXQUATERNION out;
1372
1373     TRACE("(%p, %p, %p)\n", pout, pq1, pq2);
1374
1375     out.x = pq2->w * pq1->x + pq2->x * pq1->w + pq2->y * pq1->z - pq2->z * pq1->y;
1376     out.y = pq2->w * pq1->y - pq2->x * pq1->z + pq2->y * pq1->w + pq2->z * pq1->x;
1377     out.z = pq2->w * pq1->z + pq2->x * pq1->y - pq2->y * pq1->x + pq2->z * pq1->w;
1378     out.w = pq2->w * pq1->w - pq2->x * pq1->x - pq2->y * pq1->y - pq2->z * pq1->z;
1379     *pout = out;
1380     return pout;
1381 }
1382
1383 D3DXQUATERNION * WINAPI D3DXQuaternionNormalize(D3DXQUATERNION *out, const D3DXQUATERNION *q)
1384 {
1385     FLOAT norm;
1386
1387     TRACE("out %p, q %p\n", out, q);
1388
1389     norm = D3DXQuaternionLength(q);
1390
1391     out->x = q->x / norm;
1392     out->y = q->y / norm;
1393     out->z = q->z / norm;
1394     out->w = q->w / norm;
1395
1396     return out;
1397 }
1398
1399 D3DXQUATERNION * WINAPI D3DXQuaternionRotationAxis(D3DXQUATERNION *out, const D3DXVECTOR3 *v, FLOAT angle)
1400 {
1401     D3DXVECTOR3 temp;
1402
1403     TRACE("out %p, v %p, angle %f\n", out, v, angle);
1404
1405     D3DXVec3Normalize(&temp, v);
1406
1407     out->x = sinf(angle / 2.0f) * temp.x;
1408     out->y = sinf(angle / 2.0f) * temp.y;
1409     out->z = sinf(angle / 2.0f) * temp.z;
1410     out->w = cosf(angle / 2.0f);
1411
1412     return out;
1413 }
1414
1415 D3DXQUATERNION * WINAPI D3DXQuaternionRotationMatrix(D3DXQUATERNION *out, const D3DXMATRIX *m)
1416 {
1417     FLOAT s, trace;
1418
1419     TRACE("out %p, m %p\n", out, m);
1420
1421     trace = m->u.m[0][0] + m->u.m[1][1] + m->u.m[2][2] + 1.0f;
1422     if (trace > 1.0f)
1423     {
1424         s = 2.0f * sqrtf(trace);
1425         out->x = (m->u.m[1][2] - m->u.m[2][1]) / s;
1426         out->y = (m->u.m[2][0] - m->u.m[0][2]) / s;
1427         out->z = (m->u.m[0][1] - m->u.m[1][0]) / s;
1428         out->w = 0.25f * s;
1429     }
1430     else
1431     {
1432         int i, maxi = 0;
1433
1434         for (i = 1; i < 3; i++)
1435         {
1436             if (m->u.m[i][i] > m->u.m[maxi][maxi])
1437                 maxi = i;
1438         }
1439
1440         switch (maxi)
1441         {
1442             case 0:
1443                 s = 2.0f * sqrtf(1.0f + m->u.m[0][0] - m->u.m[1][1] - m->u.m[2][2]);
1444                 out->x = 0.25f * s;
1445                 out->y = (m->u.m[0][1] + m->u.m[1][0]) / s;
1446                 out->z = (m->u.m[0][2] + m->u.m[2][0]) / s;
1447                 out->w = (m->u.m[1][2] - m->u.m[2][1]) / s;
1448                 break;
1449
1450             case 1:
1451                 s = 2.0f * sqrtf(1.0f + m->u.m[1][1] - m->u.m[0][0] - m->u.m[2][2]);
1452                 out->x = (m->u.m[0][1] + m->u.m[1][0]) / s;
1453                 out->y = 0.25f * s;
1454                 out->z = (m->u.m[1][2] + m->u.m[2][1]) / s;
1455                 out->w = (m->u.m[2][0] - m->u.m[0][2]) / s;
1456                 break;
1457
1458             case 2:
1459                 s = 2.0f * sqrtf(1.0f + m->u.m[2][2] - m->u.m[0][0] - m->u.m[1][1]);
1460                 out->x = (m->u.m[0][2] + m->u.m[2][0]) / s;
1461                 out->y = (m->u.m[1][2] + m->u.m[2][1]) / s;
1462                 out->z = 0.25f * s;
1463                 out->w = (m->u.m[0][1] - m->u.m[1][0]) / s;
1464                 break;
1465         }
1466     }
1467
1468     return out;
1469 }
1470
1471 D3DXQUATERNION * WINAPI D3DXQuaternionRotationYawPitchRoll(D3DXQUATERNION *out, FLOAT yaw, FLOAT pitch, FLOAT roll)
1472 {
1473     FLOAT syaw, cyaw, spitch, cpitch, sroll, croll;
1474
1475     TRACE("out %p, yaw %f, pitch %f, roll %f\n", out, yaw, pitch, roll);
1476
1477     syaw = sinf(yaw / 2.0f);
1478     cyaw = cosf(yaw / 2.0f);
1479     spitch = sinf(pitch / 2.0f);
1480     cpitch = cosf(pitch / 2.0f);
1481     sroll = sinf(roll / 2.0f);
1482     croll = cosf(roll / 2.0f);
1483
1484     out->x = syaw * cpitch * sroll + cyaw * spitch * croll;
1485     out->y = syaw * cpitch * croll - cyaw * spitch * sroll;
1486     out->z = cyaw * cpitch * sroll - syaw * spitch * croll;
1487     out->w = cyaw * cpitch * croll + syaw * spitch * sroll;
1488
1489     return out;
1490 }
1491
1492 D3DXQUATERNION * WINAPI D3DXQuaternionSlerp(D3DXQUATERNION *out, const D3DXQUATERNION *q1,
1493         const D3DXQUATERNION *q2, FLOAT t)
1494 {
1495     FLOAT dot, temp;
1496
1497     TRACE("out %p, q1 %p, q2 %p, t %f\n", out, q1, q2, t);
1498
1499     temp = 1.0f - t;
1500     dot = D3DXQuaternionDot(q1, q2);
1501     if (dot < 0.0f)
1502     {
1503         t = -t;
1504         dot = -dot;
1505     }
1506
1507     if (1.0f - dot > 0.001f)
1508     {
1509         FLOAT theta = acosf(dot);
1510
1511         temp = sinf(theta * temp) / sinf(theta);
1512         t = sinf(theta * t) / sinf(theta);
1513     }
1514
1515     out->x = temp * q1->x + t * q2->x;
1516     out->y = temp * q1->y + t * q2->y;
1517     out->z = temp * q1->z + t * q2->z;
1518     out->w = temp * q1->w + t * q2->w;
1519
1520     return out;
1521 }
1522
1523 D3DXQUATERNION* WINAPI D3DXQuaternionSquad(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq1, CONST D3DXQUATERNION *pq2, CONST D3DXQUATERNION *pq3, CONST D3DXQUATERNION *pq4, FLOAT t)
1524 {
1525     D3DXQUATERNION temp1, temp2;
1526
1527     TRACE("(%p, %p, %p, %p, %p, %f)\n", pout, pq1, pq2, pq3, pq4, t);
1528
1529     D3DXQuaternionSlerp(pout, D3DXQuaternionSlerp(&temp1, pq1, pq4, t), D3DXQuaternionSlerp(&temp2, pq2, pq3, t), 2.0f * t * (1.0f - t));
1530     return pout;
1531 }
1532
1533 static D3DXQUATERNION add_diff(CONST D3DXQUATERNION *q1, CONST D3DXQUATERNION *q2, CONST FLOAT add)
1534 {
1535     D3DXQUATERNION temp;
1536
1537     temp.x = q1->x + add * q2->x;
1538     temp.y = q1->y + add * q2->y;
1539     temp.z = q1->z + add * q2->z;
1540     temp.w = q1->w + add * q2->w;
1541
1542     return temp;
1543 }
1544
1545 void WINAPI D3DXQuaternionSquadSetup(D3DXQUATERNION *paout, D3DXQUATERNION *pbout, D3DXQUATERNION *pcout, CONST D3DXQUATERNION *pq0, CONST D3DXQUATERNION *pq1, CONST D3DXQUATERNION *pq2, CONST D3DXQUATERNION *pq3)
1546 {
1547     D3DXQUATERNION q, temp1, temp2, temp3, zero;
1548
1549     TRACE("(%p, %p, %p, %p, %p, %p, %p)\n", paout, pbout, pcout, pq0, pq1, pq2, pq3);
1550
1551     zero.x = 0.0f;
1552     zero.y = 0.0f;
1553     zero.z = 0.0f;
1554     zero.w = 0.0f;
1555
1556     if ( D3DXQuaternionDot(pq0, pq1) <  0.0f )
1557         temp2 = add_diff(&zero, pq0, -1.0f);
1558     else
1559         temp2 = *pq0;
1560
1561     if ( D3DXQuaternionDot(pq1, pq2) < 0.0f )
1562         *pcout = add_diff(&zero, pq2, -1.0f);
1563     else
1564         *pcout = *pq2;
1565
1566     if ( D3DXQuaternionDot(pcout, pq3) < 0.0f )
1567         temp3 = add_diff(&zero, pq3, -1.0f);
1568     else
1569         temp3 = *pq3;
1570
1571     D3DXQuaternionInverse(&temp1, pq1);
1572     D3DXQuaternionMultiply(&temp2, &temp1, &temp2);
1573     D3DXQuaternionLn(&temp2, &temp2);
1574     D3DXQuaternionMultiply(&q, &temp1, pcout);
1575     D3DXQuaternionLn(&q, &q);
1576     temp1 = add_diff(&temp2, &q, 1.0f);
1577     temp1.x *= -0.25f;
1578     temp1.y *= -0.25f;
1579     temp1.z *= -0.25f;
1580     temp1.w *= -0.25f;
1581     D3DXQuaternionExp(&temp1, &temp1);
1582     D3DXQuaternionMultiply(paout, pq1, &temp1);
1583
1584     D3DXQuaternionInverse(&temp1, pcout);
1585     D3DXQuaternionMultiply(&temp2, &temp1, pq1);
1586     D3DXQuaternionLn(&temp2, &temp2);
1587     D3DXQuaternionMultiply(&q, &temp1, &temp3);
1588     D3DXQuaternionLn(&q, &q);
1589     temp1 = add_diff(&temp2, &q, 1.0f);
1590     temp1.x *= -0.25f;
1591     temp1.y *= -0.25f;
1592     temp1.z *= -0.25f;
1593     temp1.w *= -0.25f;
1594     D3DXQuaternionExp(&temp1, &temp1);
1595     D3DXQuaternionMultiply(pbout, pcout, &temp1);
1596
1597     return;
1598 }
1599
1600 void WINAPI D3DXQuaternionToAxisAngle(CONST D3DXQUATERNION *pq, D3DXVECTOR3 *paxis, FLOAT *pangle)
1601 {
1602     TRACE("(%p, %p, %p)\n", pq, paxis, pangle);
1603
1604     paxis->x = pq->x;
1605     paxis->y = pq->y;
1606     paxis->z = pq->z;
1607     *pangle = 2.0f * acos(pq->w);
1608 }
1609
1610 /*_________________D3DXVec2_____________________*/
1611
1612 D3DXVECTOR2* WINAPI D3DXVec2BaryCentric(D3DXVECTOR2 *pout, CONST D3DXVECTOR2 *pv1, CONST D3DXVECTOR2 *pv2, CONST D3DXVECTOR2 *pv3, FLOAT f, FLOAT g)
1613 {
1614     TRACE("(%p, %p, %p, %p, %f, %f)\n", pout, pv1, pv2, pv3, f, g);
1615
1616     pout->x = (1.0f-f-g) * (pv1->x) + f * (pv2->x) + g * (pv3->x);
1617     pout->y = (1.0f-f-g) * (pv1->y) + f * (pv2->y) + g * (pv3->y);
1618     return pout;
1619 }
1620
1621 D3DXVECTOR2* WINAPI D3DXVec2CatmullRom(D3DXVECTOR2 *pout, CONST D3DXVECTOR2 *pv0, CONST D3DXVECTOR2 *pv1, CONST D3DXVECTOR2 *pv2, CONST D3DXVECTOR2 *pv3, FLOAT s)
1622 {
1623     TRACE("(%p, %p, %p, %p, %p, %f)\n", pout, pv0, pv1, pv2, pv3, s);
1624
1625     pout->x = 0.5f * (2.0f * pv1->x + (pv2->x - pv0->x) *s + (2.0f *pv0->x - 5.0f * pv1->x + 4.0f * pv2->x - pv3->x) * s * s + (pv3->x -3.0f * pv2->x + 3.0f * pv1->x - pv0->x) * s * s * s);
1626     pout->y = 0.5f * (2.0f * pv1->y + (pv2->y - pv0->y) *s + (2.0f *pv0->y - 5.0f * pv1->y + 4.0f * pv2->y - pv3->y) * s * s + (pv3->y -3.0f * pv2->y + 3.0f * pv1->y - pv0->y) * s * s * s);
1627     return pout;
1628 }
1629
1630 D3DXVECTOR2* WINAPI D3DXVec2Hermite(D3DXVECTOR2 *pout, CONST D3DXVECTOR2 *pv1, CONST D3DXVECTOR2 *pt1, CONST D3DXVECTOR2 *pv2, CONST D3DXVECTOR2 *pt2, FLOAT s)
1631 {
1632     FLOAT h1, h2, h3, h4;
1633
1634     TRACE("(%p, %p, %p, %p, %p, %f)\n", pout, pv1, pt1, pv2, pt2, s);
1635
1636     h1 = 2.0f * s * s * s - 3.0f * s * s + 1.0f;
1637     h2 = s * s * s - 2.0f * s * s + s;
1638     h3 = -2.0f * s * s * s + 3.0f * s * s;
1639     h4 = s * s * s - s * s;
1640
1641     pout->x = h1 * (pv1->x) + h2 * (pt1->x) + h3 * (pv2->x) + h4 * (pt2->x);
1642     pout->y = h1 * (pv1->y) + h2 * (pt1->y) + h3 * (pv2->y) + h4 * (pt2->y);
1643     return pout;
1644 }
1645
1646 D3DXVECTOR2* WINAPI D3DXVec2Normalize(D3DXVECTOR2 *pout, CONST D3DXVECTOR2 *pv)
1647 {
1648     FLOAT norm;
1649
1650     TRACE("(%p, %p)\n", pout, pv);
1651
1652     norm = D3DXVec2Length(pv);
1653     if ( !norm )
1654     {
1655         pout->x = 0.0f;
1656         pout->y = 0.0f;
1657     }
1658     else
1659     {
1660         pout->x = pv->x / norm;
1661         pout->y = pv->y / norm;
1662     }
1663
1664     return pout;
1665 }
1666
1667 D3DXVECTOR4* WINAPI D3DXVec2Transform(D3DXVECTOR4 *pout, CONST D3DXVECTOR2 *pv, CONST D3DXMATRIX *pm)
1668 {
1669     TRACE("(%p, %p, %p)\n", pout, pv, pm);
1670
1671     pout->x = pm->u.m[0][0] * pv->x + pm->u.m[1][0] * pv->y  + pm->u.m[3][0];
1672     pout->y = pm->u.m[0][1] * pv->x + pm->u.m[1][1] * pv->y  + pm->u.m[3][1];
1673     pout->z = pm->u.m[0][2] * pv->x + pm->u.m[1][2] * pv->y  + pm->u.m[3][2];
1674     pout->w = pm->u.m[0][3] * pv->x + pm->u.m[1][3] * pv->y  + pm->u.m[3][3];
1675     return pout;
1676 }
1677
1678 D3DXVECTOR4* WINAPI D3DXVec2TransformArray(D3DXVECTOR4* out, UINT outstride, CONST D3DXVECTOR2* in, UINT instride, CONST D3DXMATRIX* matrix, UINT elements)
1679 {
1680     UINT i;
1681
1682     TRACE("(%p, %u, %p, %u, %p, %u)\n", out, outstride, in, instride, matrix, elements);
1683
1684     for (i = 0; i < elements; ++i) {
1685         D3DXVec2Transform(
1686             (D3DXVECTOR4*)((char*)out + outstride * i),
1687             (CONST D3DXVECTOR2*)((const char*)in + instride * i),
1688             matrix);
1689     }
1690     return out;
1691 }
1692
1693 D3DXVECTOR2* WINAPI D3DXVec2TransformCoord(D3DXVECTOR2 *pout, CONST D3DXVECTOR2 *pv, CONST D3DXMATRIX *pm)
1694 {
1695     D3DXVECTOR2 v;
1696     FLOAT norm;
1697
1698     TRACE("(%p, %p, %p)\n", pout, pv, pm);
1699
1700     v = *pv;
1701     norm = pm->u.m[0][3] * pv->x + pm->u.m[1][3] * pv->y + pm->u.m[3][3];
1702
1703     pout->x = (pm->u.m[0][0] * v.x + pm->u.m[1][0] * v.y + pm->u.m[3][0]) / norm;
1704     pout->y = (pm->u.m[0][1] * v.x + pm->u.m[1][1] * v.y + pm->u.m[3][1]) / norm;
1705
1706     return pout;
1707 }
1708
1709 D3DXVECTOR2* WINAPI D3DXVec2TransformCoordArray(D3DXVECTOR2* out, UINT outstride, CONST D3DXVECTOR2* in, UINT instride, CONST D3DXMATRIX* matrix, UINT elements)
1710 {
1711     UINT i;
1712
1713     TRACE("(%p, %u, %p, %u, %p, %u)\n", out, outstride, in, instride, matrix, elements);
1714
1715     for (i = 0; i < elements; ++i) {
1716         D3DXVec2TransformCoord(
1717             (D3DXVECTOR2*)((char*)out + outstride * i),
1718             (CONST D3DXVECTOR2*)((const char*)in + instride * i),
1719             matrix);
1720     }
1721     return out;
1722 }
1723
1724 D3DXVECTOR2* WINAPI D3DXVec2TransformNormal(D3DXVECTOR2 *pout, CONST D3DXVECTOR2 *pv, CONST D3DXMATRIX *pm)
1725 {
1726     CONST D3DXVECTOR2 v = *pv;
1727     pout->x = pm->u.m[0][0] * v.x + pm->u.m[1][0] * v.y;
1728     pout->y = pm->u.m[0][1] * v.x + pm->u.m[1][1] * v.y;
1729     return pout;
1730 }
1731
1732 D3DXVECTOR2* WINAPI D3DXVec2TransformNormalArray(D3DXVECTOR2* out, UINT outstride, CONST D3DXVECTOR2 *in, UINT instride, CONST D3DXMATRIX *matrix, UINT elements)
1733 {
1734     UINT i;
1735
1736     TRACE("(%p, %u, %p, %u, %p, %u)\n", out, outstride, in, instride, matrix, elements);
1737
1738     for (i = 0; i < elements; ++i) {
1739         D3DXVec2TransformNormal(
1740             (D3DXVECTOR2*)((char*)out + outstride * i),
1741             (CONST D3DXVECTOR2*)((const char*)in + instride * i),
1742             matrix);
1743     }
1744     return out;
1745 }
1746
1747 /*_________________D3DXVec3_____________________*/
1748
1749 D3DXVECTOR3* WINAPI D3DXVec3BaryCentric(D3DXVECTOR3 *pout, CONST D3DXVECTOR3 *pv1, CONST D3DXVECTOR3 *pv2, CONST D3DXVECTOR3 *pv3, FLOAT f, FLOAT g)
1750 {
1751     TRACE("(%p, %p, %p, %p, %f, %f)\n", pout, pv1, pv2, pv3, f, g);
1752
1753     pout->x = (1.0f-f-g) * (pv1->x) + f * (pv2->x) + g * (pv3->x);
1754     pout->y = (1.0f-f-g) * (pv1->y) + f * (pv2->y) + g * (pv3->y);
1755     pout->z = (1.0f-f-g) * (pv1->z) + f * (pv2->z) + g * (pv3->z);
1756     return pout;
1757 }
1758
1759 D3DXVECTOR3* WINAPI D3DXVec3CatmullRom( D3DXVECTOR3 *pout, CONST D3DXVECTOR3 *pv0, CONST D3DXVECTOR3 *pv1, CONST D3DXVECTOR3 *pv2, CONST D3DXVECTOR3 *pv3, FLOAT s)
1760 {
1761     TRACE("(%p, %p, %p, %p, %p, %f)\n", pout, pv0, pv1, pv2, pv3, s);
1762
1763     pout->x = 0.5f * (2.0f * pv1->x + (pv2->x - pv0->x) *s + (2.0f *pv0->x - 5.0f * pv1->x + 4.0f * pv2->x - pv3->x) * s * s + (pv3->x -3.0f * pv2->x + 3.0f * pv1->x - pv0->x) * s * s * s);
1764     pout->y = 0.5f * (2.0f * pv1->y + (pv2->y - pv0->y) *s + (2.0f *pv0->y - 5.0f * pv1->y + 4.0f * pv2->y - pv3->y) * s * s + (pv3->y -3.0f * pv2->y + 3.0f * pv1->y - pv0->y) * s * s * s);
1765     pout->z = 0.5f * (2.0f * pv1->z + (pv2->z - pv0->z) *s + (2.0f *pv0->z - 5.0f * pv1->z + 4.0f * pv2->z - pv3->z) * s * s + (pv3->z -3.0f * pv2->z + 3.0f * pv1->z - pv0->z) * s * s * s);
1766     return pout;
1767 }
1768
1769 D3DXVECTOR3* WINAPI D3DXVec3Hermite(D3DXVECTOR3 *pout, CONST D3DXVECTOR3 *pv1, CONST D3DXVECTOR3 *pt1, CONST D3DXVECTOR3 *pv2, CONST D3DXVECTOR3 *pt2, FLOAT s)
1770 {
1771     FLOAT h1, h2, h3, h4;
1772
1773     TRACE("(%p, %p, %p, %p, %p, %f)\n", pout, pv1, pt1, pv2, pt2, s);
1774
1775     h1 = 2.0f * s * s * s - 3.0f * s * s + 1.0f;
1776     h2 = s * s * s - 2.0f * s * s + s;
1777     h3 = -2.0f * s * s * s + 3.0f * s * s;
1778     h4 = s * s * s - s * s;
1779
1780     pout->x = h1 * (pv1->x) + h2 * (pt1->x) + h3 * (pv2->x) + h4 * (pt2->x);
1781     pout->y = h1 * (pv1->y) + h2 * (pt1->y) + h3 * (pv2->y) + h4 * (pt2->y);
1782     pout->z = h1 * (pv1->z) + h2 * (pt1->z) + h3 * (pv2->z) + h4 * (pt2->z);
1783     return pout;
1784 }
1785
1786 D3DXVECTOR3* WINAPI D3DXVec3Normalize(D3DXVECTOR3 *pout, CONST D3DXVECTOR3 *pv)
1787 {
1788     FLOAT norm;
1789
1790     TRACE("(%p, %p)\n", pout, pv);
1791
1792     norm = D3DXVec3Length(pv);
1793     if ( !norm )
1794     {
1795         pout->x = 0.0f;
1796         pout->y = 0.0f;
1797         pout->z = 0.0f;
1798     }
1799     else
1800     {
1801         pout->x = pv->x / norm;
1802         pout->y = pv->y / norm;
1803         pout->z = pv->z / norm;
1804     }
1805
1806     return pout;
1807 }
1808
1809 D3DXVECTOR3* WINAPI D3DXVec3Project(D3DXVECTOR3 *pout, CONST D3DXVECTOR3 *pv, CONST D3DVIEWPORT9 *pviewport, CONST D3DXMATRIX *pprojection, CONST D3DXMATRIX *pview, CONST D3DXMATRIX *pworld)
1810 {
1811     D3DXMATRIX m;
1812
1813     TRACE("(%p, %p, %p, %p, %p, %p)\n", pout, pv, pviewport, pprojection, pview, pworld);
1814
1815     D3DXMatrixIdentity(&m);
1816     if (pworld) D3DXMatrixMultiply(&m, &m, pworld);
1817     if (pview) D3DXMatrixMultiply(&m, &m, pview);
1818     if (pprojection) D3DXMatrixMultiply(&m, &m, pprojection);
1819
1820     D3DXVec3TransformCoord(pout, pv, &m);
1821
1822     if (pviewport)
1823     {
1824         pout->x = pviewport->X +  ( 1.0f + pout->x ) * pviewport->Width / 2.0f;
1825         pout->y = pviewport->Y +  ( 1.0f - pout->y ) * pviewport->Height / 2.0f;
1826         pout->z = pviewport->MinZ + pout->z * ( pviewport->MaxZ - pviewport->MinZ );
1827     }
1828     return pout;
1829 }
1830
1831 D3DXVECTOR3* WINAPI D3DXVec3ProjectArray(D3DXVECTOR3* out, UINT outstride, CONST D3DXVECTOR3* in, UINT instride, CONST D3DVIEWPORT9* viewport, CONST D3DXMATRIX* projection, CONST D3DXMATRIX* view, CONST D3DXMATRIX* world, UINT elements)
1832 {
1833     UINT i;
1834
1835     TRACE("(%p, %u, %p, %u, %p, %p, %p, %p, %u)\n", out, outstride, in, instride, viewport, projection, view, world, elements);
1836
1837     for (i = 0; i < elements; ++i) {
1838         D3DXVec3Project(
1839             (D3DXVECTOR3*)((char*)out + outstride * i),
1840             (CONST D3DXVECTOR3*)((const char*)in + instride * i),
1841             viewport, projection, view, world);
1842     }
1843     return out;
1844 }
1845
1846 D3DXVECTOR4* WINAPI D3DXVec3Transform(D3DXVECTOR4 *pout, CONST D3DXVECTOR3 *pv, CONST D3DXMATRIX *pm)
1847 {
1848     TRACE("(%p, %p, %p)\n", pout, pv, pm);
1849
1850     pout->x = pm->u.m[0][0] * pv->x + pm->u.m[1][0] * pv->y + pm->u.m[2][0] * pv->z + pm->u.m[3][0];
1851     pout->y = pm->u.m[0][1] * pv->x + pm->u.m[1][1] * pv->y + pm->u.m[2][1] * pv->z + pm->u.m[3][1];
1852     pout->z = pm->u.m[0][2] * pv->x + pm->u.m[1][2] * pv->y + pm->u.m[2][2] * pv->z + pm->u.m[3][2];
1853     pout->w = pm->u.m[0][3] * pv->x + pm->u.m[1][3] * pv->y + pm->u.m[2][3] * pv->z + pm->u.m[3][3];
1854     return pout;
1855 }
1856
1857 D3DXVECTOR4* WINAPI D3DXVec3TransformArray(D3DXVECTOR4* out, UINT outstride, CONST D3DXVECTOR3* in, UINT instride, CONST D3DXMATRIX* matrix, UINT elements)
1858 {
1859     UINT i;
1860
1861     TRACE("(%p, %u, %p, %u, %p, %u)\n", out, outstride, in, instride, matrix, elements);
1862
1863     for (i = 0; i < elements; ++i) {
1864         D3DXVec3Transform(
1865             (D3DXVECTOR4*)((char*)out + outstride * i),
1866             (CONST D3DXVECTOR3*)((const char*)in + instride * i),
1867             matrix);
1868     }
1869     return out;
1870 }
1871
1872 D3DXVECTOR3* WINAPI D3DXVec3TransformCoord(D3DXVECTOR3 *pout, CONST D3DXVECTOR3 *pv, CONST D3DXMATRIX *pm)
1873 {
1874     D3DXVECTOR3 out;
1875     FLOAT norm;
1876
1877     TRACE("(%p, %p, %p)\n", pout, pv, pm);
1878
1879     norm = pm->u.m[0][3] * pv->x + pm->u.m[1][3] * pv->y + pm->u.m[2][3] *pv->z + pm->u.m[3][3];
1880
1881     out.x = (pm->u.m[0][0] * pv->x + pm->u.m[1][0] * pv->y + pm->u.m[2][0] * pv->z + pm->u.m[3][0]) / norm;
1882     out.y = (pm->u.m[0][1] * pv->x + pm->u.m[1][1] * pv->y + pm->u.m[2][1] * pv->z + pm->u.m[3][1]) / norm;
1883     out.z = (pm->u.m[0][2] * pv->x + pm->u.m[1][2] * pv->y + pm->u.m[2][2] * pv->z + pm->u.m[3][2]) / norm;
1884
1885     *pout = out;
1886
1887     return pout;
1888 }
1889
1890 D3DXVECTOR3* WINAPI D3DXVec3TransformCoordArray(D3DXVECTOR3* out, UINT outstride, CONST D3DXVECTOR3* in, UINT instride, CONST D3DXMATRIX* matrix, UINT elements)
1891 {
1892     UINT i;
1893
1894     TRACE("(%p, %u, %p, %u, %p, %u)\n", out, outstride, in, instride, matrix, elements);
1895
1896     for (i = 0; i < elements; ++i) {
1897         D3DXVec3TransformCoord(
1898             (D3DXVECTOR3*)((char*)out + outstride * i),
1899             (CONST D3DXVECTOR3*)((const char*)in + instride * i),
1900             matrix);
1901     }
1902     return out;
1903 }
1904
1905 D3DXVECTOR3* WINAPI D3DXVec3TransformNormal(D3DXVECTOR3 *pout, CONST D3DXVECTOR3 *pv, CONST D3DXMATRIX *pm)
1906 {
1907     CONST D3DXVECTOR3 v = *pv;
1908
1909     TRACE("(%p, %p, %p)\n", pout, pv, pm);
1910
1911     pout->x = pm->u.m[0][0] * v.x + pm->u.m[1][0] * v.y + pm->u.m[2][0] * v.z;
1912     pout->y = pm->u.m[0][1] * v.x + pm->u.m[1][1] * v.y + pm->u.m[2][1] * v.z;
1913     pout->z = pm->u.m[0][2] * v.x + pm->u.m[1][2] * v.y + pm->u.m[2][2] * v.z;
1914     return pout;
1915
1916 }
1917
1918 D3DXVECTOR3* WINAPI D3DXVec3TransformNormalArray(D3DXVECTOR3* out, UINT outstride, CONST D3DXVECTOR3* in, UINT instride, CONST D3DXMATRIX* matrix, UINT elements)
1919 {
1920     UINT i;
1921
1922     TRACE("(%p, %u, %p, %u, %p, %u)\n", out, outstride, in, instride, matrix, elements);
1923
1924     for (i = 0; i < elements; ++i) {
1925         D3DXVec3TransformNormal(
1926             (D3DXVECTOR3*)((char*)out + outstride * i),
1927             (CONST D3DXVECTOR3*)((const char*)in + instride * i),
1928             matrix);
1929     }
1930     return out;
1931 }
1932
1933 D3DXVECTOR3* WINAPI D3DXVec3Unproject(D3DXVECTOR3 *pout, CONST D3DXVECTOR3 *pv, CONST D3DVIEWPORT9 *pviewport, CONST D3DXMATRIX *pprojection, CONST D3DXMATRIX *pview, CONST D3DXMATRIX *pworld)
1934 {
1935     D3DXMATRIX m;
1936
1937     TRACE("(%p, %p, %p, %p, %p, %p)\n", pout, pv, pviewport, pprojection, pview, pworld);
1938
1939     D3DXMatrixIdentity(&m);
1940     if (pworld) D3DXMatrixMultiply(&m, &m, pworld);
1941     if (pview) D3DXMatrixMultiply(&m, &m, pview);
1942     if (pprojection) D3DXMatrixMultiply(&m, &m, pprojection);
1943     D3DXMatrixInverse(&m, NULL, &m);
1944
1945     *pout = *pv;
1946     if (pviewport)
1947     {
1948         pout->x = 2.0f * ( pout->x - pviewport->X ) / pviewport->Width - 1.0f;
1949         pout->y = 1.0f - 2.0f * ( pout->y - pviewport->Y ) / pviewport->Height;
1950         pout->z = ( pout->z - pviewport->MinZ) / ( pviewport->MaxZ - pviewport->MinZ );
1951     }
1952     D3DXVec3TransformCoord(pout, pout, &m);
1953     return pout;
1954 }
1955
1956 D3DXVECTOR3* WINAPI D3DXVec3UnprojectArray(D3DXVECTOR3* out, UINT outstride, CONST D3DXVECTOR3* in, UINT instride, CONST D3DVIEWPORT9* viewport, CONST D3DXMATRIX* projection, CONST D3DXMATRIX* view, CONST D3DXMATRIX* world, UINT elements)
1957 {
1958     UINT i;
1959
1960     TRACE("(%p, %u, %p, %u, %p, %p, %p, %p, %u)\n", out, outstride, in, instride, viewport, projection, view, world, elements);
1961
1962     for (i = 0; i < elements; ++i) {
1963         D3DXVec3Unproject(
1964             (D3DXVECTOR3*)((char*)out + outstride * i),
1965             (CONST D3DXVECTOR3*)((const char*)in + instride * i),
1966             viewport, projection, view, world);
1967     }
1968     return out;
1969 }
1970
1971 /*_________________D3DXVec4_____________________*/
1972
1973 D3DXVECTOR4* WINAPI D3DXVec4BaryCentric(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv1, CONST D3DXVECTOR4 *pv2, CONST D3DXVECTOR4 *pv3, FLOAT f, FLOAT g)
1974 {
1975     TRACE("(%p, %p, %p, %p, %f, %f)\n", pout, pv1, pv2, pv3, f, g);
1976
1977     pout->x = (1.0f-f-g) * (pv1->x) + f * (pv2->x) + g * (pv3->x);
1978     pout->y = (1.0f-f-g) * (pv1->y) + f * (pv2->y) + g * (pv3->y);
1979     pout->z = (1.0f-f-g) * (pv1->z) + f * (pv2->z) + g * (pv3->z);
1980     pout->w = (1.0f-f-g) * (pv1->w) + f * (pv2->w) + g * (pv3->w);
1981     return pout;
1982 }
1983
1984 D3DXVECTOR4* WINAPI D3DXVec4CatmullRom(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv0, CONST D3DXVECTOR4 *pv1, CONST D3DXVECTOR4 *pv2, CONST D3DXVECTOR4 *pv3, FLOAT s)
1985 {
1986     TRACE("(%p, %p, %p, %p, %p, %f)\n", pout, pv0, pv1, pv2, pv3, s);
1987
1988     pout->x = 0.5f * (2.0f * pv1->x + (pv2->x - pv0->x) *s + (2.0f *pv0->x - 5.0f * pv1->x + 4.0f * pv2->x - pv3->x) * s * s + (pv3->x -3.0f * pv2->x + 3.0f * pv1->x - pv0->x) * s * s * s);
1989     pout->y = 0.5f * (2.0f * pv1->y + (pv2->y - pv0->y) *s + (2.0f *pv0->y - 5.0f * pv1->y + 4.0f * pv2->y - pv3->y) * s * s + (pv3->y -3.0f * pv2->y + 3.0f * pv1->y - pv0->y) * s * s * s);
1990     pout->z = 0.5f * (2.0f * pv1->z + (pv2->z - pv0->z) *s + (2.0f *pv0->z - 5.0f * pv1->z + 4.0f * pv2->z - pv3->z) * s * s + (pv3->z -3.0f * pv2->z + 3.0f * pv1->z - pv0->z) * s * s * s);
1991     pout->w = 0.5f * (2.0f * pv1->w + (pv2->w - pv0->w) *s + (2.0f *pv0->w - 5.0f * pv1->w + 4.0f * pv2->w - pv3->w) * s * s + (pv3->w -3.0f * pv2->w + 3.0f * pv1->w - pv0->w) * s * s * s);
1992     return pout;
1993 }
1994
1995 D3DXVECTOR4* WINAPI D3DXVec4Cross(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv1, CONST D3DXVECTOR4 *pv2, CONST D3DXVECTOR4 *pv3)
1996 {
1997     D3DXVECTOR4 out;
1998
1999     TRACE("(%p, %p, %p, %p)\n", pout, pv1, pv2, pv3);
2000
2001     out.x = pv1->y * (pv2->z * pv3->w - pv3->z * pv2->w) - pv1->z * (pv2->y * pv3->w - pv3->y * pv2->w) + pv1->w * (pv2->y * pv3->z - pv2->z *pv3->y);
2002     out.y = -(pv1->x * (pv2->z * pv3->w - pv3->z * pv2->w) - pv1->z * (pv2->x * pv3->w - pv3->x * pv2->w) + pv1->w * (pv2->x * pv3->z - pv3->x * pv2->z));
2003     out.z = pv1->x * (pv2->y * pv3->w - pv3->y * pv2->w) - pv1->y * (pv2->x *pv3->w - pv3->x * pv2->w) + pv1->w * (pv2->x * pv3->y - pv3->x * pv2->y);
2004     out.w = -(pv1->x * (pv2->y * pv3->z - pv3->y * pv2->z) - pv1->y * (pv2->x * pv3->z - pv3->x *pv2->z) + pv1->z * (pv2->x * pv3->y - pv3->x * pv2->y));
2005     *pout = out;
2006     return pout;
2007 }
2008
2009 D3DXVECTOR4* WINAPI D3DXVec4Hermite(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv1, CONST D3DXVECTOR4 *pt1, CONST D3DXVECTOR4 *pv2, CONST D3DXVECTOR4 *pt2, FLOAT s)
2010 {
2011     FLOAT h1, h2, h3, h4;
2012
2013     TRACE("(%p, %p, %p, %p, %p, %f)\n", pout, pv1, pt1, pv2, pt2, s);
2014
2015     h1 = 2.0f * s * s * s - 3.0f * s * s + 1.0f;
2016     h2 = s * s * s - 2.0f * s * s + s;
2017     h3 = -2.0f * s * s * s + 3.0f * s * s;
2018     h4 = s * s * s - s * s;
2019
2020     pout->x = h1 * (pv1->x) + h2 * (pt1->x) + h3 * (pv2->x) + h4 * (pt2->x);
2021     pout->y = h1 * (pv1->y) + h2 * (pt1->y) + h3 * (pv2->y) + h4 * (pt2->y);
2022     pout->z = h1 * (pv1->z) + h2 * (pt1->z) + h3 * (pv2->z) + h4 * (pt2->z);
2023     pout->w = h1 * (pv1->w) + h2 * (pt1->w) + h3 * (pv2->w) + h4 * (pt2->w);
2024     return pout;
2025 }
2026
2027 D3DXVECTOR4* WINAPI D3DXVec4Normalize(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv)
2028 {
2029     FLOAT norm;
2030
2031     TRACE("(%p, %p)\n", pout, pv);
2032
2033     norm = D3DXVec4Length(pv);
2034
2035     pout->x = pv->x / norm;
2036     pout->y = pv->y / norm;
2037     pout->z = pv->z / norm;
2038     pout->w = pv->w / norm;
2039
2040     return pout;
2041 }
2042
2043 D3DXVECTOR4* WINAPI D3DXVec4Transform(D3DXVECTOR4 *pout, CONST D3DXVECTOR4 *pv, CONST D3DXMATRIX *pm)
2044 {
2045     D3DXVECTOR4 out;
2046
2047     TRACE("(%p, %p, %p)\n", pout, pv, pm);
2048
2049     out.x = pm->u.m[0][0] * pv->x + pm->u.m[1][0] * pv->y + pm->u.m[2][0] * pv->z + pm->u.m[3][0] * pv->w;
2050     out.y = pm->u.m[0][1] * pv->x + pm->u.m[1][1] * pv->y + pm->u.m[2][1] * pv->z + pm->u.m[3][1] * pv->w;
2051     out.z = pm->u.m[0][2] * pv->x + pm->u.m[1][2] * pv->y + pm->u.m[2][2] * pv->z + pm->u.m[3][2] * pv->w;
2052     out.w = pm->u.m[0][3] * pv->x + pm->u.m[1][3] * pv->y + pm->u.m[2][3] * pv->z + pm->u.m[3][3] * pv->w;
2053     *pout = out;
2054     return pout;
2055 }
2056
2057 D3DXVECTOR4* WINAPI D3DXVec4TransformArray(D3DXVECTOR4* out, UINT outstride, CONST D3DXVECTOR4* in, UINT instride, CONST D3DXMATRIX* matrix, UINT elements)
2058 {
2059     UINT i;
2060
2061     TRACE("(%p, %u, %p, %u, %p, %u)\n", out, outstride, in, instride, matrix, elements);
2062
2063     for (i = 0; i < elements; ++i) {
2064         D3DXVec4Transform(
2065             (D3DXVECTOR4*)((char*)out + outstride * i),
2066             (CONST D3DXVECTOR4*)((const char*)in + instride * i),
2067             matrix);
2068     }
2069     return out;
2070 }
2071
2072 static inline unsigned short float_32_to_16(const float in)
2073 {
2074     int exp = 0, origexp;
2075     float tmp = fabs(in);
2076     int sign = (copysignf(1, in) < 0);
2077     unsigned int mantissa;
2078     unsigned short ret;
2079
2080     /* Deal with special numbers */
2081     if (isinf(in)) return (sign ? 0xffff : 0x7fff);
2082     if (isnan(in)) return (sign ? 0xffff : 0x7fff);
2083     if (in == 0.0f) return (sign ? 0x8000 : 0x0000);
2084
2085     if (tmp < powf(2, 10))
2086     {
2087         do
2088         {
2089             tmp *= 2.0f;
2090             exp--;
2091         } while (tmp < powf(2, 10));
2092     }
2093     else if (tmp >= powf(2, 11))
2094     {
2095         do
2096         {
2097             tmp /= 2.0f;
2098             exp++;
2099         } while (tmp >= powf(2, 11));
2100     }
2101
2102     exp += 10;  /* Normalize the mantissa */
2103     exp += 15;  /* Exponent is encoded with excess 15 */
2104
2105     origexp = exp;
2106
2107     mantissa = (unsigned int) tmp;
2108     if ((tmp - mantissa == 0.5f && mantissa % 2 == 1) || /* round half to even */
2109         (tmp - mantissa > 0.5f))
2110     {
2111         mantissa++; /* round to nearest, away from zero */
2112     }
2113     if (mantissa == 2048)
2114     {
2115         mantissa = 1024;
2116         exp++;
2117     }
2118
2119     if (exp > 31)
2120     {
2121         /* too big */
2122         ret = 0x7fff; /* INF */
2123     }
2124     else if (exp <= 0)
2125     {
2126         unsigned int rounding = 0;
2127
2128         /* Denormalized half float */
2129
2130         /* return 0x0000 (=0.0) for numbers too small to represent in half floats */
2131         if (exp < -11)
2132             return (sign ? 0x8000 : 0x0000);
2133
2134         exp = origexp;
2135
2136         /* the 13 extra bits from single precision are used for rounding */
2137         mantissa = (unsigned int)(tmp * powf(2, 13));
2138         mantissa >>= 1 - exp; /* denormalize */
2139
2140         mantissa -= ~(mantissa >> 13) & 1; /* round half to even */
2141         /* remove 13 least significant bits to get half float precision */
2142         mantissa >>= 12;
2143         rounding = mantissa & 1;
2144         mantissa >>= 1;
2145
2146         ret = mantissa + rounding;
2147     }
2148     else
2149     {
2150         ret = (exp << 10) | (mantissa & 0x3ff);
2151     }
2152
2153     ret |= ((sign ? 1 : 0) << 15); /* Add the sign */
2154     return ret;
2155 }
2156
2157 D3DXFLOAT16 *WINAPI D3DXFloat32To16Array(D3DXFLOAT16 *pout, CONST FLOAT *pin, UINT n)
2158 {
2159     unsigned int i;
2160
2161     TRACE("(%p, %p, %u)\n", pout, pin, n);
2162
2163     for (i = 0; i < n; ++i)
2164     {
2165         pout[i].value = float_32_to_16(pin[i]);
2166     }
2167
2168     return pout;
2169 }
2170
2171 /* Native d3dx9's D3DXFloat16to32Array lacks support for NaN and Inf. Specifically, e = 16 is treated as a
2172  * regular number - e.g., 0x7fff is converted to 131008.0 and 0xffff to -131008.0. */
2173 static inline float float_16_to_32(const unsigned short in)
2174 {
2175     const unsigned short s = (in & 0x8000);
2176     const unsigned short e = (in & 0x7C00) >> 10;
2177     const unsigned short m = in & 0x3FF;
2178     const float sgn = (s ? -1.0f : 1.0f);
2179
2180     if (e == 0)
2181     {
2182         if (m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */
2183         else return sgn * powf(2, -14.0f) * (m / 1024.0f);
2184     }
2185     else
2186     {
2187         return sgn * powf(2, e - 15.0f) * (1.0f + (m / 1024.0f));
2188     }
2189 }
2190
2191 FLOAT *WINAPI D3DXFloat16To32Array(FLOAT *pout, CONST D3DXFLOAT16 *pin, UINT n)
2192 {
2193     unsigned int i;
2194
2195     TRACE("(%p, %p, %u)\n", pout, pin, n);
2196
2197     for (i = 0; i < n; ++i)
2198     {
2199         pout[i] = float_16_to_32(pin[i].value);
2200     }
2201
2202     return pout;
2203 }
2204
2205 /*_________________D3DXSH________________*/
2206
2207 FLOAT* WINAPI D3DXSHAdd(FLOAT *out, UINT order, const FLOAT *a, const FLOAT *b)
2208 {
2209     UINT i;
2210
2211     TRACE("out %p, order %u, a %p, b %p\n", out, order, a, b);
2212
2213     for (i = 0; i < order * order; i++)
2214         out[i] = a[i] + b[i];
2215
2216     return out;
2217 }
2218
2219 FLOAT WINAPI D3DXSHDot(UINT order, CONST FLOAT *a, CONST FLOAT *b)
2220 {
2221     FLOAT s;
2222     UINT i;
2223
2224     TRACE("order %u, a %p, b %p\n", order, a, b);
2225
2226     s = a[0] * b[0];
2227     for (i = 1; i < order * order; i++)
2228         s += a[i] * b[i];
2229
2230     return s;
2231 }
2232
2233 FLOAT* WINAPI D3DXSHEvalDirection(FLOAT *out, UINT order, CONST D3DXVECTOR3 *dir)
2234 {
2235
2236     TRACE("(%p, %u, %p)\n", out, order, dir);
2237
2238     if ( (order < D3DXSH_MINORDER) || (order > D3DXSH_MAXORDER) )
2239         return out;
2240
2241     out[0] = 0.5f / sqrt(D3DX_PI);
2242     out[1] = -0.5f / sqrt(D3DX_PI / 3.0f) * dir->y;
2243     out[2] = 0.5f / sqrt(D3DX_PI / 3.0f) * dir->z;
2244     out[3] = -0.5f / sqrt(D3DX_PI / 3.0f) * dir->x;
2245     if ( order == 2 )
2246         return out;
2247
2248     out[4] = 0.5f / sqrt(D3DX_PI / 15.0f) * dir->x * dir->y;
2249     out[5] = -0.5f / sqrt(D3DX_PI / 15.0f) * dir->y * dir->z;
2250     out[6] = 0.25f / sqrt(D3DX_PI / 5.0f) * ( 3.0f * dir->z * dir->z - 1.0f );
2251     out[7] = -0.5f / sqrt(D3DX_PI / 15.0f) * dir->x * dir->z;
2252     out[8] = 0.25f / sqrt(D3DX_PI / 15.0f) * ( dir->x * dir->x - dir->y * dir->y );
2253     if ( order == 3 )
2254         return out;
2255
2256     out[9] = -sqrt(70.0f / D3DX_PI) / 8.0f * dir->y * (3.0f * dir->x * dir->x - dir->y * dir->y );
2257     out[10] = sqrt(105.0f / D3DX_PI) / 2.0f * dir->x * dir->y * dir->z;
2258     out[11] = -sqrt(42.0 / D3DX_PI) / 8.0f * dir->y * ( -1.0f + 5.0f * dir->z * dir->z );
2259     out[12] = sqrt(7.0f / D3DX_PI) / 4.0f * dir->z * ( 5.0f * dir->z * dir->z - 3.0f );
2260     out[13] = sqrt(42.0 / D3DX_PI) / 8.0f * dir->x * ( 1.0f - 5.0f * dir->z * dir->z );
2261     out[14] = sqrt(105.0f / D3DX_PI) / 4.0f * dir->z * ( dir->x * dir->x - dir->y * dir->y );
2262     out[15] = -sqrt(70.0f / D3DX_PI) / 8.0f * dir->x * ( dir->x * dir->x - 3.0f * dir->y * dir->y );
2263     if ( order == 4 )
2264         return out;
2265
2266     out[16] = 0.75f * sqrt(35.0f / D3DX_PI) * dir->x * dir->y * (dir->x * dir->x - dir->y * dir->y );
2267     out[17] = 3.0f * dir->z * out[9];
2268     out[18] = 0.75f * sqrt(5.0f / D3DX_PI) * dir->x * dir->y * ( 7.0f * dir->z * dir->z - 1.0f );
2269     out[19] = 0.375f * sqrt(10.0f / D3DX_PI) * dir->y * dir->z * ( 3.0f - 7.0f * dir->z * dir->z );
2270     out[20] = 3.0f / ( 16.0f * sqrt(D3DX_PI) ) * ( 35.0f * dir->z * dir->z * dir->z * dir->z - 30.f * dir->z * dir->z + 3.0f );
2271     out[21] = 0.375f * sqrt(10.0f / D3DX_PI) * dir->x * dir->z * ( 3.0f - 7.0f * dir->z * dir->z );
2272     out[22] = 0.375f * sqrt(5.0f / D3DX_PI) * ( dir->x * dir->x - dir->y * dir->y ) * ( 7.0f * dir->z * dir->z - 1.0f);
2273     out[23] = 3.0 * dir->z * out[15];
2274     out[24] = 3.0f / 16.0f * sqrt(35.0f / D3DX_PI) * ( dir->x * dir->x * dir->x * dir->x- 6.0f * dir->x * dir->x * dir->y * dir->y + dir->y * dir->y * dir->y * dir->y );
2275     if ( order == 5 )
2276         return out;
2277
2278     out[25] = -3.0f/ 32.0f * sqrt(154.0f / D3DX_PI) * dir->y * ( 5.0f * dir->x * dir->x * dir->x * dir->x - 10.0f * dir->x * dir->x * dir->y * dir->y + dir->y * dir->y * dir->y * dir->y );
2279     out[26] = 0.75f * sqrt(385.0f / D3DX_PI) * dir->x * dir->y * dir->z * ( dir->x * dir->x - dir->y * dir->y );
2280     out[27] = sqrt(770.0f / D3DX_PI) / 32.0f * dir->y * ( 3.0f * dir->x * dir->x - dir->y * dir->y ) * ( 1.0f - 9.0f * dir->z * dir->z );
2281     out[28] = sqrt(1155.0f / D3DX_PI) / 4.0f * dir->x * dir->y * dir->z * ( 3.0f * dir->z * dir->z - 1.0f);
2282     out[29] = sqrt(165.0f / D3DX_PI) / 16.0f * dir->y * ( 14.0f * dir->z * dir->z - 21.0f * dir->z * dir->z * dir->z * dir->z - 1.0f );
2283     out[30] = sqrt(11.0f / D3DX_PI) / 16.0f * dir->z * ( 63.0f * dir->z * dir->z * dir->z * dir->z - 70.0f * dir->z * dir->z + 15.0f );
2284     out[31] = sqrt(165.0f / D3DX_PI) / 16.0f * dir->x * ( 14.0f * dir->z * dir->z - 21.0f * dir->z * dir->z * dir->z * dir->z - 1.0f );
2285     out[32] = sqrt(1155.0f / D3DX_PI) / 8.0f * dir->z * ( dir->x * dir->x - dir->y * dir->y ) * ( 3.0f * dir->z * dir->z - 1.0f );
2286     out[33] = sqrt(770.0f / D3DX_PI) / 32.0f * dir->x * ( dir->x * dir->x - 3.0f * dir->y * dir->y ) * ( 1.0f - 9.0f * dir->z * dir->z );
2287     out[34] = 3.0f / 16.0f * sqrt(385.0f / D3DX_PI) * dir->z * ( dir->x * dir->x * dir->x * dir->x - 6.0 * dir->x * dir->x * dir->y * dir->y + dir->y * dir->y * dir->y * dir->y );
2288     out[35] = -3.0f/ 32.0f * sqrt(154.0f / D3DX_PI) * dir->x * ( dir->x * dir->x * dir->x * dir->x - 10.0f * dir->x * dir->x * dir->y * dir->y + 5.0f * dir->y * dir->y * dir->y * dir->y );
2289
2290     return out;
2291 }
2292
2293 HRESULT WINAPI D3DXSHEvalDirectionalLight(UINT order, CONST D3DXVECTOR3 *dir, FLOAT Rintensity, FLOAT Gintensity, FLOAT Bintensity, FLOAT *Rout, FLOAT *Gout, FLOAT *Bout)
2294 {
2295     FLOAT s, temp;
2296     UINT j;
2297
2298     TRACE("Order %u, Vector %p, Red %f, Green %f, Blue %f, Rout %p, Gout %p, Bout %p\n", order, dir, Rintensity, Gintensity, Bintensity, Rout, Gout, Bout);
2299
2300     s = 0.75f;
2301     if ( order > 2 )
2302         s += 5.0f / 16.0f;
2303     if ( order > 4 )
2304         s -= 3.0f / 32.0f;
2305     s /= D3DX_PI;
2306
2307     D3DXSHEvalDirection(Rout, order, dir);
2308     for (j = 0; j < order * order; j++)
2309     {
2310         temp = Rout[j] / s;
2311
2312         Rout[j] = Rintensity * temp;
2313         if ( Gout )
2314             Gout[j] = Gintensity * temp;
2315         if ( Bout )
2316             Bout[j] = Bintensity * temp;
2317     }
2318
2319     return D3D_OK;
2320 }
2321
2322 FLOAT * WINAPI D3DXSHMultiply2(FLOAT *out, const FLOAT *a, const FLOAT *b)
2323 {
2324     FLOAT ta, tb;
2325
2326     TRACE("out %p, a %p, b %p\n", out, a, b);
2327
2328     ta = 0.28209479f * a[0];
2329     tb = 0.28209479f * b[0];
2330
2331     out[0] = 0.28209479f * D3DXSHDot(2, a, b);
2332     out[1] = ta * b[1] + tb * a[1];
2333     out[2] = ta * b[2] + tb * a[2];
2334     out[3] = ta * b[3] + tb * a[3];
2335
2336     return out;
2337 }
2338
2339 FLOAT * WINAPI D3DXSHMultiply3(FLOAT *out, const FLOAT *a, const FLOAT *b)
2340 {
2341     FLOAT t, ta, tb;
2342
2343     TRACE("out %p, a %p, b %p\n", out, a, b);
2344
2345     out[0] = 0.28209479f * a[0] * b[0];
2346
2347     ta = 0.28209479f * a[0] - 0.12615662f * a[6] - 0.21850968f * a[8];
2348     tb = 0.28209479f * b[0] - 0.12615662f * b[6] - 0.21850968f * b[8];
2349     out[1] = ta * b[1] + tb * a[1];
2350     t = a[1] * b[1];
2351     out[0] += 0.28209479f * t;
2352     out[6] = -0.12615662f * t;
2353     out[8] = -0.21850968f * t;
2354
2355     ta = 0.21850968f * a[5];
2356     tb = 0.21850968f * b[5];
2357     out[1] += ta * b[2] + tb * a[2];
2358     out[2] = ta * b[1] + tb * a[1];
2359     t = a[1] * b[2] +a[2] * b[1];
2360     out[5] = 0.21850968f * t;
2361
2362     ta = 0.21850968f * a[4];
2363     tb = 0.21850968f * b[4];
2364     out[1] += ta * b[3] + tb * a[3];
2365     out[3]  = ta * b[1] + tb * a[1];
2366     t = a[1] * b[3] + a[3] * b[1];
2367     out[4] = 0.21850968f * t;
2368
2369     ta = 0.28209480f * a[0] + 0.25231326f * a[6];
2370     tb = 0.28209480f * b[0] + 0.25231326f * b[6];
2371     out[2] += ta * b[2] + tb * a[2];
2372     t = a[2] * b[2];
2373     out[0] += 0.28209480f * t;
2374     out[6] += 0.25231326f * t;
2375
2376     ta = 0.21850969f * a[7];
2377     tb = 0.21850969f * b[7];
2378     out[2] += ta * b[3] + tb * a[3];
2379     out[3] += ta * b[2] + tb * a[2];
2380     t = a[2] * b[3] + a[3] * b[2];
2381     out[7] = 0.21850969f * t;
2382
2383     ta = 0.28209479f * a[0] - 0.12615663f * a[6] + 0.21850969f * a[8];
2384     tb = 0.28209479f * b[0] - 0.12615663f * b[6] + 0.21850969f * b[8];
2385     out[3] += ta * b[3] + tb * a[3];
2386     t = a[3] * b[3];
2387     out[0] += 0.28209479f * t;
2388     out[6] -= 0.12615663f * t;
2389     out[8] += 0.21850969f * t;
2390
2391     ta = 0.28209479f * a[0] - 0.18022375f * a[6];
2392     tb = 0.28209479f * b[0] - 0.18022375f * b[6];
2393     out[4] += ta * b[4] + tb * a[4];
2394     t = a[4] * b[4];
2395     out[0] += 0.28209479f * t;
2396     out[6] -= 0.18022375f * t;
2397
2398     ta = 0.15607835f * a[7];
2399     tb = 0.15607835f * b[7];
2400     out[4] += ta * b[5] + tb * a[5];
2401     out[5] += ta * b[4] + tb * a[4];
2402     t = a[4] * b[5] + a[5] * b[4];
2403     out[7] += 0.15607834f * t;
2404
2405     ta = 0.28209479f * a[0] + 0.09011186 * a[6] - 0.15607835f * a[8];
2406     tb = 0.28209479f * b[0] + 0.09011186 * b[6] - 0.15607835f * b[8];
2407     out[5] += ta * b[5] + tb * a[5];
2408     t = a[5] * b[5];
2409     out[0] += 0.28209479f * t;
2410     out[6] += 0.09011186f * t;
2411     out[8] -= 0.15607835f * t;
2412
2413     ta = 0.28209480f * a[0];
2414     tb = 0.28209480f * b[0];
2415     out[6] += ta * b[6] + tb * a[6];
2416     t = a[6] * b[6];
2417     out[0] += 0.28209480f * t;
2418     out[6] += 0.18022376f * t;
2419
2420     ta = 0.28209479f * a[0] + 0.09011186 * a[6] + 0.15607835f * a[8];
2421     tb = 0.28209479f * b[0] + 0.09011186 * b[6] + 0.15607835f * b[8];
2422     out[7] += ta * b[7] + tb * a[7];
2423     t = a[7] * b[7];
2424     out[0] += 0.28209479f * t;
2425     out[6] += 0.09011186f * t;
2426     out[8] += 0.15607835f * t;
2427
2428     ta = 0.28209479f * a[0] - 0.18022375f * a[6];
2429     tb = 0.28209479f * b[0] - 0.18022375f * b[6];
2430     out[8] += ta * b[8] + tb * a[8];
2431     t = a[8] * b[8];
2432     out[0] += 0.28209479f * t;
2433     out[6] -= 0.18022375f * t;
2434
2435     return out;
2436 }
2437
2438 FLOAT * WINAPI D3DXSHMultiply4(FLOAT *out, CONST FLOAT *a, CONST FLOAT *b)
2439 {
2440     FLOAT ta, tb, t;
2441
2442     TRACE("out %p, a %p, b %p\n", out, a, b);
2443
2444     out[0] = 0.28209479f * a[0] * b[0];
2445
2446     ta = 0.28209479f * a[0] - 0.12615663f * a[6] - 0.21850969f * a[8];
2447     tb = 0.28209479f * b[0] - 0.12615663f * b[6] - 0.21850969f * b[8];
2448     out[1] = ta * b[1] + tb * a[1];
2449     t = a[1] * b[1];
2450     out[0] += 0.28209479f * t;
2451     out[6] = -0.12615663f * t;
2452     out[8] = -0.21850969f * t;
2453
2454     ta = 0.21850969f * a[3] - 0.05839917f * a[13] - 0.22617901f * a[15];
2455     tb = 0.21850969f * b[3] - 0.05839917f * b[13] - 0.22617901f * b[15];
2456     out[1] += ta * b[4] + tb * a[4];
2457     out[4] = ta * b[1] + tb * a[1];
2458     t = a[1] * b[4] + a[4] * b[1];
2459     out[3] = 0.21850969f * t;
2460     out[13] = -0.05839917f * t;
2461     out[15] = -0.22617901f * t;
2462
2463     ta = 0.21850969f * a[2] - 0.14304817f * a[12] - 0.18467439f * a[14];
2464     tb = 0.21850969f * b[2] - 0.14304817f * b[12] - 0.18467439f * b[14];
2465     out[1] += ta * b[5] + tb * a[5];
2466     out[5] = ta * b[1] + tb * a[1];
2467     t = a[1] * b[5] + a[5] * b[1];
2468     out[2] = 0.21850969f * t;
2469     out[12] = -0.14304817f * t;
2470     out[14] = -0.18467439f * t;
2471
2472     ta = 0.20230066f * a[11];
2473     tb = 0.20230066f * b[11];
2474     out[1] += ta * b[6] + tb * a[6];
2475     out[6] += ta * b[1] + tb * a[1];
2476     t = a[1] * b[6] + a[6] * b[1];
2477     out[11] = 0.20230066f * t;
2478
2479     ta = 0.22617901f * a[9] + 0.05839917f * a[11];
2480     tb = 0.22617901f * b[9] + 0.05839917f * b[11];
2481     out[1] += ta * b[8] + tb * a[8];
2482     out[8] += ta * b[1] + tb * a[1];
2483     t = a[1] * b[8] + a[8] * b[1];
2484     out[9] = 0.22617901f * t;
2485     out[11] += 0.05839917f * t;
2486
2487     ta = 0.28209480f * a[0] + 0.25231326f * a[6];
2488     tb = 0.28209480f * b[0] + 0.25231326f * b[6];
2489     out[2] += ta * b[2] + tb * a[2];
2490     t = a[2] * b[2];
2491     out[0] += 0.28209480f * t;
2492     out[6] += 0.25231326f * t;
2493
2494     ta = 0.24776671f * a[12];
2495     tb = 0.24776671f * b[12];
2496     out[2] += ta * b[6] + tb * a[6];
2497     out[6] += ta * b[2] + tb * a[2];
2498     t = a[2] * b[6] + a[6] * b[2];
2499     out[12] += 0.24776671f * t;
2500
2501     ta = 0.28209480f * a[0] - 0.12615663f * a[6] + 0.21850969f * a[8];
2502     tb = 0.28209480f * b[0] - 0.12615663f * b[6] + 0.21850969f * b[8];
2503     out[3] += ta * b[3] + tb * a[3];
2504     t = a[3] * b[3];
2505     out[0] += 0.28209480f * t;
2506     out[6] -= 0.12615663f * t;
2507     out[8] += 0.21850969f * t;
2508
2509     ta = 0.20230066f * a[13];
2510     tb = 0.20230066f * b[13];
2511     out[3] += ta * b[6] + tb * a[6];
2512     out[6] += ta * b[3] + tb * a[3];
2513     t = a[3] * b[6] + a[6] * b[3];
2514     out[13] += 0.20230066f * t;
2515
2516     ta = 0.21850969f * a[2] - 0.14304817f * a[12] + 0.18467439f * a[14];
2517     tb = 0.21850969f * b[2] - 0.14304817f * b[12] + 0.18467439f * b[14];
2518     out[3] += ta * b[7] + tb * a[7];
2519     out[7] = ta * b[3] + tb * a[3];
2520     t = a[3] * b[7] + a[7] * b[3];
2521     out[2] += 0.21850969f * t;
2522     out[12] -= 0.14304817f * t;
2523     out[14] += 0.18467439f * t;
2524
2525     ta = -0.05839917f * a[13] + 0.22617901f * a[15];
2526     tb = -0.05839917f * b[13] + 0.22617901f * b[15];
2527     out[3] += ta * b[8] + tb * a[8];
2528     out[8] += ta * b[3] + tb * a[3];
2529     t = a[3] * b[8] + a[8] * b[3];
2530     out[13] -= 0.05839917f * t;
2531     out[15] += 0.22617901f * t;
2532
2533     ta = 0.28209479f * a[0] - 0.18022375f * a[6];
2534     tb = 0.28209479f * b[0] - 0.18022375f * b[6];
2535     out[4] += ta * b[4] + tb * a[4];
2536     t = a[4] * b[4];
2537     out[0] += 0.28209479f * t;
2538     out[6] -= 0.18022375f * t;
2539
2540     ta = 0.15607835f * a[7];
2541     tb = 0.15607835f * b[7];
2542     out[4] += ta * b[5] + tb * a[5];
2543     out[5] += ta * b[4] + tb * a[4];
2544     t = a[4] * b[5] + a[5] * b[4];
2545     out[7] += 0.15607835f * t;
2546
2547     ta = 0.22617901f * a[3] - 0.09403160f * a[13];
2548     tb = 0.22617901f * b[3] - 0.09403160f * b[13];
2549     out[4] += ta * b[9] + tb * a[9];
2550     out[9] += ta * b[4] + tb * a[4];
2551     t = a[4] * b[9] + a[9] * b[4];
2552     out[3] += 0.22617901f * t;
2553     out[13] -= 0.09403160f * t;
2554
2555     ta = 0.18467439f * a[2] - 0.18806319f * a[12];
2556     tb = 0.18467439f * b[2] - 0.18806319f * b[12];
2557     out[4] += ta * b[10] + tb * a [10];
2558     out[10] = ta * b[4] + tb * a[4];
2559     t = a[4] * b[10] + a[10] * b[4];
2560     out[2] += 0.18467439f * t;
2561     out[12] -= 0.18806319f * t;
2562
2563     ta = -0.05839917f * a[3] + 0.14567312f * a[13] + 0.09403160f * a[15];
2564     tb = -0.05839917f * b[3] + 0.14567312f * b[13] + 0.09403160f * b[15];
2565     out[4] += ta * b[11] + tb * a[11];
2566     out[11] += ta * b[4] + tb * a[4];
2567     t = a[4] * b[11] + a[11] * b[4];
2568     out[3] -= 0.05839917f * t;
2569     out[13] += 0.14567312f * t;
2570     out[15] += 0.09403160f * t;
2571
2572     ta = 0.28209479f * a[0] + 0.09011186f * a[6] - 0.15607835f * a[8];
2573     tb = 0.28209479f * b[0] + 0.09011186f * b[6] - 0.15607835f * b[8];
2574     out[5] += ta * b[5] + tb * a[5];
2575     t = a[5] * b[5];
2576     out[0] += 0.28209479f * t;
2577     out[6] += 0.09011186f * t;
2578     out[8] -= 0.15607835f * t;
2579
2580     ta = 0.14867701f * a[14];
2581     tb = 0.14867701f * b[14];
2582     out[5] += ta * b[9] + tb * a[9];
2583     out[9] += ta * b[5] + tb * a[5];
2584     t = a[5] * b[9] + a[9] * b[5];
2585     out[14] += 0.14867701f * t;
2586
2587     ta = 0.18467439f * a[3] + 0.11516472f * a[13] - 0.14867701f * a[15];
2588     tb = 0.18467439f * b[3] + 0.11516472f * b[13] - 0.14867701f * b[15];
2589     out[5] += ta * b[10] + tb * a[10];
2590     out[10] += ta * b[5] + tb * a[5];
2591     t = a[5] * b[10] + a[10] * b[5];
2592     out[3] += 0.18467439f * t;
2593     out[13] += 0.11516472f * t;
2594     out[15] -= 0.14867701f * t;
2595
2596     ta = 0.23359668f * a[2] + 0.05947080f * a[12] - 0.11516472f * a[14];
2597     tb = 0.23359668f * b[2] + 0.05947080f * b[12] - 0.11516472f * b[14];
2598     out[5] += ta * b[11] + tb * a[11];
2599     out[11] += ta * b[5] + tb * a[5];
2600     t = a[5] * b[11] + a[11] * b[5];
2601     out[2] += 0.23359668f * t;
2602     out[12] += 0.05947080f * t;
2603     out[14] -= 0.11516472f * t;
2604
2605     ta = 0.28209479f * a[0];
2606     tb = 0.28209479f * b[0];
2607     out[6] += ta * b[6] + tb * a[6];
2608     t = a[6] * b[6];
2609     out[0] += 0.28209479f * t;
2610     out[6] += 0.18022376f * t;
2611
2612     ta = 0.09011186f * a[6] + 0.28209479f * a[0] + 0.15607835f * a[8];
2613     tb = 0.09011186f * b[6] + 0.28209479f * b[0] + 0.15607835f * b[8];
2614     out[7] += ta * b[7] + tb * a[7];
2615     t = a[7] * b[7];
2616     out[6] += 0.09011186f * t;
2617     out[0] += 0.28209479f * t;
2618     out[8] += 0.15607835f * t;
2619
2620     ta = 0.14867701f * a[9] + 0.18467439f * a[1] + 0.11516472f * a[11];
2621     tb = 0.14867701f * b[9] + 0.18467439f * b[1] + 0.11516472f * b[11];
2622     out[7] += ta * b[10] + tb * a[10];
2623     out[10] += ta * b[7] + tb * a[7];
2624     t = a[7] * b[10] + a[10] * b[7];
2625     out[9] += 0.14867701f * t;
2626     out[1] += 0.18467439f * t;
2627     out[11] += 0.11516472f * t;
2628
2629     ta = 0.05947080f * a[12] + 0.23359668f * a[2] + 0.11516472f * a[14];
2630     tb = 0.05947080f * b[12] + 0.23359668f * b[2] + 0.11516472f * b[14];
2631     out[7] += ta * b[13] + tb * a[13];
2632     out[13] += ta * b[7]+ tb * a[7];
2633     t = a[7] * b[13] + a[13] * b[7];
2634     out[12] += 0.05947080f * t;
2635     out[2] += 0.23359668f * t;
2636     out[14] += 0.11516472f * t;
2637
2638     ta = 0.14867701f * a[15];
2639     tb = 0.14867701f * b[15];
2640     out[7] += ta * b[14] + tb * a[14];
2641     out[14] += ta * b[7] + tb * a[7];
2642     t = a[7] * b[14] + a[14] * b[7];
2643     out[15] += 0.14867701f * t;
2644
2645     ta = 0.28209479f * a[0] - 0.18022375f * a[6];
2646     tb = 0.28209479f * b[0] - 0.18022375f * b[6];
2647     out[8] += ta * b[8] + tb * a[8];
2648     t = a[8] * b[8];
2649     out[0] += 0.28209479f * t;
2650     out[6] -= 0.18022375f * t;
2651
2652     ta = -0.09403160f * a[11];
2653     tb = -0.09403160f * b[11];
2654     out[8] += ta * b[9] + tb * a[9];
2655     out[9] += ta * b[8] + tb * a[8];
2656     t = a[8] * b[9] + a[9] * b[8];
2657     out[11] -= 0.09403160f * t;
2658
2659     ta = -0.09403160f * a[15];
2660     tb = -0.09403160f * b[15];
2661     out[8] += ta * b[13] + tb * a[13];
2662     out[13] += ta * b[8] + tb * a[8];
2663     t = a[8] * b[13] + a[13] * b[8];
2664     out[15] -= 0.09403160f * t;
2665
2666     ta = 0.18467439f * a[2] - 0.18806319f * a[12];
2667     tb = 0.18467439f * b[2] - 0.18806319f * b[12];
2668     out[8] += ta * b[14] + tb * a[14];
2669     out[14] += ta * b[8] + tb * a[8];
2670     t = a[8] * b[14] + a[14] * b[8];
2671     out[2] += 0.18467439f * t;
2672     out[12] -= 0.18806319f * t;
2673
2674     ta = -0.21026104f * a[6] + 0.28209479f * a[0];
2675     tb = -0.21026104f * b[6] + 0.28209479f * b[0];
2676     out[9] += ta * b[9] + tb * a[9];
2677     t = a[9] * b[9];
2678     out[6] -= 0.21026104f * t;
2679     out[0] += 0.28209479f * t;
2680
2681     ta = 0.28209479f * a[0];
2682     tb = 0.28209479f * b[0];
2683     out[10] += ta * b[10] + tb * a[10];
2684     t = a[10] * b[10];
2685     out[0] += 0.28209479f * t;
2686
2687     ta = 0.28209479f * a[0] + 0.12615663f * a[6] - 0.14567312f * a[8];
2688     tb = 0.28209479f * b[0] + 0.12615663f * b[6] - 0.14567312f * b[8];
2689     out[11] += ta * b[11] + tb * a[11];
2690     t = a[11] * b[11];
2691     out[0] += 0.28209479f * t;
2692     out[6] += 0.12615663f * t;
2693     out[8] -= 0.14567312f * t;
2694
2695     ta = 0.28209479f * a[0] + 0.16820885f * a[6];
2696     tb = 0.28209479f * b[0] + 0.16820885f * b[6];
2697     out[12] += ta * b[12] + tb * a[12];
2698     t = a[12] * b[12];
2699     out[0] += 0.28209479f * t;
2700     out[6] += 0.16820885f * t;
2701
2702     ta =0.28209479f * a[0] + 0.14567312f * a[8] + 0.12615663f * a[6];
2703     tb =0.28209479f * b[0] + 0.14567312f * b[8] + 0.12615663f * b[6];
2704     out[13] += ta * b[13] + tb * a[13];
2705     t = a[13] * b[13];
2706     out[0] += 0.28209479f * t;
2707     out[8] += 0.14567312f * t;
2708     out[6] += 0.12615663f * t;
2709
2710     ta = 0.28209479f * a[0];
2711     tb = 0.28209479f * b[0];
2712     out[14] += ta * b[14] + tb * a[14];
2713     t = a[14] * b[14];
2714     out[0] += 0.28209479f * t;
2715
2716     ta = 0.28209479f * a[0] - 0.21026104f * a[6];
2717     tb = 0.28209479f * b[0] - 0.21026104f * b[6];
2718     out[15] += ta * b[15] + tb * a[15];
2719     t = a[15] * b[15];
2720     out[0] += 0.28209479f * t;
2721     out[6] -= 0.21026104f * t;
2722
2723     return out;
2724 }
2725
2726 static void rotate_X(FLOAT *out, UINT order, FLOAT a, FLOAT *in)
2727 {
2728     out[0] = in[0];
2729
2730     out[1] = a * in[2];
2731     out[2] = -a * in[1];
2732     out[3] = in[3];
2733
2734     out[4] = a * in[7];
2735     out[5] = -in[5];
2736     out[6] = -0.5f * in[6] - 0.8660253882f * in[8];
2737     out[7] = -a * in[4];
2738     out[8] = -0.8660253882f * in[6] + 0.5f * in[8];
2739     out[9] = -a * 0.7905694842f * in[12] + a * 0.6123724580f * in[14];
2740
2741     out[10] = -in[10];
2742     out[11] = -a * 0.6123724580f * in[12] - a * 0.7905694842f * in[14];
2743     out[12] = a * 0.7905694842f * in[9] + a * 0.6123724580f * in[11];
2744     out[13] = -0.25f * in[13] - 0.9682458639f * in[15];
2745     out[14] = -a * 0.6123724580f * in[9] + a * 0.7905694842f * in[11];
2746     out[15] = -0.9682458639f * in[13] + 0.25f * in[15];
2747     if (order == 4)
2748         return;
2749
2750     out[16] = -a * 0.9354143739f * in[21] + a * 0.3535533845f * in[23];
2751     out[17] = -0.75f * in[17] + 0.6614378095f * in[19];
2752     out[18] = -a * 0.3535533845f * in[21] - a * 0.9354143739f * in[23];
2753     out[19] = 0.6614378095f * in[17] + 0.75f * in[19];
2754     out[20] = 0.375f * in[20] + 0.5590170026f * in[22] + 0.7395099998f * in[24];
2755     out[21] = a * 0.9354143739f * in[16] + a * 0.3535533845f * in[18];
2756     out[22] = 0.5590170026f * in[20] + 0.5f * in[22] - 0.6614378691f * in[24];
2757     out[23] = -a * 0.3535533845f * in[16] + a * 0.9354143739f * in[18];
2758     out[24] = 0.7395099998f * in[20] - 0.6614378691f * in[22] + 0.125f * in[24];
2759     if (order == 5)
2760         return;
2761
2762     out[25] = a * 0.7015607357f * in[30] - a * 0.6846531630f * in[32] + a * 0.1976423711f * in[34];
2763     out[26] = -0.5f * in[26] + 0.8660253882f * in[28];
2764     out[27] = a * 0.5229125023f * in[30] + a * 0.3061861992f * in[32] - a * 0.7954951525 * in[34];
2765     out[28] = 0.8660253882f * in[26] + 0.5f * in[28];
2766     out[29] = a * 0.4841229022f * in[30] + a * 0.6614378691f * in[32] + a * 0.5728219748f * in[34];
2767     out[30] = -a * 0.7015607357f * in[25] - a * 0.5229125023f * in[27] - a * 0.4841229022f * in[29];
2768     out[31] = 0.125f * in[31] + 0.4050463140f * in[33] + 0.9057110548f * in[35];
2769     out[32] = a * 0.6846531630f * in[25] - a * 0.3061861992f * in[27] - a * 0.6614378691f * in[29];
2770     out[33] = 0.4050463140f * in[31] + 0.8125f * in[33] - 0.4192627370f * in[35];
2771     out[34] = -a * 0.1976423711f * in[25] + a * 0.7954951525f * in[27] - a * 0.5728219748f * in[29];
2772     out[35] = 0.9057110548f * in[31] - 0.4192627370f * in[33] + 0.0624999329f * in[35];
2773 }
2774
2775 FLOAT* WINAPI D3DXSHRotate(FLOAT *out, UINT order, CONST D3DXMATRIX *matrix, CONST FLOAT *in)
2776 {
2777     FLOAT alpha, beta, gamma, sinb, temp[36], temp1[36];
2778
2779     TRACE("out %p, order %u, matrix %p, in %p\n", out, order, matrix, in);
2780
2781     out[0] = in[0];
2782
2783     if ((order > D3DXSH_MAXORDER) || (order < D3DXSH_MINORDER))
2784         return out;
2785
2786     if (order <= 3)
2787     {
2788         out[1] = matrix->u.m[1][1] * in[1] - matrix->u.m[2][1] * in[2] + matrix->u.m[0][1] * in[3];
2789         out[2] = -matrix->u.m[1][2] * in[1] + matrix->u.m[2][2] * in[2] - matrix->u.m[0][2] * in[3];
2790         out[3] = matrix->u.m[1][0] * in[1] - matrix->u.m[2][0] * in[2] + matrix->u.m[0][0] * in[3];
2791
2792         if (order == 3)
2793         {
2794             FLOAT coeff[]={
2795                 matrix->u.m[1][0] * matrix->u.m[0][0], matrix->u.m[1][1] * matrix->u.m[0][1],
2796                 matrix->u.m[1][1] * matrix->u.m[2][1], matrix->u.m[1][0] * matrix->u.m[2][0],
2797                 matrix->u.m[2][0] * matrix->u.m[2][0], matrix->u.m[2][1] * matrix->u.m[2][1],
2798                 matrix->u.m[0][0] * matrix->u.m[2][0], matrix->u.m[0][1] * matrix->u.m[2][1],
2799                 matrix->u.m[0][1] * matrix->u.m[0][1], matrix->u.m[1][0] * matrix->u.m[1][0],
2800                 matrix->u.m[1][1] * matrix->u.m[1][1], matrix->u.m[0][0] * matrix->u.m[0][0], };
2801
2802             out[4] = (matrix->u.m[1][1] * matrix->u.m[0][0] + matrix->u.m[0][1] * matrix->u.m[1][0]) * in[4];
2803             out[4] -= (matrix->u.m[1][0] * matrix->u.m[2][1] + matrix->u.m[1][1] * matrix->u.m[2][0]) * in[5];
2804             out[4] += 1.7320508076f * matrix->u.m[2][0] * matrix->u.m[2][1] * in[6];
2805             out[4] -= (matrix->u.m[0][1] * matrix->u.m[2][0] + matrix->u.m[0][0] * matrix->u.m[2][1]) * in[7];
2806             out[4] += (matrix->u.m[0][0] * matrix->u.m[0][1] - matrix->u.m[1][0] * matrix->u.m[1][1]) * in[8];
2807
2808             out[5] = (matrix->u.m[1][1] * matrix->u.m[2][2] + matrix->u.m[1][2] * matrix->u.m[2][1]) * in[5];
2809             out[5] -= (matrix->u.m[1][1] * matrix->u.m[0][2] + matrix->u.m[1][2] * matrix->u.m[0][1]) * in[4];
2810             out[5] -= 1.7320508076f * matrix->u.m[2][2] * matrix->u.m[2][1] * in[6];
2811             out[5] += (matrix->u.m[0][2] * matrix->u.m[2][1] + matrix->u.m[0][1] * matrix->u.m[2][2]) * in[7];
2812             out[5] -= (matrix->u.m[0][1] * matrix->u.m[0][2] - matrix->u.m[1][1] * matrix->u.m[1][2]) * in[8];
2813
2814             out[6] = (matrix->u.m[2][2] * matrix->u.m[2][2] - 0.5f * (coeff[4] + coeff[5])) * in[6];
2815             out[6] -= (0.5773502692f * (coeff[0] + coeff[1]) - 1.1547005384f * matrix->u.m[1][2] * matrix->u.m[0][2]) * in[4];
2816             out[6] += (0.5773502692f * (coeff[2] + coeff[3]) - 1.1547005384f * matrix->u.m[1][2] * matrix->u.m[2][2]) * in[5];
2817             out[6] += (0.5773502692f * (coeff[6] + coeff[7]) - 1.1547005384f * matrix->u.m[0][2] * matrix->u.m[2][2]) * in[7];
2818             out[6] += (0.2886751347f * (coeff[9] - coeff[8] + coeff[10] - coeff[11]) - 0.5773502692f *
2819                   (matrix->u.m[1][2] * matrix->u.m[1][2] - matrix->u.m[0][2] * matrix->u.m[0][2])) * in[8];
2820
2821             out[7] = (matrix->u.m[0][0] * matrix->u.m[2][2] + matrix->u.m[0][2] * matrix->u.m[2][0]) * in[7];
2822             out[7] -= (matrix->u.m[1][0] * matrix->u.m[0][2] + matrix->u.m[1][2] * matrix->u.m[0][0]) * in[4];
2823             out[7] += (matrix->u.m[1][0] * matrix->u.m[2][2] + matrix->u.m[1][2] * matrix->u.m[2][0]) * in[5];
2824             out[7] -= 1.7320508076f * matrix->u.m[2][2] * matrix->u.m[2][0] * in[6];
2825             out[7] -= (matrix->u.m[0][0] * matrix->u.m[0][2] - matrix->u.m[1][0] * matrix->u.m[1][2]) * in[8];
2826
2827             out[8] = 0.5f * (coeff[11] - coeff[8] - coeff[9] + coeff[10]) * in[8];
2828             out[8] += (coeff[0] - coeff[1]) * in[4];
2829             out[8] += (coeff[2] - coeff[3]) * in[5];
2830             out[8] += 0.86602540f * (coeff[4] - coeff[5]) * in[6];
2831             out[8] += (coeff[7] - coeff[6]) * in[7];
2832         }
2833
2834         return out;
2835     }
2836
2837     if (fabsf(matrix->u.m[2][2]) != 1.0f)
2838     {
2839         sinb = sqrtf(1.0f - matrix->u.m[2][2] * matrix->u.m[2][2]);
2840         alpha = atan2f(matrix->u.m[2][1] / sinb, matrix->u.m[2][0] / sinb);
2841         beta = atan2f(sinb, matrix->u.m[2][2]);
2842         gamma = atan2f(matrix->u.m[1][2] / sinb, -matrix->u.m[0][2] / sinb);
2843     }
2844     else
2845     {
2846         alpha = atan2f(matrix->u.m[0][1], matrix->u.m[0][0]);
2847         beta = 0.0f;
2848         gamma = 0.0f;
2849     }
2850
2851     D3DXSHRotateZ(temp, order, gamma, in);
2852     rotate_X(temp1, order, 1.0f, temp);
2853     D3DXSHRotateZ(temp, order, beta, temp1);
2854     rotate_X(temp1, order, -1.0f, temp);
2855     D3DXSHRotateZ(out, order, alpha, temp1);
2856
2857     return out;
2858 }
2859
2860 FLOAT * WINAPI D3DXSHRotateZ(FLOAT *out, UINT order, FLOAT angle, const FLOAT *in)
2861 {
2862     UINT i, sum = 0;
2863     FLOAT c[5], s[5];
2864
2865     TRACE("out %p, order %u, angle %f, in %p\n", out, order, angle, in);
2866
2867     order = min(max(order, D3DXSH_MINORDER), D3DXSH_MAXORDER);
2868
2869     out[0] = in[0];
2870
2871     for (i = 1; i < order; i++)
2872     {
2873         UINT j;
2874
2875         c[i - 1] = cosf(i * angle);
2876         s[i - 1] = sinf(i * angle);
2877         sum += i * 2;
2878
2879         out[sum - i] = c[i - 1] * in[sum - i];
2880         out[sum - i] += s[i - 1] * in[sum + i];
2881         for (j = i - 1; j > 0; j--)
2882         {
2883             out[sum - j] = 0.0f;
2884             out[sum - j] = c[j - 1] * in[sum - j];
2885             out[sum - j] += s[j - 1] * in[sum + j];
2886         }
2887
2888         if (in == out)
2889             out[sum] = 0.0f;
2890         else
2891             out[sum] = in[sum];
2892
2893         for (j = 1; j < i; j++)
2894         {
2895             out[sum + j] = 0.0f;
2896             out[sum + j] = -s[j - 1] * in[sum - j];
2897             out[sum + j] += c[j - 1] * in[sum + j];
2898         }
2899         out[sum + i] = -s[i - 1] * in[sum - i];
2900         out[sum + i] += c[i - 1] * in[sum + i];
2901     }
2902
2903     return out;
2904 }
2905
2906 FLOAT* WINAPI D3DXSHScale(FLOAT *out, UINT order, CONST FLOAT *a, CONST FLOAT scale)
2907 {
2908     UINT i;
2909
2910     TRACE("out %p, order %u, a %p, scale %f\n", out, order, a, scale);
2911
2912     for (i = 0; i < order * order; i++)
2913         out[i] = a[i] * scale;
2914
2915     return out;
2916 }