push 52cba0a224aad01bcbdb26d79e43229ba950650e
[wine/hacks.git] / dlls / d3dx8 / mesh.c
blobb0562c7401e853b492aff9932d2798f9d3f1c836
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"
25 #include "d3dx8_private.h"
28 BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *pmin, CONST D3DXVECTOR3 *pmax, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
30 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
31 Amy Williams University of Utah
32 Steve Barrus University of Utah
33 R. Keith Morley University of Utah
34 Peter Shirley University of Utah
36 International Conference on Computer Graphics and Interactive Techniques archive
37 ACM SIGGRAPH 2005 Courses
38 Los Angeles, California
40 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
42 Algorithm: Consider the box as the intersection of three slabs. Clip the ray
43 against each slab, if there's anything left of the ray after we're
44 done we've got an intersection of the ray with the box.
48 FLOAT div, tmin, tmax, tymin, tymax, tzmin, tzmax;
50 div = 1.0f / praydirection->x;
51 if ( div >= 0.0f )
53 tmin = ( pmin->x - prayposition->x ) * div;
54 tmax = ( pmax->x - prayposition->x ) * div;
56 else
58 tmin = ( pmax->x - prayposition->x ) * div;
59 tmax = ( pmin->x - prayposition->x ) * div;
62 if ( tmax < 0.0f ) return FALSE;
64 div = 1.0f / praydirection->y;
65 if ( div >= 0.0f )
67 tymin = ( pmin->y - prayposition->y ) * div;
68 tymax = ( pmax->y - prayposition->y ) * div;
70 else
72 tymin = ( pmax->y - prayposition->y ) * div;
73 tymax = ( pmin->y - prayposition->y ) * div;
76 if ( ( tymax < 0.0f ) || ( tmin > tymax ) || ( tymin > tmax ) ) return FALSE;
78 if ( tymin > tmin ) tmin = tymin;
79 if ( tymax < tmax ) tmax = tymax;
81 div = 1.0f / praydirection->z;
82 if ( div >= 0.0f )
84 tzmin = ( pmin->z - prayposition->z ) * div;
85 tzmax = ( pmax->z - prayposition->z ) * div;
87 else
89 tzmin = ( pmax->z - prayposition->z ) * div;
90 tzmax = ( pmin->z - prayposition->z ) * div;
93 if ( (tzmax < 0.0f ) || ( tmin > tzmax ) || ( tzmin > tmax ) ) return FALSE;
95 return TRUE;
98 HRESULT WINAPI D3DXComputeBoundingBox(PVOID ppointsFVF, DWORD numvertices, DWORD FVF, D3DXVECTOR3 *pmin, D3DXVECTOR3 *pmax)
100 D3DXVECTOR3 vec;
101 unsigned int i;
103 if( !ppointsFVF || !pmin || !pmax ) return D3DERR_INVALIDCALL;
105 *pmin = *(D3DXVECTOR3*)((char*)ppointsFVF);
106 *pmax = *pmin;
108 /* It looks like that D3DXComputeBoundingBox does not take in account the last vertex. */
109 for(i=0; i<numvertices-1; i++)
111 vec = *(D3DXVECTOR3*)((char*)ppointsFVF + D3DXGetFVFVertexSize(FVF) * i);
113 if ( vec.x < pmin->x ) pmin->x = vec.x;
114 if ( vec.x > pmax->x ) pmax->x = vec.x;
116 if ( vec.y < pmin->y ) pmin->y = vec.y;
117 if ( vec.y > pmax->y ) pmax->y = vec.y;
119 if ( vec.z < pmin->z ) pmin->z = vec.z;
120 if ( vec.z > pmax->z ) pmax->z = vec.z;
123 return D3D_OK;
126 HRESULT WINAPI D3DXComputeBoundingSphere(PVOID ppointsFVF, DWORD numvertices, DWORD FVF, D3DXVECTOR3 *pcenter, FLOAT *pradius)
128 D3DXVECTOR3 temp, temp1;
129 FLOAT d;
130 unsigned int i;
132 if( !ppointsFVF || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
134 temp.x = 0.0f;
135 temp.y = 0.0f;
136 temp.z = 0.0f;
137 temp1 = temp;
138 d = 0.0f;
139 *pradius = 0.0f;
141 for(i=0; i<numvertices; i++)
143 D3DXVec3Add(&temp1, &temp, (D3DXVECTOR3*)((char*)ppointsFVF + D3DXGetFVFVertexSize(FVF) * i));
144 temp = temp1;
147 D3DXVec3Scale(pcenter, &temp, 1.0f/((FLOAT)numvertices));
149 for(i=0; i<numvertices; i++)
151 d = D3DXVec3Length(D3DXVec3Subtract(&temp, (D3DXVECTOR3*)((char*)ppointsFVF + D3DXGetFVFVertexSize(FVF) * i), pcenter));
152 if ( d > *pradius ) *pradius = d;
154 return D3D_OK;
157 static UINT Get_TexCoord_Size_From_FVF(DWORD FVF, int tex_num)
159 return (((((FVF) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1);
162 UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF)
164 DWORD size = 0;
165 UINT i;
166 UINT numTextures = (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
168 if (FVF & D3DFVF_NORMAL) size += sizeof(D3DXVECTOR3);
169 if (FVF & D3DFVF_DIFFUSE) size += sizeof(DWORD);
170 if (FVF & D3DFVF_SPECULAR) size += sizeof(DWORD);
171 if (FVF & D3DFVF_PSIZE) size += sizeof(DWORD);
173 switch (FVF & D3DFVF_POSITION_MASK)
175 case D3DFVF_XYZ: size += sizeof(D3DXVECTOR3); break;
176 case D3DFVF_XYZRHW: size += 4 * sizeof(FLOAT); break;
177 case D3DFVF_XYZB1: size += 4 * sizeof(FLOAT); break;
178 case D3DFVF_XYZB2: size += 5 * sizeof(FLOAT); break;
179 case D3DFVF_XYZB3: size += 6 * sizeof(FLOAT); break;
180 case D3DFVF_XYZB4: size += 7 * sizeof(FLOAT); break;
181 case D3DFVF_XYZB5: size += 8 * sizeof(FLOAT); break;
184 for (i = 0; i < numTextures; i++)
186 size += Get_TexCoord_Size_From_FVF(FVF, i) * sizeof(FLOAT);
189 return size;
192 BOOL CDECL D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist)
194 D3DXMATRIX m;
195 D3DXVECTOR4 vec;
197 m.m[0][0] = p1->x - p0->x;
198 m.m[1][0] = p2->x - p0->x;
199 m.m[2][0] = -praydir->x;
200 m.m[3][0] = 0.0f;
201 m.m[0][1] = p1->y - p0->z;
202 m.m[1][1] = p2->y - p0->z;
203 m.m[2][1] = -praydir->y;
204 m.m[3][1] = 0.0f;
205 m.m[0][2] = p1->z - p0->z;
206 m.m[1][2] = p2->z - p0->z;
207 m.m[2][2] = -praydir->z;
208 m.m[3][2] = 0.0f;
209 m.m[0][3] = 0.0f;
210 m.m[1][3] = 0.0f;
211 m.m[2][3] = 0.0f;
212 m.m[3][3] = 1.0f;
214 vec.x = praypos->x - p0->x;
215 vec.y = praypos->y - p0->y;
216 vec.z = praypos->z - p0->z;
217 vec.w = 0.0f;
219 if ( D3DXMatrixInverse(&m, NULL, &m) )
221 D3DXVec4Transform(&vec, &vec, &m);
222 if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) )
224 *pu = vec.x;
225 *pv = vec.y;
226 *pdist = fabs( vec.z );
227 return TRUE;
231 return FALSE;
234 BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
236 D3DXVECTOR3 difference;
237 FLOAT a, b, c, d;
239 a = D3DXVec3LengthSq(praydirection);
240 if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE;
241 b = D3DXVec3Dot(&difference, praydirection);
242 c = D3DXVec3LengthSq(&difference) - radius * radius;
243 d = b * b - a * c;
245 if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE;
246 return TRUE;