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