ddraw: Allow the ddraw RGB device to be enumerated in IDirect3D3::FindDevice.
[wine] / dlls / d3dx9_36 / mesh.c
1  /*
2  * Mesh operations specific to D3DX9.
3  *
4  * Copyright (C) 2009 David Adam
5  * Copyright (C) 2010 Tony Wasserka
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "wingdi.h"
28 #include "d3dx9.h"
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
32
33 /*************************************************************************
34  * D3DXBoxBoundProbe
35  */
36 BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *pmin, CONST D3DXVECTOR3 *pmax, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
37
38 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
39 Amy Williams             University of Utah
40 Steve Barrus             University of Utah
41 R. Keith Morley          University of Utah
42 Peter Shirley            University of Utah
43
44 International Conference on Computer Graphics and Interactive Techniques  archive
45 ACM SIGGRAPH 2005 Courses
46 Los Angeles, California
47
48 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
49
50 Algorithm: Consider the box as the intersection of three slabs. Clip the ray
51 against each slab, if there's anything left of the ray after we're
52 done we've got an intersection of the ray with the box.
53 */
54
55 {
56     FLOAT div, tmin, tmax, tymin, tymax, tzmin, tzmax;
57
58     div = 1.0f / praydirection->x;
59     if ( div >= 0.0f )
60     {
61         tmin = ( pmin->x - prayposition->x ) * div;
62         tmax = ( pmax->x - prayposition->x ) * div;
63     }
64     else
65     {
66         tmin = ( pmax->x - prayposition->x ) * div;
67         tmax = ( pmin->x - prayposition->x ) * div;
68     }
69
70     if ( tmax < 0.0f ) return FALSE;
71
72     div = 1.0f / praydirection->y;
73     if ( div >= 0.0f )
74     {
75         tymin = ( pmin->y - prayposition->y ) * div;
76         tymax = ( pmax->y - prayposition->y ) * div;
77     }
78     else
79     {
80         tymin = ( pmax->y - prayposition->y ) * div;
81         tymax = ( pmin->y - prayposition->y ) * div;
82     }
83
84     if ( ( tymax < 0.0f ) || ( tmin > tymax ) || ( tymin > tmax ) ) return FALSE;
85
86     if ( tymin > tmin ) tmin = tymin;
87     if ( tymax < tmax ) tmax = tymax;
88
89     div = 1.0f / praydirection->z;
90     if ( div >= 0.0f )
91     {
92         tzmin = ( pmin->z - prayposition->z ) * div;
93         tzmax = ( pmax->z - prayposition->z ) * div;
94     }
95     else
96     {
97         tzmin = ( pmax->z - prayposition->z ) * div;
98         tzmax = ( pmin->z - prayposition->z ) * div;
99     }
100
101     if ( (tzmax < 0.0f ) || ( tmin > tzmax ) || ( tzmin > tmax ) ) return FALSE;
102
103     return TRUE;
104 }
105
106 /*************************************************************************
107  * D3DXComputeBoundingBox
108  */
109 HRESULT WINAPI D3DXComputeBoundingBox(CONST D3DXVECTOR3 *pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
110 {
111     D3DXVECTOR3 vec;
112     unsigned int i;
113
114     if( !pfirstposition || !pmin || !pmax ) return D3DERR_INVALIDCALL;
115
116     *pmin = *pfirstposition;
117     *pmax = *pmin;
118
119     for(i=0; i<numvertices; i++)
120     {
121         vec = *( (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i) );
122
123         if ( vec.x < pmin->x ) pmin->x = vec.x;
124         if ( vec.x > pmax->x ) pmax->x = vec.x;
125
126         if ( vec.y < pmin->y ) pmin->y = vec.y;
127         if ( vec.y > pmax->y ) pmax->y = vec.y;
128
129         if ( vec.z < pmin->z ) pmin->z = vec.z;
130         if ( vec.z > pmax->z ) pmax->z = vec.z;
131     }
132
133     return D3D_OK;
134 }
135
136 /*************************************************************************
137  * D3DXComputeBoundingSphere
138  */
139 HRESULT WINAPI D3DXComputeBoundingSphere(CONST D3DXVECTOR3* pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pcenter, FLOAT *pradius)
140 {
141     D3DXVECTOR3 temp, temp1;
142     FLOAT d;
143     unsigned int i;
144
145     if( !pfirstposition || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
146
147     temp.x = 0.0f;
148     temp.y = 0.0f;
149     temp.z = 0.0f;
150     temp1 = temp;
151     d = 0.0f;
152     *pradius = 0.0f;
153
154     for(i=0; i<numvertices; i++)
155     {
156         D3DXVec3Add(&temp1, &temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i));
157         temp = temp1;
158     }
159
160     D3DXVec3Scale(pcenter, &temp, 1.0f/((FLOAT)numvertices));
161
162     for(i=0; i<numvertices; i++)
163     {
164         d = D3DXVec3Length(D3DXVec3Subtract(&temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i), pcenter));
165         if ( d > *pradius ) *pradius = d;
166     }
167     return D3D_OK;
168 }
169
170 /*************************************************************************
171  * D3DXDeclaratorFromFVF
172  */
173 HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE])
174 {
175     FIXME("(%d, %p): stub\n", fvf, Declaration);
176
177     return E_NOTIMPL;
178 }
179
180 /*************************************************************************
181  * D3DXGetFVFVertexSize
182  */
183 static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
184 {
185     return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
186 }
187
188 UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
189 {
190     DWORD size = 0;
191     UINT i;
192     UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
193
194     if (FVF & D3DFVF_NORMAL) size += sizeof(D3DXVECTOR3);
195     if (FVF & D3DFVF_DIFFUSE) size += sizeof(DWORD);
196     if (FVF & D3DFVF_SPECULAR) size += sizeof(DWORD);
197     if (FVF & D3DFVF_PSIZE) size += sizeof(DWORD);
198
199     switch (FVF & D3DFVF_POSITION_MASK)
200     {
201         case D3DFVF_XYZ:    size += sizeof(D3DXVECTOR3); break;
202         case D3DFVF_XYZRHW: size += 4 * sizeof(FLOAT); break;
203         case D3DFVF_XYZB1:  size += 4 * sizeof(FLOAT); break;
204         case D3DFVF_XYZB2:  size += 5 * sizeof(FLOAT); break;
205         case D3DFVF_XYZB3:  size += 6 * sizeof(FLOAT); break;
206         case D3DFVF_XYZB4:  size += 7 * sizeof(FLOAT); break;
207         case D3DFVF_XYZB5:  size += 8 * sizeof(FLOAT); break;
208         case D3DFVF_XYZW:   size += 4 * sizeof(FLOAT); break;
209     }
210
211     for (i = 0; i < numTextures; i++)
212     {
213         size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
214     }
215
216     return size;
217 }
218
219 /*************************************************************************
220  * D3DXGetDeclVertexSize
221  */
222 UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx)
223 {
224     const D3DVERTEXELEMENT9 *element;
225     UINT size = 0;
226
227     TRACE("decl %p, stream_idx %u\n", decl, stream_idx);
228
229     if (!decl) return 0;
230
231     for (element = decl; element->Stream != 0xff; ++element)
232     {
233         UINT type_size;
234
235         if (element->Stream != stream_idx) continue;
236
237         switch (element->Type)
238         {
239             case D3DDECLTYPE_FLOAT1: type_size = 1 * 4; break;
240             case D3DDECLTYPE_FLOAT2: type_size = 2 * 4; break;
241             case D3DDECLTYPE_FLOAT3: type_size = 3 * 4; break;
242             case D3DDECLTYPE_FLOAT4: type_size = 4 * 4; break;
243             case D3DDECLTYPE_D3DCOLOR: type_size = 4 * 1; break;
244             case D3DDECLTYPE_UBYTE4: type_size = 4 * 1; break;
245             case D3DDECLTYPE_SHORT2: type_size = 2 * 2; break;
246             case D3DDECLTYPE_SHORT4: type_size = 4 * 2; break;
247             case D3DDECLTYPE_UBYTE4N: type_size = 4 * 1; break;
248             case D3DDECLTYPE_SHORT2N: type_size = 2 * 2; break;
249             case D3DDECLTYPE_SHORT4N: type_size = 4 * 2; break;
250             case D3DDECLTYPE_USHORT2N: type_size = 2 * 2; break;
251             case D3DDECLTYPE_USHORT4N: type_size = 4 * 2; break;
252             case D3DDECLTYPE_UDEC3: type_size = 4; break; /* 3 * 10 bits + 2 padding */
253             case D3DDECLTYPE_DEC3N: type_size = 4; break;
254             case D3DDECLTYPE_FLOAT16_2: type_size = 2 * 2; break;
255             case D3DDECLTYPE_FLOAT16_4: type_size = 4 * 2; break;
256             default:
257                 FIXME("Unhandled element type %#x, size will be incorrect.\n", element->Type);
258                 type_size = 0;
259                 break;
260         }
261
262         if (element->Offset + type_size > size) size = element->Offset + type_size;
263     }
264
265     return size;
266 }
267
268 /*************************************************************************
269  * D3DXIntersectTri
270  */
271 BOOL WINAPI D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist)
272 {
273     D3DXMATRIX m;
274     D3DXVECTOR4 vec;
275
276     m.u.m[0][0] = p1->x - p0->x;
277     m.u.m[1][0] = p2->x - p0->x;
278     m.u.m[2][0] = -praydir->x;
279     m.u.m[3][0] = 0.0f;
280     m.u.m[0][1] = p1->y - p0->z;
281     m.u.m[1][1] = p2->y - p0->z;
282     m.u.m[2][1] = -praydir->y;
283     m.u.m[3][1] = 0.0f;
284     m.u.m[0][2] = p1->z - p0->z;
285     m.u.m[1][2] = p2->z - p0->z;
286     m.u.m[2][2] = -praydir->z;
287     m.u.m[3][2] = 0.0f;
288     m.u.m[0][3] = 0.0f;
289     m.u.m[1][3] = 0.0f;
290     m.u.m[2][3] = 0.0f;
291     m.u.m[3][3] = 1.0f;
292
293     vec.x = praypos->x - p0->x;
294     vec.y = praypos->y - p0->y;
295     vec.z = praypos->z - p0->z;
296     vec.w = 0.0f;
297
298     if ( D3DXMatrixInverse(&m, NULL, &m) )
299     {
300         D3DXVec4Transform(&vec, &vec, &m);
301         if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) )
302         {
303             *pu = vec.x;
304             *pv = vec.y;
305             *pdist = fabs( vec.z );
306             return TRUE;
307         }
308     }
309
310     return FALSE;
311 }
312
313 /*************************************************************************
314  * D3DXSphereBoundProbe
315  */
316 BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
317 {
318     D3DXVECTOR3 difference;
319     FLOAT a, b, c, d;
320
321     a = D3DXVec3LengthSq(praydirection);
322     if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE;
323     b = D3DXVec3Dot(&difference, praydirection);
324     c = D3DXVec3LengthSq(&difference) - radius * radius;
325     d = b * b - a * c;
326
327     if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE;
328     return TRUE;
329 }
330
331 HRESULT WINAPI D3DXCreateBox(LPDIRECT3DDEVICE9 device, FLOAT width, FLOAT height,
332                              FLOAT depth, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
333 {
334     FIXME("(%p, %f, %f, %f, %p, %p): stub\n", device, width, height, depth, mesh, adjacency);
335
336     return E_NOTIMPL;
337 }