push 8c61147e396035865ef2da2e6aa2d0f3b0907179
[wine/hacks.git] / dlls / d3dx9_36 / mesh.c
blob251bb40f9fc3d3284a610ac1df14632a4bbbeb70
1 /*
2 * Mesh operations specific to D3DX9.
4 * Copyright (C) 2009 David Adam
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
23 #include "wine/debug.h"
24 #include "windef.h"
25 #include "wingdi.h"
26 #include "d3dx9.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
30 /*************************************************************************
31 * D3DXBoxBoundProbe
33 BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *pmin, CONST D3DXVECTOR3 *pmax, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
35 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
36 Amy Williams University of Utah
37 Steve Barrus University of Utah
38 R. Keith Morley University of Utah
39 Peter Shirley University of Utah
41 International Conference on Computer Graphics and Interactive Techniques archive
42 ACM SIGGRAPH 2005 Courses
43 Los Angeles, California
45 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
47 Algorithm: Consider the box as the intersection of three slabs. Clip the ray
48 against each slab, if there's anything left of the ray after we're
49 done we've got an intersection of the ray with the box.
53 FLOAT div, tmin, tmax, tymin, tymax, tzmin, tzmax;
55 div = 1.0f / praydirection->x;
56 if ( div >= 0.0f )
58 tmin = ( pmin->x - prayposition->x ) * div;
59 tmax = ( pmax->x - prayposition->x ) * div;
61 else
63 tmin = ( pmax->x - prayposition->x ) * div;
64 tmax = ( pmin->x - prayposition->x ) * div;
67 if ( tmax < 0.0f ) return FALSE;
69 div = 1.0f / praydirection->y;
70 if ( div >= 0.0f )
72 tymin = ( pmin->y - prayposition->y ) * div;
73 tymax = ( pmax->y - prayposition->y ) * div;
75 else
77 tymin = ( pmax->y - prayposition->y ) * div;
78 tymax = ( pmin->y - prayposition->y ) * div;
81 if ( ( tymax < 0.0f ) || ( tmin > tymax ) || ( tymin > tmax ) ) return FALSE;
83 if ( tymin > tmin ) tmin = tymin;
84 if ( tymax < tmax ) tmax = tymax;
86 div = 1.0f / praydirection->z;
87 if ( div >= 0.0f )
89 tzmin = ( pmin->z - prayposition->z ) * div;
90 tzmax = ( pmax->z - prayposition->z ) * div;
92 else
94 tzmin = ( pmax->z - prayposition->z ) * div;
95 tzmax = ( pmin->z - prayposition->z ) * div;
98 if ( (tzmax < 0.0f ) || ( tmin > tzmax ) || ( tzmin > tmax ) ) return FALSE;
100 return TRUE;
103 /*************************************************************************
104 * D3DXComputeBoundingBox
106 HRESULT WINAPI D3DXComputeBoundingBox(CONST D3DXVECTOR3 *pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
108 D3DXVECTOR3 vec;
109 unsigned int i;
111 if( !pfirstposition || !pmin || !pmax ) return D3DERR_INVALIDCALL;
113 *pmin = *pfirstposition;
114 *pmax = *pmin;
116 for(i=0; i<numvertices; i++)
118 vec = *( (D3DXVECTOR3*)((char*)pfirstposition + dwstride * i) );
120 if ( vec.x < pmin->x ) pmin->x = vec.x;
121 if ( vec.x > pmax->x ) pmax->x = vec.x;
123 if ( vec.y < pmin->y ) pmin->y = vec.y;
124 if ( vec.y > pmax->y ) pmax->y = vec.y;
126 if ( vec.z < pmin->z ) pmin->z = vec.z;
127 if ( vec.z > pmax->z ) pmax->z = vec.z;
130 return D3D_OK;
133 /*************************************************************************
134 * D3DXComputeBoundingSphere
136 HRESULT WINAPI D3DXComputeBoundingSphere(CONST D3DXVECTOR3* pfirstposition, DWORD numvertices, DWORD dwstride, D3DXVECTOR3 *pcenter, FLOAT *pradius)
138 D3DXVECTOR3 temp, temp1;
139 FLOAT d;
140 unsigned int i;
142 if( !pfirstposition || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
144 temp.x = 0.0f;
145 temp.y = 0.0f;
146 temp.z = 0.0f;
147 temp1 = temp;
148 d = 0.0f;
149 *pradius = 0.0f;
151 for(i=0; i<numvertices; i++)
153 D3DXVec3Add(&temp1, &temp, (D3DXVECTOR3*)((char*)pfirstposition + dwstride * i));
154 temp = temp1;
157 D3DXVec3Scale(pcenter, &temp, 1.0f/((FLOAT)numvertices));
159 for(i=0; i<numvertices; i++)
161 d = D3DXVec3Length(D3DXVec3Subtract(&temp, (D3DXVECTOR3*)((char*)pfirstposition + dwstride * i), pcenter));
162 if ( d > *pradius ) *pradius = d;
164 return D3D_OK;
167 /*************************************************************************
168 * D3DXGetFVFVertexSize
170 static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
172 return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
175 UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
177 DWORD size = 0;
178 UINT i;
179 UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
181 if (FVF & D3DFVF_NORMAL) size += sizeof(D3DXVECTOR3);
182 if (FVF & D3DFVF_DIFFUSE) size += sizeof(DWORD);
183 if (FVF & D3DFVF_SPECULAR) size += sizeof(DWORD);
184 if (FVF & D3DFVF_PSIZE) size += sizeof(DWORD);
186 switch (FVF & D3DFVF_POSITION_MASK)
188 case D3DFVF_XYZ: size += sizeof(D3DXVECTOR3); break;
189 case D3DFVF_XYZRHW: size += 4 * sizeof(FLOAT); break;
190 case D3DFVF_XYZB1: size += 4 * sizeof(FLOAT); break;
191 case D3DFVF_XYZB2: size += 5 * sizeof(FLOAT); break;
192 case D3DFVF_XYZB3: size += 6 * sizeof(FLOAT); break;
193 case D3DFVF_XYZB4: size += 7 * sizeof(FLOAT); break;
194 case D3DFVF_XYZB5: size += 8 * sizeof(FLOAT); break;
195 case D3DFVF_XYZW: size += 4 * sizeof(FLOAT); break;
198 for (i = 0; i < numTextures; i++)
200 size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
203 return size;
206 /*************************************************************************
207 * D3DXGetDeclVertexSize
209 UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 *decl, DWORD stream_idx)
211 const D3DVERTEXELEMENT9 *element;
212 UINT size = 0;
214 TRACE("decl %p, stream_idx %u\n", decl, stream_idx);
216 if (!decl) return 0;
218 for (element = decl; element->Stream != 0xff; ++element)
220 UINT type_size;
222 if (element->Stream != stream_idx) continue;
224 switch (element->Type)
226 case D3DDECLTYPE_FLOAT1: type_size = 1 * 4; break;
227 case D3DDECLTYPE_FLOAT2: type_size = 2 * 4; break;
228 case D3DDECLTYPE_FLOAT3: type_size = 3 * 4; break;
229 case D3DDECLTYPE_FLOAT4: type_size = 4 * 4; break;
230 case D3DDECLTYPE_D3DCOLOR: type_size = 4 * 1; break;
231 case D3DDECLTYPE_UBYTE4: type_size = 4 * 1; break;
232 case D3DDECLTYPE_SHORT2: type_size = 2 * 2; break;
233 case D3DDECLTYPE_SHORT4: type_size = 4 * 2; break;
234 case D3DDECLTYPE_UBYTE4N: type_size = 4 * 1; break;
235 case D3DDECLTYPE_SHORT2N: type_size = 2 * 2; break;
236 case D3DDECLTYPE_SHORT4N: type_size = 4 * 2; break;
237 case D3DDECLTYPE_USHORT2N: type_size = 2 * 2; break;
238 case D3DDECLTYPE_USHORT4N: type_size = 4 * 2; break;
239 case D3DDECLTYPE_UDEC3: type_size = 4; break; /* 3 * 10 bits + 2 padding */
240 case D3DDECLTYPE_DEC3N: type_size = 4; break;
241 case D3DDECLTYPE_FLOAT16_2: type_size = 2 * 2; break;
242 case D3DDECLTYPE_FLOAT16_4: type_size = 4 * 2; break;
243 default:
244 FIXME("Unhandled element type %#x, size will be incorrect.\n", element->Type);
245 type_size = 0;
246 break;
249 if (element->Offset + type_size > size) size = element->Offset + type_size;
252 return size;
255 /*************************************************************************
256 * D3DXIntersectTri
258 BOOL WINAPI D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist)
260 D3DXMATRIX m;
261 D3DXVECTOR4 vec;
263 m.m[0][0] = p1->x - p0->x;
264 m.m[1][0] = p2->x - p0->x;
265 m.m[2][0] = -praydir->x;
266 m.m[3][0] = 0.0f;
267 m.m[0][1] = p1->y - p0->z;
268 m.m[1][1] = p2->y - p0->z;
269 m.m[2][1] = -praydir->y;
270 m.m[3][1] = 0.0f;
271 m.m[0][2] = p1->z - p0->z;
272 m.m[1][2] = p2->z - p0->z;
273 m.m[2][2] = -praydir->z;
274 m.m[3][2] = 0.0f;
275 m.m[0][3] = 0.0f;
276 m.m[1][3] = 0.0f;
277 m.m[2][3] = 0.0f;
278 m.m[3][3] = 1.0f;
280 vec.x = praypos->x - p0->x;
281 vec.y = praypos->y - p0->y;
282 vec.z = praypos->z - p0->z;
283 vec.w = 0.0f;
285 if ( D3DXMatrixInverse(&m, NULL, &m) )
287 D3DXVec4Transform(&vec, &vec, &m);
288 if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) )
290 *pu = vec.x;
291 *pv = vec.y;
292 *pdist = fabs( vec.z );
293 return TRUE;
297 return FALSE;
300 /*************************************************************************
301 * D3DXSphereBoundProbe
303 BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
305 D3DXVECTOR3 difference;
306 FLOAT a, b, c, d;
308 a = D3DXVec3LengthSq(praydirection);
309 if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE;
310 b = D3DXVec3Dot(&difference, praydirection);
311 c = D3DXVec3LengthSq(&difference) - radius * radius;
312 d = b * b - a * c;
314 if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE;
315 return TRUE;