windowscodecs: Handle TIFF's with RowsPerStrip greater than Height.
[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 /*************************************************************************
194  * D3DXDeclaratorFromFVF
195  */
196 HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE])
197 {
198     FIXME("(%d, %p): stub\n", fvf, Declaration);
199
200     return E_NOTIMPL;
201 }
202
203 /*************************************************************************
204  * D3DXFVFFromDeclarator
205  */
206 HRESULT WINAPI D3DXFVFFromDeclarator(const LPD3DVERTEXELEMENT9 *declaration, DWORD *fvf)
207 {
208     FIXME("(%p, %p): stub\n", declaration, fvf);
209
210     return E_NOTIMPL;
211 }
212
213 /*************************************************************************
214  * D3DXGetFVFVertexSize
215  */
216 static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
217 {
218     return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
219 }
220
221 UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
222 {
223     DWORD size = 0;
224     UINT i;
225     UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
226
227     if (FVF & D3DFVF_NORMAL) size += sizeof(D3DXVECTOR3);
228     if (FVF & D3DFVF_DIFFUSE) size += sizeof(DWORD);
229     if (FVF & D3DFVF_SPECULAR) size += sizeof(DWORD);
230     if (FVF & D3DFVF_PSIZE) size += sizeof(DWORD);
231
232     switch (FVF & D3DFVF_POSITION_MASK)
233     {
234         case D3DFVF_XYZ:    size += sizeof(D3DXVECTOR3); break;
235         case D3DFVF_XYZRHW: size += 4 * sizeof(FLOAT); break;
236         case D3DFVF_XYZB1:  size += 4 * sizeof(FLOAT); break;
237         case D3DFVF_XYZB2:  size += 5 * sizeof(FLOAT); break;
238         case D3DFVF_XYZB3:  size += 6 * sizeof(FLOAT); break;
239         case D3DFVF_XYZB4:  size += 7 * sizeof(FLOAT); break;
240         case D3DFVF_XYZB5:  size += 8 * sizeof(FLOAT); break;
241         case D3DFVF_XYZW:   size += 4 * sizeof(FLOAT); break;
242     }
243
244     for (i = 0; i < numTextures; i++)
245     {
246         size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
247     }
248
249     return size;
250 }
251
252 /*************************************************************************
253  * D3DXGetDeclVertexSize
254  */
255 UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx)
256 {
257     const D3DVERTEXELEMENT9 *element;
258     UINT size = 0;
259
260     TRACE("decl %p, stream_idx %u\n", decl, stream_idx);
261
262     if (!decl) return 0;
263
264     for (element = decl; element->Stream != 0xff; ++element)
265     {
266         UINT type_size;
267
268         if (element->Stream != stream_idx) continue;
269
270         if (element->Type >= sizeof(d3dx_decltype_size) / sizeof(*d3dx_decltype_size))
271         {
272             FIXME("Unhandled element type %#x, size will be incorrect.\n", element->Type);
273             continue;
274         }
275
276         type_size = d3dx_decltype_size[element->Type];
277         if (element->Offset + type_size > size) size = element->Offset + type_size;
278     }
279
280     return size;
281 }
282
283 /*************************************************************************
284  * D3DXIntersectTri
285  */
286 BOOL WINAPI D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist)
287 {
288     D3DXMATRIX m;
289     D3DXVECTOR4 vec;
290
291     m.u.m[0][0] = p1->x - p0->x;
292     m.u.m[1][0] = p2->x - p0->x;
293     m.u.m[2][0] = -praydir->x;
294     m.u.m[3][0] = 0.0f;
295     m.u.m[0][1] = p1->y - p0->z;
296     m.u.m[1][1] = p2->y - p0->z;
297     m.u.m[2][1] = -praydir->y;
298     m.u.m[3][1] = 0.0f;
299     m.u.m[0][2] = p1->z - p0->z;
300     m.u.m[1][2] = p2->z - p0->z;
301     m.u.m[2][2] = -praydir->z;
302     m.u.m[3][2] = 0.0f;
303     m.u.m[0][3] = 0.0f;
304     m.u.m[1][3] = 0.0f;
305     m.u.m[2][3] = 0.0f;
306     m.u.m[3][3] = 1.0f;
307
308     vec.x = praypos->x - p0->x;
309     vec.y = praypos->y - p0->y;
310     vec.z = praypos->z - p0->z;
311     vec.w = 0.0f;
312
313     if ( D3DXMatrixInverse(&m, NULL, &m) )
314     {
315         D3DXVec4Transform(&vec, &vec, &m);
316         if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) )
317         {
318             *pu = vec.x;
319             *pv = vec.y;
320             *pdist = fabs( vec.z );
321             return TRUE;
322         }
323     }
324
325     return FALSE;
326 }
327
328 /*************************************************************************
329  * D3DXSphereBoundProbe
330  */
331 BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
332 {
333     D3DXVECTOR3 difference;
334     FLOAT a, b, c, d;
335
336     a = D3DXVec3LengthSq(praydirection);
337     if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE;
338     b = D3DXVec3Dot(&difference, praydirection);
339     c = D3DXVec3LengthSq(&difference) - radius * radius;
340     d = b * b - a * c;
341
342     if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE;
343     return TRUE;
344 }
345
346 HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options, CONST LPD3DVERTEXELEMENT9 *declaration,
347                               LPDIRECT3DDEVICE9 device, LPD3DXMESH *mesh)
348 {
349     FIXME("(%d, %d, %d, %p, %p, %p): stub\n", numfaces, numvertices, options, declaration, device, mesh);
350
351     return E_NOTIMPL;
352 }
353
354 HRESULT WINAPI D3DXCreateBox(LPDIRECT3DDEVICE9 device, FLOAT width, FLOAT height,
355                              FLOAT depth, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
356 {
357     FIXME("(%p, %f, %f, %f, %p, %p): stub\n", device, width, height, depth, mesh, adjacency);
358
359     return E_NOTIMPL;
360 }
361
362 HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT slices,
363                                 UINT stacks, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
364 {
365     FIXME("(%p, %f, %d, %d, %p, %p): stub\n", device, radius, slices, stacks, mesh, adjacency);
366
367     return E_NOTIMPL;
368 }