d3dx9_36: Implement D3DXGetDeclLength with tests.
[wine] / dlls / d3dx9_36 / mesh.c
1  /*
2  * Mesh operations specific to D3DX9.
3  *
4  * Copyright (C) 2005 Henri Verbeet
5  * Copyright (C) 2006 Ivan Gyurdiev
6  * Copyright (C) 2009 David Adam
7  * Copyright (C) 2010 Tony Wasserka
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25 #include "wine/port.h"
26
27 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "wingdi.h"
30 #include "d3dx9.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
34
35 /*************************************************************************
36  * D3DXBoxBoundProbe
37  */
38 BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *pmin, CONST D3DXVECTOR3 *pmax, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
39
40 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
41 Amy Williams             University of Utah
42 Steve Barrus             University of Utah
43 R. Keith Morley          University of Utah
44 Peter Shirley            University of Utah
45
46 International Conference on Computer Graphics and Interactive Techniques  archive
47 ACM SIGGRAPH 2005 Courses
48 Los Angeles, California
49
50 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
51
52 Algorithm: Consider the box as the intersection of three slabs. Clip the ray
53 against each slab, if there's anything left of the ray after we're
54 done we've got an intersection of the ray with the box.
55 */
56
57 {
58     FLOAT div, tmin, tmax, tymin, tymax, tzmin, tzmax;
59
60     div = 1.0f / praydirection->x;
61     if ( div >= 0.0f )
62     {
63         tmin = ( pmin->x - prayposition->x ) * div;
64         tmax = ( pmax->x - prayposition->x ) * div;
65     }
66     else
67     {
68         tmin = ( pmax->x - prayposition->x ) * div;
69         tmax = ( pmin->x - prayposition->x ) * div;
70     }
71
72     if ( tmax < 0.0f ) return FALSE;
73
74     div = 1.0f / praydirection->y;
75     if ( div >= 0.0f )
76     {
77         tymin = ( pmin->y - prayposition->y ) * div;
78         tymax = ( pmax->y - prayposition->y ) * div;
79     }
80     else
81     {
82         tymin = ( pmax->y - prayposition->y ) * div;
83         tymax = ( pmin->y - prayposition->y ) * div;
84     }
85
86     if ( ( tymax < 0.0f ) || ( tmin > tymax ) || ( tymin > tmax ) ) return FALSE;
87
88     if ( tymin > tmin ) tmin = tymin;
89     if ( tymax < tmax ) tmax = tymax;
90
91     div = 1.0f / praydirection->z;
92     if ( div >= 0.0f )
93     {
94         tzmin = ( pmin->z - prayposition->z ) * div;
95         tzmax = ( pmax->z - prayposition->z ) * div;
96     }
97     else
98     {
99         tzmin = ( pmax->z - prayposition->z ) * div;
100         tzmax = ( pmin->z - prayposition->z ) * div;
101     }
102
103     if ( (tzmax < 0.0f ) || ( tmin > tzmax ) || ( tzmin > tmax ) ) return FALSE;
104
105     return TRUE;
106 }
107
108 /*************************************************************************
109  * D3DXComputeBoundingBox
110  */
111 HRESULT WINAPI D3DXComputeBoundingBox(CONST D3DXVECTOR3 *pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
112 {
113     D3DXVECTOR3 vec;
114     unsigned int i;
115
116     if( !pfirstposition || !pmin || !pmax ) return D3DERR_INVALIDCALL;
117
118     *pmin = *pfirstposition;
119     *pmax = *pmin;
120
121     for(i=0; i<numvertices; i++)
122     {
123         vec = *( (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i) );
124
125         if ( vec.x < pmin->x ) pmin->x = vec.x;
126         if ( vec.x > pmax->x ) pmax->x = vec.x;
127
128         if ( vec.y < pmin->y ) pmin->y = vec.y;
129         if ( vec.y > pmax->y ) pmax->y = vec.y;
130
131         if ( vec.z < pmin->z ) pmin->z = vec.z;
132         if ( vec.z > pmax->z ) pmax->z = vec.z;
133     }
134
135     return D3D_OK;
136 }
137
138 /*************************************************************************
139  * D3DXComputeBoundingSphere
140  */
141 HRESULT WINAPI D3DXComputeBoundingSphere(CONST D3DXVECTOR3* pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pcenter, FLOAT *pradius)
142 {
143     D3DXVECTOR3 temp, temp1;
144     FLOAT d;
145     unsigned int i;
146
147     if( !pfirstposition || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
148
149     temp.x = 0.0f;
150     temp.y = 0.0f;
151     temp.z = 0.0f;
152     temp1 = temp;
153     d = 0.0f;
154     *pradius = 0.0f;
155
156     for(i=0; i<numvertices; i++)
157     {
158         D3DXVec3Add(&temp1, &temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i));
159         temp = temp1;
160     }
161
162     D3DXVec3Scale(pcenter, &temp, 1.0f/((FLOAT)numvertices));
163
164     for(i=0; i<numvertices; i++)
165     {
166         d = D3DXVec3Length(D3DXVec3Subtract(&temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i), pcenter));
167         if ( d > *pradius ) *pradius = d;
168     }
169     return D3D_OK;
170 }
171
172 static const UINT d3dx_decltype_size[D3DDECLTYPE_UNUSED] =
173 {
174    /* D3DDECLTYPE_FLOAT1    */ 1 * 4,
175    /* D3DDECLTYPE_FLOAT2    */ 2 * 4,
176    /* D3DDECLTYPE_FLOAT3    */ 3 * 4,
177    /* D3DDECLTYPE_FLOAT4    */ 4 * 4,
178    /* D3DDECLTYPE_D3DCOLOR  */ 4 * 1,
179    /* D3DDECLTYPE_UBYTE4    */ 4 * 1,
180    /* D3DDECLTYPE_SHORT2    */ 2 * 2,
181    /* D3DDECLTYPE_SHORT4    */ 4 * 2,
182    /* D3DDECLTYPE_UBYTE4N   */ 4 * 1,
183    /* D3DDECLTYPE_SHORT2N   */ 2 * 2,
184    /* D3DDECLTYPE_SHORT4N   */ 4 * 2,
185    /* D3DDECLTYPE_USHORT2N  */ 2 * 2,
186    /* D3DDECLTYPE_USHORT4N  */ 4 * 2,
187    /* D3DDECLTYPE_UDEC3     */ 4, /* 3 * 10 bits + 2 padding */
188    /* D3DDECLTYPE_DEC3N     */ 4,
189    /* D3DDECLTYPE_FLOAT16_2 */ 2 * 2,
190    /* D3DDECLTYPE_FLOAT16_4 */ 4 * 2,
191 };
192
193 static void append_decl_element(D3DVERTEXELEMENT9 *declaration, UINT *idx, UINT *offset,
194         D3DDECLTYPE type, D3DDECLUSAGE usage, UINT usage_idx)
195 {
196     declaration[*idx].Stream = 0;
197     declaration[*idx].Offset = *offset;
198     declaration[*idx].Type = type;
199     declaration[*idx].Method = D3DDECLMETHOD_DEFAULT;
200     declaration[*idx].Usage = usage;
201     declaration[*idx].UsageIndex = usage_idx;
202
203     *offset += d3dx_decltype_size[type];
204     ++(*idx);
205 }
206
207 /*************************************************************************
208  * D3DXDeclaratorFromFVF
209  */
210 HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
211 {
212     static const D3DVERTEXELEMENT9 end_element = D3DDECL_END();
213     DWORD tex_count = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
214     unsigned int offset = 0;
215     unsigned int idx = 0;
216     unsigned int i;
217
218     TRACE("fvf %#x, declaration %p.\n", fvf, declaration);
219
220     if (fvf & D3DFVF_POSITION_MASK)
221     {
222         BOOL has_blend = (fvf & D3DFVF_XYZB5) >= D3DFVF_XYZB1;
223         DWORD blend_count = 1 + (((fvf & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
224         BOOL has_blend_idx = (fvf & D3DFVF_LASTBETA_D3DCOLOR) || (fvf & D3DFVF_LASTBETA_UBYTE4);
225
226         if (has_blend_idx) --blend_count;
227
228         if ((fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZW
229                 || (has_blend && blend_count > 4))
230             return D3DERR_INVALIDCALL;
231
232         if ((fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)
233             append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT4, D3DDECLUSAGE_POSITIONT, 0);
234         else
235             append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_POSITION, 0);
236
237         if (has_blend)
238         {
239             switch (blend_count)
240             {
241                  case 0:
242                     break;
243                  case 1:
244                     append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT1, D3DDECLUSAGE_BLENDWEIGHT, 0);
245                     break;
246                  case 2:
247                     append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT2, D3DDECLUSAGE_BLENDWEIGHT, 0);
248                     break;
249                  case 3:
250                     append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_BLENDWEIGHT, 0);
251                     break;
252                  case 4:
253                     append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT4, D3DDECLUSAGE_BLENDWEIGHT, 0);
254                     break;
255                  default:
256                      ERR("Invalid blend count %u.\n", blend_count);
257                      break;
258             }
259
260             if (has_blend_idx)
261             {
262                 if (fvf & D3DFVF_LASTBETA_UBYTE4)
263                     append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_UBYTE4, D3DDECLUSAGE_BLENDINDICES, 0);
264                 else if (fvf & D3DFVF_LASTBETA_D3DCOLOR)
265                     append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_BLENDINDICES, 0);
266             }
267         }
268     }
269
270     if (fvf & D3DFVF_NORMAL)
271         append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_NORMAL, 0);
272     if (fvf & D3DFVF_PSIZE)
273         append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT1, D3DDECLUSAGE_PSIZE, 0);
274     if (fvf & D3DFVF_DIFFUSE)
275         append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_COLOR, 0);
276     if (fvf & D3DFVF_SPECULAR)
277         append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_COLOR, 1);
278
279     for (i = 0; i < tex_count; ++i)
280     {
281         switch ((fvf >> (16 + 2 * i)) & 0x03)
282         {
283             case D3DFVF_TEXTUREFORMAT1:
284                 append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT1, D3DDECLUSAGE_TEXCOORD, i);
285                 break;
286             case D3DFVF_TEXTUREFORMAT2:
287                 append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT2, D3DDECLUSAGE_TEXCOORD, i);
288                 break;
289             case D3DFVF_TEXTUREFORMAT3:
290                 append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_TEXCOORD, i);
291                 break;
292             case D3DFVF_TEXTUREFORMAT4:
293                 append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT4, D3DDECLUSAGE_TEXCOORD, i);
294                 break;
295         }
296     }
297
298     declaration[idx] = end_element;
299
300     return D3D_OK;
301 }
302
303 /*************************************************************************
304  * D3DXFVFFromDeclarator
305  */
306 HRESULT WINAPI D3DXFVFFromDeclarator(const D3DVERTEXELEMENT9 *declaration, DWORD *fvf)
307 {
308     unsigned int i = 0, texture, offset;
309
310     TRACE("(%p, %p)\n", declaration, fvf);
311
312     *fvf = 0;
313     if (declaration[0].Type == D3DDECLTYPE_FLOAT3 && declaration[0].Usage == D3DDECLUSAGE_POSITION)
314     {
315         if ((declaration[1].Type == D3DDECLTYPE_FLOAT4 && declaration[1].Usage == D3DDECLUSAGE_BLENDWEIGHT &&
316              declaration[1].UsageIndex == 0) &&
317             (declaration[2].Type == D3DDECLTYPE_FLOAT1 && declaration[2].Usage == D3DDECLUSAGE_BLENDINDICES &&
318              declaration[2].UsageIndex == 0))
319         {
320             return D3DERR_INVALIDCALL;
321         }
322         else if ((declaration[1].Type == D3DDECLTYPE_UBYTE4 || declaration[1].Type == D3DDECLTYPE_D3DCOLOR) &&
323                  declaration[1].Usage == D3DDECLUSAGE_BLENDINDICES && declaration[1].UsageIndex == 0)
324         {
325             if (declaration[1].Type == D3DDECLTYPE_UBYTE4)
326             {
327                 *fvf |= D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4;
328             }
329             else
330             {
331                 *fvf |= D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR;
332             }
333             i = 2;
334         }
335         else if (declaration[1].Type <= D3DDECLTYPE_FLOAT4 && declaration[1].Usage == D3DDECLUSAGE_BLENDWEIGHT &&
336                  declaration[1].UsageIndex == 0)
337         {
338             if ((declaration[2].Type == D3DDECLTYPE_UBYTE4 || declaration[2].Type == D3DDECLTYPE_D3DCOLOR) &&
339                 declaration[2].Usage == D3DDECLUSAGE_BLENDINDICES && declaration[2].UsageIndex == 0)
340             {
341                 if (declaration[2].Type == D3DDECLTYPE_UBYTE4)
342                 {
343                     *fvf |= D3DFVF_LASTBETA_UBYTE4;
344                 }
345                 else
346                 {
347                     *fvf |= D3DFVF_LASTBETA_D3DCOLOR;
348                 }
349                 switch (declaration[1].Type)
350                 {
351                     case D3DDECLTYPE_FLOAT1: *fvf |= D3DFVF_XYZB2; break;
352                     case D3DDECLTYPE_FLOAT2: *fvf |= D3DFVF_XYZB3; break;
353                     case D3DDECLTYPE_FLOAT3: *fvf |= D3DFVF_XYZB4; break;
354                     case D3DDECLTYPE_FLOAT4: *fvf |= D3DFVF_XYZB5; break;
355                 }
356                 i = 3;
357             }
358             else
359             {
360                 switch (declaration[1].Type)
361                 {
362                     case D3DDECLTYPE_FLOAT1: *fvf |= D3DFVF_XYZB1; break;
363                     case D3DDECLTYPE_FLOAT2: *fvf |= D3DFVF_XYZB2; break;
364                     case D3DDECLTYPE_FLOAT3: *fvf |= D3DFVF_XYZB3; break;
365                     case D3DDECLTYPE_FLOAT4: *fvf |= D3DFVF_XYZB4; break;
366                 }
367                 i = 2;
368             }
369         }
370         else
371         {
372             *fvf |= D3DFVF_XYZ;
373             i = 1;
374         }
375     }
376     else if (declaration[0].Type == D3DDECLTYPE_FLOAT4 && declaration[0].Usage == D3DDECLUSAGE_POSITIONT &&
377              declaration[0].UsageIndex == 0)
378     {
379         *fvf |= D3DFVF_XYZRHW;
380         i = 1;
381     }
382
383     if (declaration[i].Type == D3DDECLTYPE_FLOAT3 && declaration[i].Usage == D3DDECLUSAGE_NORMAL)
384     {
385         *fvf |= D3DFVF_NORMAL;
386         i++;
387     }
388     if (declaration[i].Type == D3DDECLTYPE_FLOAT1 && declaration[i].Usage == D3DDECLUSAGE_PSIZE &&
389         declaration[i].UsageIndex == 0)
390     {
391         *fvf |= D3DFVF_PSIZE;
392         i++;
393     }
394     if (declaration[i].Type == D3DDECLTYPE_D3DCOLOR && declaration[i].Usage == D3DDECLUSAGE_COLOR &&
395         declaration[i].UsageIndex == 0)
396     {
397         *fvf |= D3DFVF_DIFFUSE;
398         i++;
399     }
400     if (declaration[i].Type == D3DDECLTYPE_D3DCOLOR && declaration[i].Usage == D3DDECLUSAGE_COLOR &&
401         declaration[i].UsageIndex == 1)
402     {
403         *fvf |= D3DFVF_SPECULAR;
404         i++;
405     }
406
407     for (texture = 0; texture < D3DDP_MAXTEXCOORD; i++, texture++)
408     {
409         if (declaration[i].Stream == 0xFF)
410         {
411             break;
412         }
413         else if (declaration[i].Type == D3DDECLTYPE_FLOAT1 && declaration[i].Usage == D3DDECLUSAGE_TEXCOORD &&
414                  declaration[i].UsageIndex == texture)
415         {
416             *fvf |= D3DFVF_TEXCOORDSIZE1(declaration[i].UsageIndex);
417         }
418         else if (declaration[i].Type == D3DDECLTYPE_FLOAT2 && declaration[i].Usage == D3DDECLUSAGE_TEXCOORD &&
419                  declaration[i].UsageIndex == texture)
420         {
421             *fvf |= D3DFVF_TEXCOORDSIZE2(declaration[i].UsageIndex);
422         }
423         else if (declaration[i].Type == D3DDECLTYPE_FLOAT3 && declaration[i].Usage == D3DDECLUSAGE_TEXCOORD &&
424                  declaration[i].UsageIndex == texture)
425         {
426             *fvf |= D3DFVF_TEXCOORDSIZE3(declaration[i].UsageIndex);
427         }
428         else if (declaration[i].Type == D3DDECLTYPE_FLOAT4 && declaration[i].Usage == D3DDECLUSAGE_TEXCOORD &&
429                  declaration[i].UsageIndex == texture)
430         {
431             *fvf |= D3DFVF_TEXCOORDSIZE4(declaration[i].UsageIndex);
432         }
433         else
434         {
435             return D3DERR_INVALIDCALL;
436         }
437     }
438
439     *fvf |= (texture << D3DFVF_TEXCOUNT_SHIFT);
440
441     for (offset = 0, i = 0; declaration[i].Stream != 0xFF;
442          offset += d3dx_decltype_size[declaration[i].Type], i++)
443     {
444         if (declaration[i].Offset != offset)
445         {
446             return D3DERR_INVALIDCALL;
447         }
448     }
449
450     return D3D_OK;
451 }
452
453 /*************************************************************************
454  * D3DXGetFVFVertexSize
455  */
456 static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
457 {
458     return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
459 }
460
461 UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
462 {
463     DWORD size = 0;
464     UINT i;
465     UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
466
467     if (FVF & D3DFVF_NORMAL) size += sizeof(D3DXVECTOR3);
468     if (FVF & D3DFVF_DIFFUSE) size += sizeof(DWORD);
469     if (FVF & D3DFVF_SPECULAR) size += sizeof(DWORD);
470     if (FVF & D3DFVF_PSIZE) size += sizeof(DWORD);
471
472     switch (FVF & D3DFVF_POSITION_MASK)
473     {
474         case D3DFVF_XYZ:    size += sizeof(D3DXVECTOR3); break;
475         case D3DFVF_XYZRHW: size += 4 * sizeof(FLOAT); break;
476         case D3DFVF_XYZB1:  size += 4 * sizeof(FLOAT); break;
477         case D3DFVF_XYZB2:  size += 5 * sizeof(FLOAT); break;
478         case D3DFVF_XYZB3:  size += 6 * sizeof(FLOAT); break;
479         case D3DFVF_XYZB4:  size += 7 * sizeof(FLOAT); break;
480         case D3DFVF_XYZB5:  size += 8 * sizeof(FLOAT); break;
481         case D3DFVF_XYZW:   size += 4 * sizeof(FLOAT); break;
482     }
483
484     for (i = 0; i < numTextures; i++)
485     {
486         size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
487     }
488
489     return size;
490 }
491
492 /*************************************************************************
493  * D3DXGetDeclVertexSize
494  */
495 UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx)
496 {
497     const D3DVERTEXELEMENT9 *element;
498     UINT size = 0;
499
500     TRACE("decl %p, stream_idx %u\n", decl, stream_idx);
501
502     if (!decl) return 0;
503
504     for (element = decl; element->Stream != 0xff; ++element)
505     {
506         UINT type_size;
507
508         if (element->Stream != stream_idx) continue;
509
510         if (element->Type >= sizeof(d3dx_decltype_size) / sizeof(*d3dx_decltype_size))
511         {
512             FIXME("Unhandled element type %#x, size will be incorrect.\n", element->Type);
513             continue;
514         }
515
516         type_size = d3dx_decltype_size[element->Type];
517         if (element->Offset + type_size > size) size = element->Offset + type_size;
518     }
519
520     return size;
521 }
522
523 /*************************************************************************
524  * D3DXGetDeclLength
525  */
526 UINT WINAPI D3DXGetDeclLength(const D3DVERTEXELEMENT9 *decl)
527 {
528     const D3DVERTEXELEMENT9 *element;
529
530     TRACE("decl %p\n", decl);
531
532     /* null decl results in exception on Windows XP */
533
534     for (element = decl; element->Stream != 0xff; ++element);
535
536     return element - decl;
537 }
538
539 /*************************************************************************
540  * D3DXIntersectTri
541  */
542 BOOL WINAPI D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist)
543 {
544     D3DXMATRIX m;
545     D3DXVECTOR4 vec;
546
547     m.u.m[0][0] = p1->x - p0->x;
548     m.u.m[1][0] = p2->x - p0->x;
549     m.u.m[2][0] = -praydir->x;
550     m.u.m[3][0] = 0.0f;
551     m.u.m[0][1] = p1->y - p0->z;
552     m.u.m[1][1] = p2->y - p0->z;
553     m.u.m[2][1] = -praydir->y;
554     m.u.m[3][1] = 0.0f;
555     m.u.m[0][2] = p1->z - p0->z;
556     m.u.m[1][2] = p2->z - p0->z;
557     m.u.m[2][2] = -praydir->z;
558     m.u.m[3][2] = 0.0f;
559     m.u.m[0][3] = 0.0f;
560     m.u.m[1][3] = 0.0f;
561     m.u.m[2][3] = 0.0f;
562     m.u.m[3][3] = 1.0f;
563
564     vec.x = praypos->x - p0->x;
565     vec.y = praypos->y - p0->y;
566     vec.z = praypos->z - p0->z;
567     vec.w = 0.0f;
568
569     if ( D3DXMatrixInverse(&m, NULL, &m) )
570     {
571         D3DXVec4Transform(&vec, &vec, &m);
572         if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) )
573         {
574             *pu = vec.x;
575             *pv = vec.y;
576             *pdist = fabs( vec.z );
577             return TRUE;
578         }
579     }
580
581     return FALSE;
582 }
583
584 /*************************************************************************
585  * D3DXSphereBoundProbe
586  */
587 BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
588 {
589     D3DXVECTOR3 difference;
590     FLOAT a, b, c, d;
591
592     a = D3DXVec3LengthSq(praydirection);
593     if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE;
594     b = D3DXVec3Dot(&difference, praydirection);
595     c = D3DXVec3LengthSq(&difference) - radius * radius;
596     d = b * b - a * c;
597
598     if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE;
599     return TRUE;
600 }
601
602 HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options, CONST D3DVERTEXELEMENT9 *declaration,
603                               LPDIRECT3DDEVICE9 device, LPD3DXMESH *mesh)
604 {
605     FIXME("(%d, %d, %d, %p, %p, %p): stub\n", numfaces, numvertices, options, declaration, device, mesh);
606
607     return E_NOTIMPL;
608 }
609
610 HRESULT WINAPI D3DXCreateBox(LPDIRECT3DDEVICE9 device, FLOAT width, FLOAT height,
611                              FLOAT depth, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
612 {
613     FIXME("(%p, %f, %f, %f, %p, %p): stub\n", device, width, height, depth, mesh, adjacency);
614
615     return E_NOTIMPL;
616 }
617
618 HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT slices,
619                                 UINT stacks, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
620 {
621     FIXME("(%p, %f, %d, %d, %p, %p): stub\n", device, radius, slices, stacks, mesh, adjacency);
622
623     return E_NOTIMPL;
624 }