shdoclc: Remove a space before an ellipsis in the Italian translation.
[wine/hramrach.git] / dlls / d3dx9_36 / mesh.c
blobed7f9a849e468e21585851da9224f7f7709f7456
1 /*
2 * Mesh operations specific to D3DX9.
4 * Copyright (C) 2005 Henri Verbeet
5 * Copyright (C) 2006 Ivan Gyurdiev
6 * Copyright (C) 2009 David Adam
7 * Copyright (C) 2010 Tony Wasserka
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.
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.
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
24 #include "config.h"
25 #include "wine/port.h"
27 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "wingdi.h"
30 #include "d3dx9.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
35 /*************************************************************************
36 * D3DXBoxBoundProbe
38 BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *pmin, CONST D3DXVECTOR3 *pmax, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
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
46 International Conference on Computer Graphics and Interactive Techniques archive
47 ACM SIGGRAPH 2005 Courses
48 Los Angeles, California
50 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
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.
58 FLOAT div, tmin, tmax, tymin, tymax, tzmin, tzmax;
60 div = 1.0f / praydirection->x;
61 if ( div >= 0.0f )
63 tmin = ( pmin->x - prayposition->x ) * div;
64 tmax = ( pmax->x - prayposition->x ) * div;
66 else
68 tmin = ( pmax->x - prayposition->x ) * div;
69 tmax = ( pmin->x - prayposition->x ) * div;
72 if ( tmax < 0.0f ) return FALSE;
74 div = 1.0f / praydirection->y;
75 if ( div >= 0.0f )
77 tymin = ( pmin->y - prayposition->y ) * div;
78 tymax = ( pmax->y - prayposition->y ) * div;
80 else
82 tymin = ( pmax->y - prayposition->y ) * div;
83 tymax = ( pmin->y - prayposition->y ) * div;
86 if ( ( tymax < 0.0f ) || ( tmin > tymax ) || ( tymin > tmax ) ) return FALSE;
88 if ( tymin > tmin ) tmin = tymin;
89 if ( tymax < tmax ) tmax = tymax;
91 div = 1.0f / praydirection->z;
92 if ( div >= 0.0f )
94 tzmin = ( pmin->z - prayposition->z ) * div;
95 tzmax = ( pmax->z - prayposition->z ) * div;
97 else
99 tzmin = ( pmax->z - prayposition->z ) * div;
100 tzmax = ( pmin->z - prayposition->z ) * div;
103 if ( (tzmax < 0.0f ) || ( tmin > tzmax ) || ( tzmin > tmax ) ) return FALSE;
105 return TRUE;
108 /*************************************************************************
109 * D3DXComputeBoundingBox
111 HRESULT WINAPI D3DXComputeBoundingBox(CONST D3DXVECTOR3 *pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
113 D3DXVECTOR3 vec;
114 unsigned int i;
116 if( !pfirstposition || !pmin || !pmax ) return D3DERR_INVALIDCALL;
118 *pmin = *pfirstposition;
119 *pmax = *pmin;
121 for(i=0; i<numvertices; i++)
123 vec = *( (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i) );
125 if ( vec.x < pmin->x ) pmin->x = vec.x;
126 if ( vec.x > pmax->x ) pmax->x = vec.x;
128 if ( vec.y < pmin->y ) pmin->y = vec.y;
129 if ( vec.y > pmax->y ) pmax->y = vec.y;
131 if ( vec.z < pmin->z ) pmin->z = vec.z;
132 if ( vec.z > pmax->z ) pmax->z = vec.z;
135 return D3D_OK;
138 /*************************************************************************
139 * D3DXComputeBoundingSphere
141 HRESULT WINAPI D3DXComputeBoundingSphere(CONST D3DXVECTOR3* pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pcenter, FLOAT *pradius)
143 D3DXVECTOR3 temp, temp1;
144 FLOAT d;
145 unsigned int i;
147 if( !pfirstposition || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
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;
156 for(i=0; i<numvertices; i++)
158 D3DXVec3Add(&temp1, &temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i));
159 temp = temp1;
162 D3DXVec3Scale(pcenter, &temp, 1.0f/((FLOAT)numvertices));
164 for(i=0; i<numvertices; i++)
166 d = D3DXVec3Length(D3DXVec3Subtract(&temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i), pcenter));
167 if ( d > *pradius ) *pradius = d;
169 return D3D_OK;
172 static const UINT d3dx_decltype_size[D3DDECLTYPE_UNUSED] =
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,
193 static void append_decl_element(D3DVERTEXELEMENT9 *declaration, UINT *idx, UINT *offset,
194 D3DDECLTYPE type, D3DDECLUSAGE usage, UINT usage_idx)
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;
203 *offset += d3dx_decltype_size[type];
204 ++(*idx);
207 /*************************************************************************
208 * D3DXDeclaratorFromFVF
210 HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
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;
218 TRACE("fvf %#x, declaration %p.\n", fvf, declaration);
220 if (fvf & D3DFVF_POSITION_MASK)
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);
226 if (has_blend_idx) --blend_count;
228 if ((fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZW
229 || (has_blend && blend_count > 4))
230 return D3DERR_INVALIDCALL;
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);
237 if (has_blend)
239 switch (blend_count)
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;
260 if (has_blend_idx)
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);
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);
279 for (i = 0; i < tex_count; ++i)
281 switch ((fvf >> (16 + 2 * i)) & 0x03)
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;
298 declaration[idx] = end_element;
300 return D3D_OK;
303 /*************************************************************************
304 * D3DXFVFFromDeclarator
306 HRESULT WINAPI D3DXFVFFromDeclarator(const D3DVERTEXELEMENT9 *declaration, DWORD *fvf)
308 FIXME("(%p, %p): stub\n", declaration, fvf);
310 return E_NOTIMPL;
313 /*************************************************************************
314 * D3DXGetFVFVertexSize
316 static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
318 return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
321 UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
323 DWORD size = 0;
324 UINT i;
325 UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
327 if (FVF & D3DFVF_NORMAL) size += sizeof(D3DXVECTOR3);
328 if (FVF & D3DFVF_DIFFUSE) size += sizeof(DWORD);
329 if (FVF & D3DFVF_SPECULAR) size += sizeof(DWORD);
330 if (FVF & D3DFVF_PSIZE) size += sizeof(DWORD);
332 switch (FVF & D3DFVF_POSITION_MASK)
334 case D3DFVF_XYZ: size += sizeof(D3DXVECTOR3); break;
335 case D3DFVF_XYZRHW: size += 4 * sizeof(FLOAT); break;
336 case D3DFVF_XYZB1: size += 4 * sizeof(FLOAT); break;
337 case D3DFVF_XYZB2: size += 5 * sizeof(FLOAT); break;
338 case D3DFVF_XYZB3: size += 6 * sizeof(FLOAT); break;
339 case D3DFVF_XYZB4: size += 7 * sizeof(FLOAT); break;
340 case D3DFVF_XYZB5: size += 8 * sizeof(FLOAT); break;
341 case D3DFVF_XYZW: size += 4 * sizeof(FLOAT); break;
344 for (i = 0; i < numTextures; i++)
346 size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
349 return size;
352 /*************************************************************************
353 * D3DXGetDeclVertexSize
355 UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx)
357 const D3DVERTEXELEMENT9 *element;
358 UINT size = 0;
360 TRACE("decl %p, stream_idx %u\n", decl, stream_idx);
362 if (!decl) return 0;
364 for (element = decl; element->Stream != 0xff; ++element)
366 UINT type_size;
368 if (element->Stream != stream_idx) continue;
370 if (element->Type >= sizeof(d3dx_decltype_size) / sizeof(*d3dx_decltype_size))
372 FIXME("Unhandled element type %#x, size will be incorrect.\n", element->Type);
373 continue;
376 type_size = d3dx_decltype_size[element->Type];
377 if (element->Offset + type_size > size) size = element->Offset + type_size;
380 return size;
383 /*************************************************************************
384 * D3DXIntersectTri
386 BOOL WINAPI D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist)
388 D3DXMATRIX m;
389 D3DXVECTOR4 vec;
391 m.u.m[0][0] = p1->x - p0->x;
392 m.u.m[1][0] = p2->x - p0->x;
393 m.u.m[2][0] = -praydir->x;
394 m.u.m[3][0] = 0.0f;
395 m.u.m[0][1] = p1->y - p0->z;
396 m.u.m[1][1] = p2->y - p0->z;
397 m.u.m[2][1] = -praydir->y;
398 m.u.m[3][1] = 0.0f;
399 m.u.m[0][2] = p1->z - p0->z;
400 m.u.m[1][2] = p2->z - p0->z;
401 m.u.m[2][2] = -praydir->z;
402 m.u.m[3][2] = 0.0f;
403 m.u.m[0][3] = 0.0f;
404 m.u.m[1][3] = 0.0f;
405 m.u.m[2][3] = 0.0f;
406 m.u.m[3][3] = 1.0f;
408 vec.x = praypos->x - p0->x;
409 vec.y = praypos->y - p0->y;
410 vec.z = praypos->z - p0->z;
411 vec.w = 0.0f;
413 if ( D3DXMatrixInverse(&m, NULL, &m) )
415 D3DXVec4Transform(&vec, &vec, &m);
416 if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) )
418 *pu = vec.x;
419 *pv = vec.y;
420 *pdist = fabs( vec.z );
421 return TRUE;
425 return FALSE;
428 /*************************************************************************
429 * D3DXSphereBoundProbe
431 BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
433 D3DXVECTOR3 difference;
434 FLOAT a, b, c, d;
436 a = D3DXVec3LengthSq(praydirection);
437 if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE;
438 b = D3DXVec3Dot(&difference, praydirection);
439 c = D3DXVec3LengthSq(&difference) - radius * radius;
440 d = b * b - a * c;
442 if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE;
443 return TRUE;
446 HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options, CONST LPD3DVERTEXELEMENT9 *declaration,
447 LPDIRECT3DDEVICE9 device, LPD3DXMESH *mesh)
449 FIXME("(%d, %d, %d, %p, %p, %p): stub\n", numfaces, numvertices, options, declaration, device, mesh);
451 return E_NOTIMPL;
454 HRESULT WINAPI D3DXCreateBox(LPDIRECT3DDEVICE9 device, FLOAT width, FLOAT height,
455 FLOAT depth, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
457 FIXME("(%p, %f, %f, %f, %p, %p): stub\n", device, width, height, depth, mesh, adjacency);
459 return E_NOTIMPL;
462 HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT slices,
463 UINT stacks, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
465 FIXME("(%p, %f, %d, %d, %p, %p): stub\n", device, radius, slices, stacks, mesh, adjacency);
467 return E_NOTIMPL;