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
25 #include "wine/port.h"
27 #define NONAMELESSUNION
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
35 /*************************************************************************
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;
63 tmin = ( pmin->x - prayposition->x ) * div;
64 tmax = ( pmax->x - prayposition->x ) * div;
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;
77 tymin = ( pmin->y - prayposition->y ) * div;
78 tymax = ( pmax->y - prayposition->y ) * div;
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;
94 tzmin = ( pmin->z - prayposition->z ) * div;
95 tzmax = ( pmax->z - prayposition->z ) * div;
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;
108 /*************************************************************************
109 * D3DXComputeBoundingBox
111 HRESULT WINAPI D3DXComputeBoundingBox(CONST D3DXVECTOR3 *pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
116 if( !pfirstposition || !pmin || !pmax ) return D3DERR_INVALIDCALL;
118 *pmin = *pfirstposition;
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;
138 /*************************************************************************
139 * D3DXComputeBoundingSphere
141 HRESULT WINAPI D3DXComputeBoundingSphere(CONST D3DXVECTOR3* pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pcenter, FLOAT *pradius)
143 D3DXVECTOR3 temp, temp1;
147 if( !pfirstposition || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
156 for(i=0; i<numvertices; i++)
158 D3DXVec3Add(&temp1, &temp, (const D3DXVECTOR3*)((const char*)pfirstposition + dwstride * i));
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;
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 /*************************************************************************
194 * D3DXDeclaratorFromFVF
196 HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE])
198 FIXME("(%d, %p): stub\n", fvf, Declaration);
203 /*************************************************************************
204 * D3DXFVFFromDeclarator
206 HRESULT WINAPI D3DXFVFFromDeclarator(const LPD3DVERTEXELEMENT9 *declaration, DWORD *fvf)
208 FIXME("(%p, %p): stub\n", declaration, fvf);
213 /*************************************************************************
214 * D3DXGetFVFVertexSize
216 static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
218 return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
221 UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
225 UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
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);
232 switch (FVF & D3DFVF_POSITION_MASK)
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;
244 for (i = 0; i < numTextures; i++)
246 size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
252 /*************************************************************************
253 * D3DXGetDeclVertexSize
255 UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx)
257 const D3DVERTEXELEMENT9 *element;
260 TRACE("decl %p, stream_idx %u\n", decl, stream_idx);
264 for (element = decl; element->Stream != 0xff; ++element)
268 if (element->Stream != stream_idx) continue;
270 if (element->Type >= sizeof(d3dx_decltype_size) / sizeof(*d3dx_decltype_size))
272 FIXME("Unhandled element type %#x, size will be incorrect.\n", element->Type);
276 type_size = d3dx_decltype_size[element->Type];
277 if (element->Offset + type_size > size) size = element->Offset + type_size;
283 /*************************************************************************
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)
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;
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;
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;
308 vec.x = praypos->x - p0->x;
309 vec.y = praypos->y - p0->y;
310 vec.z = praypos->z - p0->z;
313 if ( D3DXMatrixInverse(&m, NULL, &m) )
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) )
320 *pdist = fabs( vec.z );
328 /*************************************************************************
329 * D3DXSphereBoundProbe
331 BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
333 D3DXVECTOR3 difference;
336 a = D3DXVec3LengthSq(praydirection);
337 if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE;
338 b = D3DXVec3Dot(&difference, praydirection);
339 c = D3DXVec3LengthSq(&difference) - radius * radius;
342 if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE;
346 HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options, CONST LPD3DVERTEXELEMENT9 *declaration,
347 LPDIRECT3DDEVICE9 device, LPD3DXMESH *mesh)
349 FIXME("(%d, %d, %d, %p, %p, %p): stub\n", numfaces, numvertices, options, declaration, device, mesh);
354 HRESULT WINAPI D3DXCreateBox(LPDIRECT3DDEVICE9 device, FLOAT width, FLOAT height,
355 FLOAT depth, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
357 FIXME("(%p, %f, %f, %f, %p, %p): stub\n", device, width, height, depth, mesh, adjacency);
362 HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT slices,
363 UINT stacks, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
365 FIXME("(%p, %f, %d, %d, %p, %p): stub\n", device, radius, slices, stacks, mesh, adjacency);