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 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
26 //#include "wine/port.h"
28 #define NONAMELESSUNION
34 #include <wine/debug.h>
36 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
38 /*************************************************************************
41 BOOL WINAPI
D3DXBoxBoundProbe(CONST D3DXVECTOR3
*pmin
, CONST D3DXVECTOR3
*pmax
, CONST D3DXVECTOR3
*prayposition
, CONST D3DXVECTOR3
*praydirection
)
43 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
44 Amy Williams University of Utah
45 Steve Barrus University of Utah
46 R. Keith Morley University of Utah
47 Peter Shirley University of Utah
49 International Conference on Computer Graphics and Interactive Techniques archive
50 ACM SIGGRAPH 2005 Courses
51 Los Angeles, California
53 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
55 Algorithm: Consider the box as the intersection of three slabs. Clip the ray
56 against each slab, if there's anything left of the ray after we're
57 done we've got an intersection of the ray with the box.
61 FLOAT div
, tmin
, tmax
, tymin
, tymax
, tzmin
, tzmax
;
63 div
= 1.0f
/ praydirection
->x
;
66 tmin
= ( pmin
->x
- prayposition
->x
) * div
;
67 tmax
= ( pmax
->x
- prayposition
->x
) * div
;
71 tmin
= ( pmax
->x
- prayposition
->x
) * div
;
72 tmax
= ( pmin
->x
- prayposition
->x
) * div
;
75 if ( tmax
< 0.0f
) return FALSE
;
77 div
= 1.0f
/ praydirection
->y
;
80 tymin
= ( pmin
->y
- prayposition
->y
) * div
;
81 tymax
= ( pmax
->y
- prayposition
->y
) * div
;
85 tymin
= ( pmax
->y
- prayposition
->y
) * div
;
86 tymax
= ( pmin
->y
- prayposition
->y
) * div
;
89 if ( ( tymax
< 0.0f
) || ( tmin
> tymax
) || ( tymin
> tmax
) ) return FALSE
;
91 if ( tymin
> tmin
) tmin
= tymin
;
92 if ( tymax
< tmax
) tmax
= tymax
;
94 div
= 1.0f
/ praydirection
->z
;
97 tzmin
= ( pmin
->z
- prayposition
->z
) * div
;
98 tzmax
= ( pmax
->z
- prayposition
->z
) * div
;
102 tzmin
= ( pmax
->z
- prayposition
->z
) * div
;
103 tzmax
= ( pmin
->z
- prayposition
->z
) * div
;
106 if ( (tzmax
< 0.0f
) || ( tmin
> tzmax
) || ( tzmin
> tmax
) ) return FALSE
;
111 /*************************************************************************
112 * D3DXComputeBoundingBox
114 HRESULT WINAPI
D3DXComputeBoundingBox(CONST D3DXVECTOR3
*pfirstposition
, DWORD numvertices
, DWORD dwstride
, D3DXVECTOR3
*pmin
, D3DXVECTOR3
*pmax
)
119 if( !pfirstposition
|| !pmin
|| !pmax
) return D3DERR_INVALIDCALL
;
121 *pmin
= *pfirstposition
;
124 for(i
=0; i
<numvertices
; i
++)
126 vec
= *( (D3DXVECTOR3
*)((char*)pfirstposition
+ dwstride
* i
) );
128 if ( vec
.x
< pmin
->x
) pmin
->x
= vec
.x
;
129 if ( vec
.x
> pmax
->x
) pmax
->x
= vec
.x
;
131 if ( vec
.y
< pmin
->y
) pmin
->y
= vec
.y
;
132 if ( vec
.y
> pmax
->y
) pmax
->y
= vec
.y
;
134 if ( vec
.z
< pmin
->z
) pmin
->z
= vec
.z
;
135 if ( vec
.z
> pmax
->z
) pmax
->z
= vec
.z
;
141 /*************************************************************************
142 * D3DXComputeBoundingSphere
144 HRESULT WINAPI
D3DXComputeBoundingSphere(CONST D3DXVECTOR3
* pfirstposition
, DWORD numvertices
, DWORD dwstride
, D3DXVECTOR3
*pcenter
, FLOAT
*pradius
)
146 D3DXVECTOR3 temp
, temp1
;
150 if( !pfirstposition
|| !pcenter
|| !pradius
) return D3DERR_INVALIDCALL
;
159 for(i
=0; i
<numvertices
; i
++)
161 D3DXVec3Add(&temp1
, &temp
, (D3DXVECTOR3
*)((char*)pfirstposition
+ dwstride
* i
));
165 D3DXVec3Scale(pcenter
, &temp
, 1.0f
/((FLOAT
)numvertices
));
167 for(i
=0; i
<numvertices
; i
++)
169 d
= D3DXVec3Length(D3DXVec3Subtract(&temp
, (D3DXVECTOR3
*)((char*)pfirstposition
+ dwstride
* i
), pcenter
));
170 if ( d
> *pradius
) *pradius
= d
;
175 /*************************************************************************
176 * D3DXGetFVFVertexSize
178 static UINT
Get_TexCoord_Size_From_FVF(DWORD FVF
, int tex_num
)
180 return (((((FVF
) >> (16 + (2 * (tex_num
)))) + 1) & 0x03) + 1);
183 UINT WINAPI
D3DXGetFVFVertexSize(DWORD FVF
)
187 UINT numTextures
= (FVF
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
189 if (FVF
& D3DFVF_NORMAL
) size
+= sizeof(D3DXVECTOR3
);
190 if (FVF
& D3DFVF_DIFFUSE
) size
+= sizeof(DWORD
);
191 if (FVF
& D3DFVF_SPECULAR
) size
+= sizeof(DWORD
);
192 if (FVF
& D3DFVF_PSIZE
) size
+= sizeof(DWORD
);
194 switch (FVF
& D3DFVF_POSITION_MASK
)
196 case D3DFVF_XYZ
: size
+= sizeof(D3DXVECTOR3
); break;
197 case D3DFVF_XYZRHW
: size
+= 4 * sizeof(FLOAT
); break;
198 case D3DFVF_XYZB1
: size
+= 4 * sizeof(FLOAT
); break;
199 case D3DFVF_XYZB2
: size
+= 5 * sizeof(FLOAT
); break;
200 case D3DFVF_XYZB3
: size
+= 6 * sizeof(FLOAT
); break;
201 case D3DFVF_XYZB4
: size
+= 7 * sizeof(FLOAT
); break;
202 case D3DFVF_XYZB5
: size
+= 8 * sizeof(FLOAT
); break;
203 case D3DFVF_XYZW
: size
+= 4 * sizeof(FLOAT
); break;
206 for (i
= 0; i
< numTextures
; i
++)
208 size
+= Get_TexCoord_Size_From_FVF(FVF
, i
) * sizeof(FLOAT
);
214 /*************************************************************************
215 * D3DXGetDeclVertexSize
217 UINT WINAPI
D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9
*decl
, DWORD stream_idx
)
219 const D3DVERTEXELEMENT9
*element
;
222 TRACE("decl %p, stream_idx %u\n", decl
, stream_idx
);
226 for (element
= decl
; element
->Stream
!= 0xff; ++element
)
230 if (element
->Stream
!= stream_idx
) continue;
232 switch (element
->Type
)
234 case D3DDECLTYPE_FLOAT1
: type_size
= 1 * 4; break;
235 case D3DDECLTYPE_FLOAT2
: type_size
= 2 * 4; break;
236 case D3DDECLTYPE_FLOAT3
: type_size
= 3 * 4; break;
237 case D3DDECLTYPE_FLOAT4
: type_size
= 4 * 4; break;
238 case D3DDECLTYPE_D3DCOLOR
: type_size
= 4 * 1; break;
239 case D3DDECLTYPE_UBYTE4
: type_size
= 4 * 1; break;
240 case D3DDECLTYPE_SHORT2
: type_size
= 2 * 2; break;
241 case D3DDECLTYPE_SHORT4
: type_size
= 4 * 2; break;
242 case D3DDECLTYPE_UBYTE4N
: type_size
= 4 * 1; break;
243 case D3DDECLTYPE_SHORT2N
: type_size
= 2 * 2; break;
244 case D3DDECLTYPE_SHORT4N
: type_size
= 4 * 2; break;
245 case D3DDECLTYPE_USHORT2N
: type_size
= 2 * 2; break;
246 case D3DDECLTYPE_USHORT4N
: type_size
= 4 * 2; break;
247 case D3DDECLTYPE_UDEC3
: type_size
= 4; break; /* 3 * 10 bits + 2 padding */
248 case D3DDECLTYPE_DEC3N
: type_size
= 4; break;
249 case D3DDECLTYPE_FLOAT16_2
: type_size
= 2 * 2; break;
250 case D3DDECLTYPE_FLOAT16_4
: type_size
= 4 * 2; break;
252 FIXME("Unhandled element type %#x, size will be incorrect.\n", element
->Type
);
257 if (element
->Offset
+ type_size
> size
) size
= element
->Offset
+ type_size
;
263 /*************************************************************************
266 BOOL WINAPI
D3DXIntersectTri(CONST D3DXVECTOR3
*p0
, CONST D3DXVECTOR3
*p1
, CONST D3DXVECTOR3
*p2
, CONST D3DXVECTOR3
*praypos
, CONST D3DXVECTOR3
*praydir
, FLOAT
*pu
, FLOAT
*pv
, FLOAT
*pdist
)
271 m
.u
.m
[0][0] = p1
->x
- p0
->x
;
272 m
.u
.m
[1][0] = p2
->x
- p0
->x
;
273 m
.u
.m
[2][0] = -praydir
->x
;
275 m
.u
.m
[0][1] = p1
->y
- p0
->z
;
276 m
.u
.m
[1][1] = p2
->y
- p0
->z
;
277 m
.u
.m
[2][1] = -praydir
->y
;
279 m
.u
.m
[0][2] = p1
->z
- p0
->z
;
280 m
.u
.m
[1][2] = p2
->z
- p0
->z
;
281 m
.u
.m
[2][2] = -praydir
->z
;
288 vec
.x
= praypos
->x
- p0
->x
;
289 vec
.y
= praypos
->y
- p0
->y
;
290 vec
.z
= praypos
->z
- p0
->z
;
293 if ( D3DXMatrixInverse(&m
, NULL
, &m
) )
295 D3DXVec4Transform(&vec
, &vec
, &m
);
296 if ( (vec
.x
>= 0.0f
) && (vec
.y
>= 0.0f
) && (vec
.x
+ vec
.y
<= 1.0f
) && (vec
.z
>= 0.0f
) )
300 *pdist
= fabs( vec
.z
);
308 /*************************************************************************
309 * D3DXSphereBoundProbe
311 BOOL WINAPI
D3DXSphereBoundProbe(CONST D3DXVECTOR3
*pcenter
, FLOAT radius
, CONST D3DXVECTOR3
*prayposition
, CONST D3DXVECTOR3
*praydirection
)
313 D3DXVECTOR3 difference
;
316 a
= D3DXVec3LengthSq(praydirection
);
317 if (!D3DXVec3Subtract(&difference
, prayposition
, pcenter
)) return FALSE
;
318 b
= D3DXVec3Dot(&difference
, praydirection
);
319 c
= D3DXVec3LengthSq(&difference
) - radius
* radius
;
322 if ( ( d
<= 0.0f
) || ( sqrt(d
) <= b
) ) return FALSE
;