push c1253c88909f2734609a5c511eb3b22fe94693d1
[wine/hacks.git] / dlls / d3dx8 / mesh.c
blobbaa5f2010f84fa69a100bd75def8d2b4edeaeff8
1 /*
2 * Copyright 2008 David Adam
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "wingdi.h"
24 #include "wine/debug.h"
26 #include "d3dx8_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
30 BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *pmin, CONST D3DXVECTOR3 *pmax, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
32 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
33 Amy Williams University of Utah
34 Steve Barrus University of Utah
35 R. Keith Morley University of Utah
36 Peter Shirley University of Utah
38 International Conference on Computer Graphics and Interactive Techniques archive
39 ACM SIGGRAPH 2005 Courses
40 Los Angeles, California
42 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
44 Algorithm: Consider the box as the intersection of three slabs. Clip the ray
45 against each slab, if there's anything left of the ray after we're
46 done we've got an intersection of the ray with the box.
50 FLOAT div, tmin, tmax, tymin, tymax, tzmin, tzmax;
52 div = 1.0f / praydirection->x;
53 if ( div >= 0.0f )
55 tmin = ( pmin->x - prayposition->x ) * div;
56 tmax = ( pmax->x - prayposition->x ) * div;
58 else
60 tmin = ( pmax->x - prayposition->x ) * div;
61 tmax = ( pmin->x - prayposition->x ) * div;
64 if ( tmax < 0.0f ) return FALSE;
66 div = 1.0f / praydirection->y;
67 if ( div >= 0.0f )
69 tymin = ( pmin->y - prayposition->y ) * div;
70 tymax = ( pmax->y - prayposition->y ) * div;
72 else
74 tymin = ( pmax->y - prayposition->y ) * div;
75 tymax = ( pmin->y - prayposition->y ) * div;
78 if ( ( tymax < 0.0f ) || ( tmin > tymax ) || ( tymin > tmax ) ) return FALSE;
80 if ( tymin > tmin ) tmin = tymin;
81 if ( tymax < tmax ) tmax = tymax;
83 div = 1.0f / praydirection->z;
84 if ( div >= 0.0f )
86 tzmin = ( pmin->z - prayposition->z ) * div;
87 tzmax = ( pmax->z - prayposition->z ) * div;
89 else
91 tzmin = ( pmax->z - prayposition->z ) * div;
92 tzmax = ( pmin->z - prayposition->z ) * div;
95 if ( (tzmax < 0.0f ) || ( tmin > tzmax ) || ( tzmin > tmax ) ) return FALSE;
97 return TRUE;
100 HRESULT WINAPI D3DXComputeBoundingBox(PVOID ppointsFVF, DWORD numvertices, DWORD FVF, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
102 D3DXVECTOR3 vec;
103 unsigned int i;
105 if( !ppointsFVF || !pmin || !pmax ) return D3DERR_INVALIDCALL;
107 *pmin = *(D3DXVECTOR3*)((char*)ppointsFVF);
108 *pmax = *pmin;
110 /* It looks like that D3DXComputeBoundingBox does not take in account the last vertex. */
111 for(i=0; i<numvertices-1; i++)
113 vec = *(D3DXVECTOR3*)((char*)ppointsFVF + D3DXGetFVFVertexSize(FVF) * i);
115 if ( vec.x < pmin->x ) pmin->x = vec.x;
116 if ( vec.x > pmax->x ) pmax->x = vec.x;
118 if ( vec.y < pmin->y ) pmin->y = vec.y;
119 if ( vec.y > pmax->y ) pmax->y = vec.y;
121 if ( vec.z < pmin->z ) pmin->z = vec.z;
122 if ( vec.z > pmax->z ) pmax->z = vec.z;
125 return D3D_OK;
128 HRESULT WINAPI D3DXComputeBoundingSphere(PVOID ppointsFVF, DWORD numvertices, DWORD FVF, D3DXVECTOR3 *pcenter, FLOAT *pradius)
130 D3DXVECTOR3 temp, temp1;
131 FLOAT d;
132 unsigned int i;
134 if( !ppointsFVF || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
136 temp.x = 0.0f;
137 temp.y = 0.0f;
138 temp.z = 0.0f;
139 temp1 = temp;
140 d = 0.0f;
141 *pradius = 0.0f;
143 for(i=0; i<numvertices; i++)
145 D3DXVec3Add(&temp1, &temp, (D3DXVECTOR3*)((char*)ppointsFVF + D3DXGetFVFVertexSize(FVF) * i));
146 temp = temp1;
149 D3DXVec3Scale(pcenter, &temp, 1.0f/((FLOAT)numvertices));
151 for(i=0; i<numvertices; i++)
153 d = D3DXVec3Length(D3DXVec3Subtract(&temp, (D3DXVECTOR3*)((char*)ppointsFVF + D3DXGetFVFVertexSize(FVF) * i), pcenter));
154 if ( d > *pradius ) *pradius = d;
156 return D3D_OK;
159 static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
161 return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
164 UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
166 DWORD size = 0;
167 UINT i;
168 UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
170 if (FVF & D3DFVF_NORMAL) size += sizeof(D3DXVECTOR3);
171 if (FVF & D3DFVF_DIFFUSE) size += sizeof(DWORD);
172 if (FVF & D3DFVF_SPECULAR) size += sizeof(DWORD);
173 if (FVF & D3DFVF_PSIZE) size += sizeof(DWORD);
175 switch (FVF & D3DFVF_POSITION_MASK)
177 case D3DFVF_XYZ: size += sizeof(D3DXVECTOR3); break;
178 case D3DFVF_XYZRHW: size += 4 * sizeof(FLOAT); break;
179 case D3DFVF_XYZB1: size += 4 * sizeof(FLOAT); break;
180 case D3DFVF_XYZB2: size += 5 * sizeof(FLOAT); break;
181 case D3DFVF_XYZB3: size += 6 * sizeof(FLOAT); break;
182 case D3DFVF_XYZB4: size += 7 * sizeof(FLOAT); break;
183 case D3DFVF_XYZB5: size += 8 * sizeof(FLOAT); break;
186 for (i = 0; i < numTextures; i++)
188 size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
191 return size;
194 BOOL CDECL D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist)
196 D3DXMATRIX m;
197 D3DXVECTOR4 vec;
199 m.m[0][0] = p1->x - p0->x;
200 m.m[1][0] = p2->x - p0->x;
201 m.m[2][0] = -praydir->x;
202 m.m[3][0] = 0.0f;
203 m.m[0][1] = p1->y - p0->z;
204 m.m[1][1] = p2->y - p0->z;
205 m.m[2][1] = -praydir->y;
206 m.m[3][1] = 0.0f;
207 m.m[0][2] = p1->z - p0->z;
208 m.m[1][2] = p2->z - p0->z;
209 m.m[2][2] = -praydir->z;
210 m.m[3][2] = 0.0f;
211 m.m[0][3] = 0.0f;
212 m.m[1][3] = 0.0f;
213 m.m[2][3] = 0.0f;
214 m.m[3][3] = 1.0f;
216 vec.x = praypos->x - p0->x;
217 vec.y = praypos->y - p0->y;
218 vec.z = praypos->z - p0->z;
219 vec.w = 0.0f;
221 if ( D3DXMatrixInverse(&m, NULL, &m) )
223 D3DXVec4Transform(&vec, &vec, &m);
224 if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) )
226 *pu = vec.x;
227 *pv = vec.y;
228 *pdist = fabs( vec.z );
229 return TRUE;
233 return FALSE;
236 BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
238 D3DXVECTOR3 difference;
239 FLOAT a, b, c, d;
241 a = D3DXVec3LengthSq(praydirection);
242 if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE;
243 b = D3DXVec3Dot(&difference, praydirection);
244 c = D3DXVec3LengthSq(&difference) - radius * radius;
245 d = b * b - a * c;
247 if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE;
248 return TRUE;