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 static void append_decl_element(D3DVERTEXELEMENT9
*declaration
, UINT
*idx
, UINT
*offset
,
194 D3DDECLTYPE type
, D3DDECLUSAGE usage
, UINT usage_idx
)
196 declaration
[*idx
].Stream
= 0;
197 declaration
[*idx
].Offset
= *offset
;
198 declaration
[*idx
].Type
= type
;
199 declaration
[*idx
].Method
= D3DDECLMETHOD_DEFAULT
;
200 declaration
[*idx
].Usage
= usage
;
201 declaration
[*idx
].UsageIndex
= usage_idx
;
203 *offset
+= d3dx_decltype_size
[type
];
207 /*************************************************************************
208 * D3DXDeclaratorFromFVF
210 HRESULT WINAPI
D3DXDeclaratorFromFVF(DWORD fvf
, D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
])
212 static const D3DVERTEXELEMENT9 end_element
= D3DDECL_END();
213 DWORD tex_count
= (fvf
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
214 unsigned int offset
= 0;
215 unsigned int idx
= 0;
218 TRACE("fvf %#x, declaration %p.\n", fvf
, declaration
);
220 if (fvf
& D3DFVF_POSITION_MASK
)
222 BOOL has_blend
= (fvf
& D3DFVF_XYZB5
) >= D3DFVF_XYZB1
;
223 DWORD blend_count
= 1 + (((fvf
& D3DFVF_XYZB5
) - D3DFVF_XYZB1
) >> 1);
224 BOOL has_blend_idx
= (fvf
& D3DFVF_LASTBETA_D3DCOLOR
) || (fvf
& D3DFVF_LASTBETA_UBYTE4
);
226 if (has_blend_idx
) --blend_count
;
228 if ((fvf
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZW
229 || (has_blend
&& blend_count
> 4))
230 return D3DERR_INVALIDCALL
;
232 if ((fvf
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
)
233 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_POSITIONT
, 0);
235 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_POSITION
, 0);
244 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
247 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT2
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
250 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
253 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
256 ERR("Invalid blend count %u.\n", blend_count
);
262 if (fvf
& D3DFVF_LASTBETA_UBYTE4
)
263 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_UBYTE4
, D3DDECLUSAGE_BLENDINDICES
, 0);
264 else if (fvf
& D3DFVF_LASTBETA_D3DCOLOR
)
265 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_BLENDINDICES
, 0);
270 if (fvf
& D3DFVF_NORMAL
)
271 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_NORMAL
, 0);
272 if (fvf
& D3DFVF_PSIZE
)
273 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_PSIZE
, 0);
274 if (fvf
& D3DFVF_DIFFUSE
)
275 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_COLOR
, 0);
276 if (fvf
& D3DFVF_SPECULAR
)
277 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_COLOR
, 1);
279 for (i
= 0; i
< tex_count
; ++i
)
281 switch ((fvf
>> (16 + 2 * i
)) & 0x03)
283 case D3DFVF_TEXTUREFORMAT1
:
284 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_TEXCOORD
, i
);
286 case D3DFVF_TEXTUREFORMAT2
:
287 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT2
, D3DDECLUSAGE_TEXCOORD
, i
);
289 case D3DFVF_TEXTUREFORMAT3
:
290 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_TEXCOORD
, i
);
292 case D3DFVF_TEXTUREFORMAT4
:
293 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_TEXCOORD
, i
);
298 declaration
[idx
] = end_element
;
303 /*************************************************************************
304 * D3DXFVFFromDeclarator
306 HRESULT WINAPI
D3DXFVFFromDeclarator(const D3DVERTEXELEMENT9
*declaration
, DWORD
*fvf
)
308 FIXME("(%p, %p): stub\n", declaration
, fvf
);
313 /*************************************************************************
314 * D3DXGetFVFVertexSize
316 static UINT
Get_TexCoord_Size_From_FVF(DWORD FVF
, int tex_num
)
318 return (((((FVF
) >> (16 + (2 * (tex_num
)))) + 1) & 0x03) + 1);
321 UINT WINAPI
D3DXGetFVFVertexSize(DWORD FVF
)
325 UINT numTextures
= (FVF
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
327 if (FVF
& D3DFVF_NORMAL
) size
+= sizeof(D3DXVECTOR3
);
328 if (FVF
& D3DFVF_DIFFUSE
) size
+= sizeof(DWORD
);
329 if (FVF
& D3DFVF_SPECULAR
) size
+= sizeof(DWORD
);
330 if (FVF
& D3DFVF_PSIZE
) size
+= sizeof(DWORD
);
332 switch (FVF
& D3DFVF_POSITION_MASK
)
334 case D3DFVF_XYZ
: size
+= sizeof(D3DXVECTOR3
); break;
335 case D3DFVF_XYZRHW
: size
+= 4 * sizeof(FLOAT
); break;
336 case D3DFVF_XYZB1
: size
+= 4 * sizeof(FLOAT
); break;
337 case D3DFVF_XYZB2
: size
+= 5 * sizeof(FLOAT
); break;
338 case D3DFVF_XYZB3
: size
+= 6 * sizeof(FLOAT
); break;
339 case D3DFVF_XYZB4
: size
+= 7 * sizeof(FLOAT
); break;
340 case D3DFVF_XYZB5
: size
+= 8 * sizeof(FLOAT
); break;
341 case D3DFVF_XYZW
: size
+= 4 * sizeof(FLOAT
); break;
344 for (i
= 0; i
< numTextures
; i
++)
346 size
+= Get_TexCoord_Size_From_FVF(FVF
, i
) * sizeof(FLOAT
);
352 /*************************************************************************
353 * D3DXGetDeclVertexSize
355 UINT WINAPI
D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9
*decl
, DWORD stream_idx
)
357 const D3DVERTEXELEMENT9
*element
;
360 TRACE("decl %p, stream_idx %u\n", decl
, stream_idx
);
364 for (element
= decl
; element
->Stream
!= 0xff; ++element
)
368 if (element
->Stream
!= stream_idx
) continue;
370 if (element
->Type
>= sizeof(d3dx_decltype_size
) / sizeof(*d3dx_decltype_size
))
372 FIXME("Unhandled element type %#x, size will be incorrect.\n", element
->Type
);
376 type_size
= d3dx_decltype_size
[element
->Type
];
377 if (element
->Offset
+ type_size
> size
) size
= element
->Offset
+ type_size
;
383 /*************************************************************************
386 BOOL WINAPI
D3DXIntersectTri(CONST D3DXVECTOR3
*p0
, CONST D3DXVECTOR3
*p1
, CONST D3DXVECTOR3
*p2
, CONST D3DXVECTOR3
*praypos
, CONST D3DXVECTOR3
*praydir
, FLOAT
*pu
, FLOAT
*pv
, FLOAT
*pdist
)
391 m
.u
.m
[0][0] = p1
->x
- p0
->x
;
392 m
.u
.m
[1][0] = p2
->x
- p0
->x
;
393 m
.u
.m
[2][0] = -praydir
->x
;
395 m
.u
.m
[0][1] = p1
->y
- p0
->z
;
396 m
.u
.m
[1][1] = p2
->y
- p0
->z
;
397 m
.u
.m
[2][1] = -praydir
->y
;
399 m
.u
.m
[0][2] = p1
->z
- p0
->z
;
400 m
.u
.m
[1][2] = p2
->z
- p0
->z
;
401 m
.u
.m
[2][2] = -praydir
->z
;
408 vec
.x
= praypos
->x
- p0
->x
;
409 vec
.y
= praypos
->y
- p0
->y
;
410 vec
.z
= praypos
->z
- p0
->z
;
413 if ( D3DXMatrixInverse(&m
, NULL
, &m
) )
415 D3DXVec4Transform(&vec
, &vec
, &m
);
416 if ( (vec
.x
>= 0.0f
) && (vec
.y
>= 0.0f
) && (vec
.x
+ vec
.y
<= 1.0f
) && (vec
.z
>= 0.0f
) )
420 *pdist
= fabs( vec
.z
);
428 /*************************************************************************
429 * D3DXSphereBoundProbe
431 BOOL WINAPI
D3DXSphereBoundProbe(CONST D3DXVECTOR3
*pcenter
, FLOAT radius
, CONST D3DXVECTOR3
*prayposition
, CONST D3DXVECTOR3
*praydirection
)
433 D3DXVECTOR3 difference
;
436 a
= D3DXVec3LengthSq(praydirection
);
437 if (!D3DXVec3Subtract(&difference
, prayposition
, pcenter
)) return FALSE
;
438 b
= D3DXVec3Dot(&difference
, praydirection
);
439 c
= D3DXVec3LengthSq(&difference
) - radius
* radius
;
442 if ( ( d
<= 0.0f
) || ( sqrt(d
) <= b
) ) return FALSE
;
446 HRESULT WINAPI
D3DXCreateMesh(DWORD numfaces
, DWORD numvertices
, DWORD options
, CONST LPD3DVERTEXELEMENT9
*declaration
,
447 LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*mesh
)
449 FIXME("(%d, %d, %d, %p, %p, %p): stub\n", numfaces
, numvertices
, options
, declaration
, device
, mesh
);
454 HRESULT WINAPI
D3DXCreateBox(LPDIRECT3DDEVICE9 device
, FLOAT width
, FLOAT height
,
455 FLOAT depth
, LPD3DXMESH
* mesh
, LPD3DXBUFFER
* adjacency
)
457 FIXME("(%p, %f, %f, %f, %p, %p): stub\n", device
, width
, height
, depth
, mesh
, adjacency
);
462 HRESULT WINAPI
D3DXCreateSphere(LPDIRECT3DDEVICE9 device
, FLOAT radius
, UINT slices
,
463 UINT stacks
, LPD3DXMESH
* mesh
, LPD3DXBUFFER
* adjacency
)
465 FIXME("(%p, %f, %d, %d, %p, %p): stub\n", device
, radius
, slices
, stacks
, mesh
, adjacency
);