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"
32 #include "d3dx9_36_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
36 typedef struct ID3DXMeshImpl
38 ID3DXMesh ID3DXMesh_iface
;
45 IDirect3DDevice9
*device
;
46 IDirect3DVertexDeclaration9
*vertex_declaration
;
47 IDirect3DVertexBuffer9
*vertex_buffer
;
48 IDirect3DIndexBuffer9
*index_buffer
;
51 static inline ID3DXMeshImpl
*impl_from_ID3DXMesh(ID3DXMesh
*iface
)
53 return CONTAINING_RECORD(iface
, ID3DXMeshImpl
, ID3DXMesh_iface
);
56 static HRESULT WINAPI
ID3DXMeshImpl_QueryInterface(ID3DXMesh
*iface
, REFIID riid
, LPVOID
*object
)
58 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
60 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), object
);
62 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
63 IsEqualGUID(riid
, &IID_ID3DXBaseMesh
) ||
64 IsEqualGUID(riid
, &IID_ID3DXMesh
))
66 iface
->lpVtbl
->AddRef(iface
);
71 WARN("Interface %s not found.\n", debugstr_guid(riid
));
76 static ULONG WINAPI
ID3DXMeshImpl_AddRef(ID3DXMesh
*iface
)
78 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
80 TRACE("(%p)->(): AddRef from %d\n", This
, This
->ref
);
82 return InterlockedIncrement(&This
->ref
);
85 static ULONG WINAPI
ID3DXMeshImpl_Release(ID3DXMesh
*iface
)
87 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
88 ULONG ref
= InterlockedDecrement(&This
->ref
);
90 TRACE("(%p)->(): Release from %d\n", This
, ref
+ 1);
94 IDirect3DIndexBuffer9_Release(This
->index_buffer
);
95 IDirect3DVertexBuffer9_Release(This
->vertex_buffer
);
96 IDirect3DVertexDeclaration9_Release(This
->vertex_declaration
);
97 IDirect3DDevice9_Release(This
->device
);
98 HeapFree(GetProcessHeap(), 0, This
);
104 /*** ID3DXBaseMesh ***/
105 static HRESULT WINAPI
ID3DXMeshImpl_DrawSubset(ID3DXMesh
*iface
, DWORD attrib_id
)
107 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
109 FIXME("(%p)->(%u): stub\n", This
, attrib_id
);
114 static DWORD WINAPI
ID3DXMeshImpl_GetNumFaces(ID3DXMesh
*iface
)
116 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
118 TRACE("(%p)\n", This
);
120 return This
->numfaces
;
123 static DWORD WINAPI
ID3DXMeshImpl_GetNumVertices(ID3DXMesh
*iface
)
125 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
127 TRACE("(%p)\n", This
);
129 return This
->numvertices
;
132 static DWORD WINAPI
ID3DXMeshImpl_GetFVF(ID3DXMesh
*iface
)
134 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
136 TRACE("(%p)\n", This
);
141 static HRESULT WINAPI
ID3DXMeshImpl_GetDeclaration(ID3DXMesh
*iface
, D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
])
143 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
146 TRACE("(%p)\n", This
);
148 if (declaration
== NULL
) return D3DERR_INVALIDCALL
;
150 return IDirect3DVertexDeclaration9_GetDeclaration(This
->vertex_declaration
,
155 static DWORD WINAPI
ID3DXMeshImpl_GetNumBytesPerVertex(ID3DXMesh
*iface
)
157 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
159 FIXME("(%p): stub\n", This
);
161 return 0; /* arbitrary since we cannot return E_NOTIMPL */
164 static DWORD WINAPI
ID3DXMeshImpl_GetOptions(ID3DXMesh
*iface
)
166 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
168 TRACE("(%p)\n", This
);
170 return This
->options
;
173 static HRESULT WINAPI
ID3DXMeshImpl_GetDevice(ID3DXMesh
*iface
, LPDIRECT3DDEVICE9
*device
)
175 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
177 TRACE("(%p)->(%p)\n", This
, device
);
179 if (device
== NULL
) return D3DERR_INVALIDCALL
;
180 *device
= This
->device
;
181 IDirect3DDevice9_AddRef(This
->device
);
186 static HRESULT WINAPI
ID3DXMeshImpl_CloneMeshFVF(ID3DXMesh
*iface
, DWORD options
, DWORD fvf
, LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*clone_mesh
)
188 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
190 FIXME("(%p)->(%u,%u,%p,%p): stub\n", This
, options
, fvf
, device
, clone_mesh
);
195 static HRESULT WINAPI
ID3DXMeshImpl_CloneMesh(ID3DXMesh
*iface
, DWORD options
, CONST D3DVERTEXELEMENT9
*declaration
, LPDIRECT3DDEVICE9 device
,
196 LPD3DXMESH
*clone_mesh
)
198 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
200 FIXME("(%p)->(%u,%p,%p,%p): stub\n", This
, options
, declaration
, device
, clone_mesh
);
205 static HRESULT WINAPI
ID3DXMeshImpl_GetVertexBuffer(ID3DXMesh
*iface
, LPDIRECT3DVERTEXBUFFER9
*vertex_buffer
)
207 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
209 TRACE("(%p)->(%p)\n", This
, vertex_buffer
);
211 if (vertex_buffer
== NULL
) return D3DERR_INVALIDCALL
;
212 *vertex_buffer
= This
->vertex_buffer
;
213 IDirect3DVertexBuffer9_AddRef(This
->vertex_buffer
);
218 static HRESULT WINAPI
ID3DXMeshImpl_GetIndexBuffer(ID3DXMesh
*iface
, LPDIRECT3DINDEXBUFFER9
*index_buffer
)
220 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
222 TRACE("(%p)->(%p)\n", This
, index_buffer
);
224 if (index_buffer
== NULL
) return D3DERR_INVALIDCALL
;
225 *index_buffer
= This
->index_buffer
;
226 IDirect3DIndexBuffer9_AddRef(This
->index_buffer
);
231 static HRESULT WINAPI
ID3DXMeshImpl_LockVertexBuffer(ID3DXMesh
*iface
, DWORD flags
, LPVOID
*data
)
233 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
235 TRACE("(%p)->(%u,%p)\n", This
, flags
, data
);
237 return IDirect3DVertexBuffer9_Lock(This
->vertex_buffer
, 0, 0, data
, flags
);
240 static HRESULT WINAPI
ID3DXMeshImpl_UnlockVertexBuffer(ID3DXMesh
*iface
)
242 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
244 TRACE("(%p)\n", This
);
246 return IDirect3DVertexBuffer9_Unlock(This
->vertex_buffer
);
249 static HRESULT WINAPI
ID3DXMeshImpl_LockIndexBuffer(ID3DXMesh
*iface
, DWORD flags
, LPVOID
*data
)
251 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
253 TRACE("(%p)->(%u,%p)\n", This
, flags
, data
);
255 return IDirect3DIndexBuffer9_Lock(This
->index_buffer
, 0, 0, data
, flags
);
258 static HRESULT WINAPI
ID3DXMeshImpl_UnlockIndexBuffer(ID3DXMesh
*iface
)
260 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
262 TRACE("(%p)\n", This
);
264 return IDirect3DIndexBuffer9_Unlock(This
->index_buffer
);
267 static HRESULT WINAPI
ID3DXMeshImpl_GetAttributeTable(ID3DXMesh
*iface
, D3DXATTRIBUTERANGE
*attrib_table
, DWORD
*attrib_table_size
)
269 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
271 FIXME("(%p)->(%p,%p): stub\n", This
, attrib_table
, attrib_table_size
);
276 static HRESULT WINAPI
ID3DXMeshImpl_ConvertPointRepsToAdjacency(ID3DXMesh
*iface
, CONST DWORD
*point_reps
, DWORD
*adjacency
)
278 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
280 FIXME("(%p)->(%p,%p): stub\n", This
, point_reps
, adjacency
);
285 static HRESULT WINAPI
ID3DXMeshImpl_ConvertAdjacencyToPointReps(ID3DXMesh
*iface
, CONST DWORD
*adjacency
, DWORD
*point_reps
)
287 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
289 FIXME("(%p)->(%p,%p): stub\n", This
, adjacency
, point_reps
);
294 static HRESULT WINAPI
ID3DXMeshImpl_GenerateAdjacency(ID3DXMesh
*iface
, FLOAT epsilon
, DWORD
*adjacency
)
296 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
298 FIXME("(%p)->(%f,%p): stub\n", This
, epsilon
, adjacency
);
303 static HRESULT WINAPI
ID3DXMeshImpl_UpdateSemantics(ID3DXMesh
*iface
, D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
])
305 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
307 FIXME("(%p)->(%p): stub\n", This
, declaration
);
313 static HRESULT WINAPI
ID3DXMeshImpl_LockAttributeBuffer(ID3DXMesh
*iface
, DWORD flags
, DWORD
**data
)
315 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
317 FIXME("(%p)->(%u,%p): stub\n", This
, flags
, data
);
322 static HRESULT WINAPI
ID3DXMeshImpl_UnlockAttributeBuffer(ID3DXMesh
*iface
)
324 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
326 FIXME("(%p): stub\n", This
);
331 static HRESULT WINAPI
ID3DXMeshImpl_Optimize(ID3DXMesh
*iface
, DWORD flags
, CONST DWORD
*adjacency_in
, DWORD
*adjacency_out
,
332 DWORD
*face_remap
, LPD3DXBUFFER
*vertex_remap
, LPD3DXMESH
*opt_mesh
)
334 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
336 FIXME("(%p)->(%u,%p,%p,%p,%p,%p): stub\n", This
, flags
, adjacency_in
, adjacency_out
, face_remap
, vertex_remap
, opt_mesh
);
341 static HRESULT WINAPI
ID3DXMeshImpl_OptimizeInplace(ID3DXMesh
*iface
, DWORD flags
, CONST DWORD
*adjacency_in
, DWORD
*adjacency_out
,
342 DWORD
*face_remap
, LPD3DXBUFFER
*vertex_remap
)
344 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
346 FIXME("(%p)->(%u,%p,%p,%p,%p): stub\n", This
, flags
, adjacency_in
, adjacency_out
, face_remap
, vertex_remap
);
351 static HRESULT WINAPI
ID3DXMeshImpl_SetAttributeTable(ID3DXMesh
*iface
, CONST D3DXATTRIBUTERANGE
*attrib_table
, DWORD attrib_table_size
)
353 ID3DXMeshImpl
*This
= impl_from_ID3DXMesh(iface
);
355 FIXME("(%p)->(%p,%u): stub\n", This
, attrib_table
, attrib_table_size
);
360 static const struct ID3DXMeshVtbl D3DXMesh_Vtbl
=
362 /*** IUnknown methods ***/
363 ID3DXMeshImpl_QueryInterface
,
364 ID3DXMeshImpl_AddRef
,
365 ID3DXMeshImpl_Release
,
366 /*** ID3DXBaseMesh ***/
367 ID3DXMeshImpl_DrawSubset
,
368 ID3DXMeshImpl_GetNumFaces
,
369 ID3DXMeshImpl_GetNumVertices
,
370 ID3DXMeshImpl_GetFVF
,
371 ID3DXMeshImpl_GetDeclaration
,
372 ID3DXMeshImpl_GetNumBytesPerVertex
,
373 ID3DXMeshImpl_GetOptions
,
374 ID3DXMeshImpl_GetDevice
,
375 ID3DXMeshImpl_CloneMeshFVF
,
376 ID3DXMeshImpl_CloneMesh
,
377 ID3DXMeshImpl_GetVertexBuffer
,
378 ID3DXMeshImpl_GetIndexBuffer
,
379 ID3DXMeshImpl_LockVertexBuffer
,
380 ID3DXMeshImpl_UnlockVertexBuffer
,
381 ID3DXMeshImpl_LockIndexBuffer
,
382 ID3DXMeshImpl_UnlockIndexBuffer
,
383 ID3DXMeshImpl_GetAttributeTable
,
384 ID3DXMeshImpl_ConvertPointRepsToAdjacency
,
385 ID3DXMeshImpl_ConvertAdjacencyToPointReps
,
386 ID3DXMeshImpl_GenerateAdjacency
,
387 ID3DXMeshImpl_UpdateSemantics
,
389 ID3DXMeshImpl_LockAttributeBuffer
,
390 ID3DXMeshImpl_UnlockAttributeBuffer
,
391 ID3DXMeshImpl_Optimize
,
392 ID3DXMeshImpl_OptimizeInplace
,
393 ID3DXMeshImpl_SetAttributeTable
396 /*************************************************************************
399 BOOL WINAPI
D3DXBoxBoundProbe(CONST D3DXVECTOR3
*pmin
, CONST D3DXVECTOR3
*pmax
, CONST D3DXVECTOR3
*prayposition
, CONST D3DXVECTOR3
*praydirection
)
401 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
402 Amy Williams University of Utah
403 Steve Barrus University of Utah
404 R. Keith Morley University of Utah
405 Peter Shirley University of Utah
407 International Conference on Computer Graphics and Interactive Techniques archive
408 ACM SIGGRAPH 2005 Courses
409 Los Angeles, California
411 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
413 Algorithm: Consider the box as the intersection of three slabs. Clip the ray
414 against each slab, if there's anything left of the ray after we're
415 done we've got an intersection of the ray with the box.
419 FLOAT div
, tmin
, tmax
, tymin
, tymax
, tzmin
, tzmax
;
421 div
= 1.0f
/ praydirection
->x
;
424 tmin
= ( pmin
->x
- prayposition
->x
) * div
;
425 tmax
= ( pmax
->x
- prayposition
->x
) * div
;
429 tmin
= ( pmax
->x
- prayposition
->x
) * div
;
430 tmax
= ( pmin
->x
- prayposition
->x
) * div
;
433 if ( tmax
< 0.0f
) return FALSE
;
435 div
= 1.0f
/ praydirection
->y
;
438 tymin
= ( pmin
->y
- prayposition
->y
) * div
;
439 tymax
= ( pmax
->y
- prayposition
->y
) * div
;
443 tymin
= ( pmax
->y
- prayposition
->y
) * div
;
444 tymax
= ( pmin
->y
- prayposition
->y
) * div
;
447 if ( ( tymax
< 0.0f
) || ( tmin
> tymax
) || ( tymin
> tmax
) ) return FALSE
;
449 if ( tymin
> tmin
) tmin
= tymin
;
450 if ( tymax
< tmax
) tmax
= tymax
;
452 div
= 1.0f
/ praydirection
->z
;
455 tzmin
= ( pmin
->z
- prayposition
->z
) * div
;
456 tzmax
= ( pmax
->z
- prayposition
->z
) * div
;
460 tzmin
= ( pmax
->z
- prayposition
->z
) * div
;
461 tzmax
= ( pmin
->z
- prayposition
->z
) * div
;
464 if ( (tzmax
< 0.0f
) || ( tmin
> tzmax
) || ( tzmin
> tmax
) ) return FALSE
;
469 /*************************************************************************
470 * D3DXComputeBoundingBox
472 HRESULT WINAPI
D3DXComputeBoundingBox(CONST D3DXVECTOR3
*pfirstposition
, DWORD numvertices
, DWORD dwstride
, D3DXVECTOR3
*pmin
, D3DXVECTOR3
*pmax
)
477 if( !pfirstposition
|| !pmin
|| !pmax
) return D3DERR_INVALIDCALL
;
479 *pmin
= *pfirstposition
;
482 for(i
=0; i
<numvertices
; i
++)
484 vec
= *( (const D3DXVECTOR3
*)((const char*)pfirstposition
+ dwstride
* i
) );
486 if ( vec
.x
< pmin
->x
) pmin
->x
= vec
.x
;
487 if ( vec
.x
> pmax
->x
) pmax
->x
= vec
.x
;
489 if ( vec
.y
< pmin
->y
) pmin
->y
= vec
.y
;
490 if ( vec
.y
> pmax
->y
) pmax
->y
= vec
.y
;
492 if ( vec
.z
< pmin
->z
) pmin
->z
= vec
.z
;
493 if ( vec
.z
> pmax
->z
) pmax
->z
= vec
.z
;
499 /*************************************************************************
500 * D3DXComputeBoundingSphere
502 HRESULT WINAPI
D3DXComputeBoundingSphere(CONST D3DXVECTOR3
* pfirstposition
, DWORD numvertices
, DWORD dwstride
, D3DXVECTOR3
*pcenter
, FLOAT
*pradius
)
504 D3DXVECTOR3 temp
, temp1
;
508 if( !pfirstposition
|| !pcenter
|| !pradius
) return D3DERR_INVALIDCALL
;
517 for(i
=0; i
<numvertices
; i
++)
519 D3DXVec3Add(&temp1
, &temp
, (const D3DXVECTOR3
*)((const char*)pfirstposition
+ dwstride
* i
));
523 D3DXVec3Scale(pcenter
, &temp
, 1.0f
/((FLOAT
)numvertices
));
525 for(i
=0; i
<numvertices
; i
++)
527 d
= D3DXVec3Length(D3DXVec3Subtract(&temp
, (const D3DXVECTOR3
*)((const char*)pfirstposition
+ dwstride
* i
), pcenter
));
528 if ( d
> *pradius
) *pradius
= d
;
533 static const UINT d3dx_decltype_size
[D3DDECLTYPE_UNUSED
] =
535 /* D3DDECLTYPE_FLOAT1 */ 1 * 4,
536 /* D3DDECLTYPE_FLOAT2 */ 2 * 4,
537 /* D3DDECLTYPE_FLOAT3 */ 3 * 4,
538 /* D3DDECLTYPE_FLOAT4 */ 4 * 4,
539 /* D3DDECLTYPE_D3DCOLOR */ 4 * 1,
540 /* D3DDECLTYPE_UBYTE4 */ 4 * 1,
541 /* D3DDECLTYPE_SHORT2 */ 2 * 2,
542 /* D3DDECLTYPE_SHORT4 */ 4 * 2,
543 /* D3DDECLTYPE_UBYTE4N */ 4 * 1,
544 /* D3DDECLTYPE_SHORT2N */ 2 * 2,
545 /* D3DDECLTYPE_SHORT4N */ 4 * 2,
546 /* D3DDECLTYPE_USHORT2N */ 2 * 2,
547 /* D3DDECLTYPE_USHORT4N */ 4 * 2,
548 /* D3DDECLTYPE_UDEC3 */ 4, /* 3 * 10 bits + 2 padding */
549 /* D3DDECLTYPE_DEC3N */ 4,
550 /* D3DDECLTYPE_FLOAT16_2 */ 2 * 2,
551 /* D3DDECLTYPE_FLOAT16_4 */ 4 * 2,
554 static void append_decl_element(D3DVERTEXELEMENT9
*declaration
, UINT
*idx
, UINT
*offset
,
555 D3DDECLTYPE type
, D3DDECLUSAGE usage
, UINT usage_idx
)
557 declaration
[*idx
].Stream
= 0;
558 declaration
[*idx
].Offset
= *offset
;
559 declaration
[*idx
].Type
= type
;
560 declaration
[*idx
].Method
= D3DDECLMETHOD_DEFAULT
;
561 declaration
[*idx
].Usage
= usage
;
562 declaration
[*idx
].UsageIndex
= usage_idx
;
564 *offset
+= d3dx_decltype_size
[type
];
568 /*************************************************************************
569 * D3DXDeclaratorFromFVF
571 HRESULT WINAPI
D3DXDeclaratorFromFVF(DWORD fvf
, D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
])
573 static const D3DVERTEXELEMENT9 end_element
= D3DDECL_END();
574 DWORD tex_count
= (fvf
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
575 unsigned int offset
= 0;
576 unsigned int idx
= 0;
579 TRACE("fvf %#x, declaration %p.\n", fvf
, declaration
);
581 if (fvf
& (D3DFVF_RESERVED0
| D3DFVF_RESERVED2
)) return D3DERR_INVALIDCALL
;
583 if (fvf
& D3DFVF_POSITION_MASK
)
585 BOOL has_blend
= (fvf
& D3DFVF_XYZB5
) >= D3DFVF_XYZB1
;
586 DWORD blend_count
= 1 + (((fvf
& D3DFVF_XYZB5
) - D3DFVF_XYZB1
) >> 1);
587 BOOL has_blend_idx
= (fvf
& D3DFVF_LASTBETA_D3DCOLOR
) || (fvf
& D3DFVF_LASTBETA_UBYTE4
);
589 if (has_blend_idx
) --blend_count
;
591 if ((fvf
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZW
592 || (has_blend
&& blend_count
> 4))
593 return D3DERR_INVALIDCALL
;
595 if ((fvf
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
)
596 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_POSITIONT
, 0);
598 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_POSITION
, 0);
607 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
610 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT2
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
613 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
616 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
619 ERR("Invalid blend count %u.\n", blend_count
);
625 if (fvf
& D3DFVF_LASTBETA_UBYTE4
)
626 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_UBYTE4
, D3DDECLUSAGE_BLENDINDICES
, 0);
627 else if (fvf
& D3DFVF_LASTBETA_D3DCOLOR
)
628 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_BLENDINDICES
, 0);
633 if (fvf
& D3DFVF_NORMAL
)
634 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_NORMAL
, 0);
635 if (fvf
& D3DFVF_PSIZE
)
636 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_PSIZE
, 0);
637 if (fvf
& D3DFVF_DIFFUSE
)
638 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_COLOR
, 0);
639 if (fvf
& D3DFVF_SPECULAR
)
640 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_COLOR
, 1);
642 for (i
= 0; i
< tex_count
; ++i
)
644 switch ((fvf
>> (16 + 2 * i
)) & 0x03)
646 case D3DFVF_TEXTUREFORMAT1
:
647 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_TEXCOORD
, i
);
649 case D3DFVF_TEXTUREFORMAT2
:
650 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT2
, D3DDECLUSAGE_TEXCOORD
, i
);
652 case D3DFVF_TEXTUREFORMAT3
:
653 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_TEXCOORD
, i
);
655 case D3DFVF_TEXTUREFORMAT4
:
656 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_TEXCOORD
, i
);
661 declaration
[idx
] = end_element
;
666 /*************************************************************************
667 * D3DXFVFFromDeclarator
669 HRESULT WINAPI
D3DXFVFFromDeclarator(const D3DVERTEXELEMENT9
*declaration
, DWORD
*fvf
)
671 unsigned int i
= 0, texture
, offset
;
673 TRACE("(%p, %p)\n", declaration
, fvf
);
676 if (declaration
[0].Type
== D3DDECLTYPE_FLOAT3
&& declaration
[0].Usage
== D3DDECLUSAGE_POSITION
)
678 if ((declaration
[1].Type
== D3DDECLTYPE_FLOAT4
&& declaration
[1].Usage
== D3DDECLUSAGE_BLENDWEIGHT
&&
679 declaration
[1].UsageIndex
== 0) &&
680 (declaration
[2].Type
== D3DDECLTYPE_FLOAT1
&& declaration
[2].Usage
== D3DDECLUSAGE_BLENDINDICES
&&
681 declaration
[2].UsageIndex
== 0))
683 return D3DERR_INVALIDCALL
;
685 else if ((declaration
[1].Type
== D3DDECLTYPE_UBYTE4
|| declaration
[1].Type
== D3DDECLTYPE_D3DCOLOR
) &&
686 declaration
[1].Usage
== D3DDECLUSAGE_BLENDINDICES
&& declaration
[1].UsageIndex
== 0)
688 if (declaration
[1].Type
== D3DDECLTYPE_UBYTE4
)
690 *fvf
|= D3DFVF_XYZB1
| D3DFVF_LASTBETA_UBYTE4
;
694 *fvf
|= D3DFVF_XYZB1
| D3DFVF_LASTBETA_D3DCOLOR
;
698 else if (declaration
[1].Type
<= D3DDECLTYPE_FLOAT4
&& declaration
[1].Usage
== D3DDECLUSAGE_BLENDWEIGHT
&&
699 declaration
[1].UsageIndex
== 0)
701 if ((declaration
[2].Type
== D3DDECLTYPE_UBYTE4
|| declaration
[2].Type
== D3DDECLTYPE_D3DCOLOR
) &&
702 declaration
[2].Usage
== D3DDECLUSAGE_BLENDINDICES
&& declaration
[2].UsageIndex
== 0)
704 if (declaration
[2].Type
== D3DDECLTYPE_UBYTE4
)
706 *fvf
|= D3DFVF_LASTBETA_UBYTE4
;
710 *fvf
|= D3DFVF_LASTBETA_D3DCOLOR
;
712 switch (declaration
[1].Type
)
714 case D3DDECLTYPE_FLOAT1
: *fvf
|= D3DFVF_XYZB2
; break;
715 case D3DDECLTYPE_FLOAT2
: *fvf
|= D3DFVF_XYZB3
; break;
716 case D3DDECLTYPE_FLOAT3
: *fvf
|= D3DFVF_XYZB4
; break;
717 case D3DDECLTYPE_FLOAT4
: *fvf
|= D3DFVF_XYZB5
; break;
723 switch (declaration
[1].Type
)
725 case D3DDECLTYPE_FLOAT1
: *fvf
|= D3DFVF_XYZB1
; break;
726 case D3DDECLTYPE_FLOAT2
: *fvf
|= D3DFVF_XYZB2
; break;
727 case D3DDECLTYPE_FLOAT3
: *fvf
|= D3DFVF_XYZB3
; break;
728 case D3DDECLTYPE_FLOAT4
: *fvf
|= D3DFVF_XYZB4
; break;
739 else if (declaration
[0].Type
== D3DDECLTYPE_FLOAT4
&& declaration
[0].Usage
== D3DDECLUSAGE_POSITIONT
&&
740 declaration
[0].UsageIndex
== 0)
742 *fvf
|= D3DFVF_XYZRHW
;
746 if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT3
&& declaration
[i
].Usage
== D3DDECLUSAGE_NORMAL
)
748 *fvf
|= D3DFVF_NORMAL
;
751 if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT1
&& declaration
[i
].Usage
== D3DDECLUSAGE_PSIZE
&&
752 declaration
[i
].UsageIndex
== 0)
754 *fvf
|= D3DFVF_PSIZE
;
757 if (declaration
[i
].Type
== D3DDECLTYPE_D3DCOLOR
&& declaration
[i
].Usage
== D3DDECLUSAGE_COLOR
&&
758 declaration
[i
].UsageIndex
== 0)
760 *fvf
|= D3DFVF_DIFFUSE
;
763 if (declaration
[i
].Type
== D3DDECLTYPE_D3DCOLOR
&& declaration
[i
].Usage
== D3DDECLUSAGE_COLOR
&&
764 declaration
[i
].UsageIndex
== 1)
766 *fvf
|= D3DFVF_SPECULAR
;
770 for (texture
= 0; texture
< D3DDP_MAXTEXCOORD
; i
++, texture
++)
772 if (declaration
[i
].Stream
== 0xFF)
776 else if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT1
&& declaration
[i
].Usage
== D3DDECLUSAGE_TEXCOORD
&&
777 declaration
[i
].UsageIndex
== texture
)
779 *fvf
|= D3DFVF_TEXCOORDSIZE1(declaration
[i
].UsageIndex
);
781 else if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT2
&& declaration
[i
].Usage
== D3DDECLUSAGE_TEXCOORD
&&
782 declaration
[i
].UsageIndex
== texture
)
784 *fvf
|= D3DFVF_TEXCOORDSIZE2(declaration
[i
].UsageIndex
);
786 else if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT3
&& declaration
[i
].Usage
== D3DDECLUSAGE_TEXCOORD
&&
787 declaration
[i
].UsageIndex
== texture
)
789 *fvf
|= D3DFVF_TEXCOORDSIZE3(declaration
[i
].UsageIndex
);
791 else if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT4
&& declaration
[i
].Usage
== D3DDECLUSAGE_TEXCOORD
&&
792 declaration
[i
].UsageIndex
== texture
)
794 *fvf
|= D3DFVF_TEXCOORDSIZE4(declaration
[i
].UsageIndex
);
798 return D3DERR_INVALIDCALL
;
802 *fvf
|= (texture
<< D3DFVF_TEXCOUNT_SHIFT
);
804 for (offset
= 0, i
= 0; declaration
[i
].Stream
!= 0xFF;
805 offset
+= d3dx_decltype_size
[declaration
[i
].Type
], i
++)
807 if (declaration
[i
].Offset
!= offset
)
809 return D3DERR_INVALIDCALL
;
816 /*************************************************************************
817 * D3DXGetFVFVertexSize
819 static UINT
Get_TexCoord_Size_From_FVF(DWORD FVF
, int tex_num
)
821 return (((((FVF
) >> (16 + (2 * (tex_num
)))) + 1) & 0x03) + 1);
824 UINT WINAPI
D3DXGetFVFVertexSize(DWORD FVF
)
828 UINT numTextures
= (FVF
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
830 if (FVF
& D3DFVF_NORMAL
) size
+= sizeof(D3DXVECTOR3
);
831 if (FVF
& D3DFVF_DIFFUSE
) size
+= sizeof(DWORD
);
832 if (FVF
& D3DFVF_SPECULAR
) size
+= sizeof(DWORD
);
833 if (FVF
& D3DFVF_PSIZE
) size
+= sizeof(DWORD
);
835 switch (FVF
& D3DFVF_POSITION_MASK
)
837 case D3DFVF_XYZ
: size
+= sizeof(D3DXVECTOR3
); break;
838 case D3DFVF_XYZRHW
: size
+= 4 * sizeof(FLOAT
); break;
839 case D3DFVF_XYZB1
: size
+= 4 * sizeof(FLOAT
); break;
840 case D3DFVF_XYZB2
: size
+= 5 * sizeof(FLOAT
); break;
841 case D3DFVF_XYZB3
: size
+= 6 * sizeof(FLOAT
); break;
842 case D3DFVF_XYZB4
: size
+= 7 * sizeof(FLOAT
); break;
843 case D3DFVF_XYZB5
: size
+= 8 * sizeof(FLOAT
); break;
844 case D3DFVF_XYZW
: size
+= 4 * sizeof(FLOAT
); break;
847 for (i
= 0; i
< numTextures
; i
++)
849 size
+= Get_TexCoord_Size_From_FVF(FVF
, i
) * sizeof(FLOAT
);
855 /*************************************************************************
856 * D3DXGetDeclVertexSize
858 UINT WINAPI
D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9
*decl
, DWORD stream_idx
)
860 const D3DVERTEXELEMENT9
*element
;
863 TRACE("decl %p, stream_idx %u\n", decl
, stream_idx
);
867 for (element
= decl
; element
->Stream
!= 0xff; ++element
)
871 if (element
->Stream
!= stream_idx
) continue;
873 if (element
->Type
>= sizeof(d3dx_decltype_size
) / sizeof(*d3dx_decltype_size
))
875 FIXME("Unhandled element type %#x, size will be incorrect.\n", element
->Type
);
879 type_size
= d3dx_decltype_size
[element
->Type
];
880 if (element
->Offset
+ type_size
> size
) size
= element
->Offset
+ type_size
;
886 /*************************************************************************
889 UINT WINAPI
D3DXGetDeclLength(const D3DVERTEXELEMENT9
*decl
)
891 const D3DVERTEXELEMENT9
*element
;
893 TRACE("decl %p\n", decl
);
895 /* null decl results in exception on Windows XP */
897 for (element
= decl
; element
->Stream
!= 0xff; ++element
);
899 return element
- decl
;
902 /*************************************************************************
905 BOOL WINAPI
D3DXIntersectTri(CONST D3DXVECTOR3
*p0
, CONST D3DXVECTOR3
*p1
, CONST D3DXVECTOR3
*p2
, CONST D3DXVECTOR3
*praypos
, CONST D3DXVECTOR3
*praydir
, FLOAT
*pu
, FLOAT
*pv
, FLOAT
*pdist
)
910 m
.u
.m
[0][0] = p1
->x
- p0
->x
;
911 m
.u
.m
[1][0] = p2
->x
- p0
->x
;
912 m
.u
.m
[2][0] = -praydir
->x
;
914 m
.u
.m
[0][1] = p1
->y
- p0
->z
;
915 m
.u
.m
[1][1] = p2
->y
- p0
->z
;
916 m
.u
.m
[2][1] = -praydir
->y
;
918 m
.u
.m
[0][2] = p1
->z
- p0
->z
;
919 m
.u
.m
[1][2] = p2
->z
- p0
->z
;
920 m
.u
.m
[2][2] = -praydir
->z
;
927 vec
.x
= praypos
->x
- p0
->x
;
928 vec
.y
= praypos
->y
- p0
->y
;
929 vec
.z
= praypos
->z
- p0
->z
;
932 if ( D3DXMatrixInverse(&m
, NULL
, &m
) )
934 D3DXVec4Transform(&vec
, &vec
, &m
);
935 if ( (vec
.x
>= 0.0f
) && (vec
.y
>= 0.0f
) && (vec
.x
+ vec
.y
<= 1.0f
) && (vec
.z
>= 0.0f
) )
939 *pdist
= fabs( vec
.z
);
947 /*************************************************************************
948 * D3DXSphereBoundProbe
950 BOOL WINAPI
D3DXSphereBoundProbe(CONST D3DXVECTOR3
*pcenter
, FLOAT radius
, CONST D3DXVECTOR3
*prayposition
, CONST D3DXVECTOR3
*praydirection
)
952 D3DXVECTOR3 difference
;
955 a
= D3DXVec3LengthSq(praydirection
);
956 if (!D3DXVec3Subtract(&difference
, prayposition
, pcenter
)) return FALSE
;
957 b
= D3DXVec3Dot(&difference
, praydirection
);
958 c
= D3DXVec3LengthSq(&difference
) - radius
* radius
;
961 if ( ( d
<= 0.0f
) || ( sqrt(d
) <= b
) ) return FALSE
;
965 /*************************************************************************
968 HRESULT WINAPI
D3DXCreateMesh(DWORD numfaces
, DWORD numvertices
, DWORD options
, CONST D3DVERTEXELEMENT9
*declaration
,
969 LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*mesh
)
973 IDirect3DVertexDeclaration9
*vertex_declaration
;
974 IDirect3DVertexBuffer9
*vertex_buffer
;
975 IDirect3DIndexBuffer9
*index_buffer
;
976 ID3DXMeshImpl
*object
;
978 TRACE("(%d, %d, %d, %p, %p, %p)\n", numfaces
, numvertices
, options
, declaration
, device
, mesh
);
980 if (numfaces
== 0 || numvertices
== 0 || declaration
== NULL
|| device
== NULL
|| mesh
== NULL
)
982 return D3DERR_INVALIDCALL
;
985 hr
= D3DXFVFFromDeclarator(declaration
, &fvf
);
991 /* Create vertex declaration */
992 hr
= IDirect3DDevice9_CreateVertexDeclaration(device
,
994 &vertex_declaration
);
997 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexDeclaration.\n",hr
);
1001 /* Create vertex buffer */
1002 hr
= IDirect3DDevice9_CreateVertexBuffer(device
,
1003 numvertices
* D3DXGetDeclVertexSize(declaration
, declaration
[0].Stream
),
1011 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexBuffer.\n",hr
);
1012 IDirect3DVertexDeclaration9_Release(vertex_declaration
);
1016 /* Create index buffer */
1017 hr
= IDirect3DDevice9_CreateIndexBuffer(device
,
1018 numfaces
* 6, /* 3 vertices per triangle, 2 triangles per face */
1026 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexBuffer.\n",hr
);
1027 IDirect3DVertexBuffer9_Release(vertex_buffer
);
1028 IDirect3DVertexDeclaration9_Release(vertex_declaration
);
1032 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ID3DXMeshImpl
));
1035 IDirect3DIndexBuffer9_Release(index_buffer
);
1036 IDirect3DVertexBuffer9_Release(vertex_buffer
);
1037 IDirect3DVertexDeclaration9_Release(vertex_declaration
);
1039 return E_OUTOFMEMORY
;
1041 object
->ID3DXMesh_iface
.lpVtbl
= &D3DXMesh_Vtbl
;
1044 object
->numfaces
= numfaces
;
1045 object
->numvertices
= numvertices
;
1046 object
->options
= options
;
1048 object
->device
= device
;
1049 IDirect3DDevice9_AddRef(device
);
1051 object
->vertex_declaration
= vertex_declaration
;
1052 object
->vertex_buffer
= vertex_buffer
;
1053 object
->index_buffer
= index_buffer
;
1055 *mesh
= &object
->ID3DXMesh_iface
;
1060 /*************************************************************************
1063 HRESULT WINAPI
D3DXCreateMeshFVF(DWORD numfaces
, DWORD numvertices
, DWORD options
, DWORD fvf
,
1064 LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*mesh
)
1067 D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
];
1069 TRACE("(%u, %u, %u, %u, %p, %p)\n", numfaces
, numvertices
, options
, fvf
, device
, mesh
);
1071 hr
= D3DXDeclaratorFromFVF(fvf
, declaration
);
1072 if (FAILED(hr
)) return hr
;
1074 return D3DXCreateMesh(numfaces
, numvertices
, options
, declaration
, device
, mesh
);
1077 HRESULT WINAPI
D3DXCreateBox(LPDIRECT3DDEVICE9 device
, FLOAT width
, FLOAT height
,
1078 FLOAT depth
, LPD3DXMESH
* mesh
, LPD3DXBUFFER
* adjacency
)
1080 FIXME("(%p, %f, %f, %f, %p, %p): stub\n", device
, width
, height
, depth
, mesh
, adjacency
);
1087 D3DXVECTOR3 position
;
1091 typedef WORD face
[3];
1099 static void free_sincos_table(struct sincos_table
*sincos_table
)
1101 HeapFree(GetProcessHeap(), 0, sincos_table
->cos
);
1102 HeapFree(GetProcessHeap(), 0, sincos_table
->sin
);
1105 /* pre compute sine and cosine tables; caller must free */
1106 static BOOL
compute_sincos_table(struct sincos_table
*sincos_table
, float angle_start
, float angle_step
, int n
)
1111 sincos_table
->sin
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(*sincos_table
->sin
));
1112 if (!sincos_table
->sin
)
1116 sincos_table
->cos
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(*sincos_table
->cos
));
1117 if (!sincos_table
->cos
)
1119 HeapFree(GetProcessHeap(), 0, sincos_table
->sin
);
1123 angle
= angle_start
;
1124 for (i
= 0; i
< n
; i
++)
1126 sincos_table
->sin
[i
] = sin(angle
);
1127 sincos_table
->cos
[i
] = cos(angle
);
1128 angle
+= angle_step
;
1134 static WORD
vertex_index(UINT slices
, int slice
, int stack
)
1136 return stack
*slices
+slice
+1;
1139 HRESULT WINAPI
D3DXCreateSphere(LPDIRECT3DDEVICE9 device
, FLOAT radius
, UINT slices
,
1140 UINT stacks
, LPD3DXMESH
* mesh
, LPD3DXBUFFER
* adjacency
)
1142 DWORD number_of_vertices
, number_of_faces
;
1145 struct vertex
*vertices
;
1147 float phi_step
, phi_start
;
1148 struct sincos_table phi
;
1149 float theta_step
, theta
, sin_theta
, cos_theta
;
1153 TRACE("(%p, %f, %u, %u, %p, %p)\n", device
, radius
, slices
, stacks
, mesh
, adjacency
);
1155 if (!device
|| radius
< 0.0f
|| slices
< 2 || stacks
< 2 || !mesh
)
1157 return D3DERR_INVALIDCALL
;
1162 FIXME("Case of adjacency != NULL not implemented.\n");
1166 number_of_vertices
= 2 + slices
* (stacks
-1);
1167 number_of_faces
= 2 * slices
+ (stacks
- 2) * (2 * slices
);
1169 hr
= D3DXCreateMeshFVF(number_of_faces
, number_of_vertices
, D3DXMESH_MANAGED
,
1170 D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &sphere
);
1176 hr
= sphere
->lpVtbl
->LockVertexBuffer(sphere
, D3DLOCK_DISCARD
, (LPVOID
*)&vertices
);
1179 sphere
->lpVtbl
->Release(sphere
);
1183 hr
= sphere
->lpVtbl
->LockIndexBuffer(sphere
, D3DLOCK_DISCARD
, (LPVOID
*)&faces
);
1186 sphere
->lpVtbl
->UnlockVertexBuffer(sphere
);
1187 sphere
->lpVtbl
->Release(sphere
);
1191 /* phi = angle on xz plane wrt z axis */
1192 phi_step
= -2 * M_PI
/ slices
;
1193 phi_start
= M_PI
/ 2;
1195 if (!compute_sincos_table(&phi
, phi_start
, phi_step
, slices
))
1197 sphere
->lpVtbl
->UnlockIndexBuffer(sphere
);
1198 sphere
->lpVtbl
->UnlockVertexBuffer(sphere
);
1199 sphere
->lpVtbl
->Release(sphere
);
1200 return E_OUTOFMEMORY
;
1203 /* theta = angle on xy plane wrt x axis */
1204 theta_step
= M_PI
/ stacks
;
1211 vertices
[vertex
].normal
.x
= 0.0f
;
1212 vertices
[vertex
].normal
.y
= 0.0f
;
1213 vertices
[vertex
].normal
.z
= 1.0f
;
1214 vertices
[vertex
].position
.x
= 0.0f
;
1215 vertices
[vertex
].position
.y
= 0.0f
;
1216 vertices
[vertex
].position
.z
= radius
;
1219 for (stack
= 0; stack
< stacks
- 1; stack
++)
1221 sin_theta
= sin(theta
);
1222 cos_theta
= cos(theta
);
1224 for (slice
= 0; slice
< slices
; slice
++)
1226 vertices
[vertex
].normal
.x
= sin_theta
* phi
.cos
[slice
];
1227 vertices
[vertex
].normal
.y
= sin_theta
* phi
.sin
[slice
];
1228 vertices
[vertex
].normal
.z
= cos_theta
;
1229 vertices
[vertex
].position
.x
= radius
* sin_theta
* phi
.cos
[slice
];
1230 vertices
[vertex
].position
.y
= radius
* sin_theta
* phi
.sin
[slice
];
1231 vertices
[vertex
].position
.z
= radius
* cos_theta
;
1238 /* top stack is triangle fan */
1240 faces
[face
][1] = slice
+ 1;
1241 faces
[face
][2] = slice
;
1246 /* stacks in between top and bottom are quad strips */
1247 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1248 faces
[face
][1] = vertex_index(slices
, slice
, stack
-1);
1249 faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1252 faces
[face
][0] = vertex_index(slices
, slice
, stack
-1);
1253 faces
[face
][1] = vertex_index(slices
, slice
, stack
);
1254 faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1260 theta
+= theta_step
;
1266 faces
[face
][2] = slice
;
1271 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1272 faces
[face
][1] = vertex_index(slices
, 0, stack
-1);
1273 faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1276 faces
[face
][0] = vertex_index(slices
, 0, stack
-1);
1277 faces
[face
][1] = vertex_index(slices
, 0, stack
);
1278 faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1283 vertices
[vertex
].position
.x
= 0.0f
;
1284 vertices
[vertex
].position
.y
= 0.0f
;
1285 vertices
[vertex
].position
.z
= -radius
;
1286 vertices
[vertex
].normal
.x
= 0.0f
;
1287 vertices
[vertex
].normal
.y
= 0.0f
;
1288 vertices
[vertex
].normal
.z
= -1.0f
;
1290 /* bottom stack is triangle fan */
1291 for (slice
= 1; slice
< slices
; slice
++)
1293 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1294 faces
[face
][1] = vertex_index(slices
, slice
, stack
-1);
1295 faces
[face
][2] = vertex
;
1299 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1300 faces
[face
][1] = vertex_index(slices
, 0, stack
-1);
1301 faces
[face
][2] = vertex
;
1303 free_sincos_table(&phi
);
1304 sphere
->lpVtbl
->UnlockIndexBuffer(sphere
);
1305 sphere
->lpVtbl
->UnlockVertexBuffer(sphere
);
1311 HRESULT WINAPI
D3DXCreateCylinder(LPDIRECT3DDEVICE9 device
, FLOAT radius1
, FLOAT radius2
, FLOAT length
, UINT slices
,
1312 UINT stacks
, LPD3DXMESH
* mesh
, LPD3DXBUFFER
* adjacency
)
1314 DWORD number_of_vertices
, number_of_faces
;
1316 ID3DXMesh
*cylinder
;
1317 struct vertex
*vertices
;
1319 float theta_step
, theta_start
;
1320 struct sincos_table theta
;
1321 float delta_radius
, radius
, radius_step
;
1322 float z
, z_step
, z_normal
;
1326 TRACE("(%p, %f, %f, %f, %u, %u, %p, %p)\n", device
, radius1
, radius2
, length
, slices
, stacks
, mesh
, adjacency
);
1328 if (device
== NULL
|| radius1
< 0.0f
|| radius2
< 0.0f
|| length
< 0.0f
|| slices
< 2 || stacks
< 1 || mesh
== NULL
)
1330 return D3DERR_INVALIDCALL
;
1335 FIXME("Case of adjacency != NULL not implemented.\n");
1339 number_of_vertices
= 2 + (slices
* (3 + stacks
));
1340 number_of_faces
= 2 * slices
+ stacks
* (2 * slices
);
1342 hr
= D3DXCreateMeshFVF(number_of_faces
, number_of_vertices
, D3DXMESH_MANAGED
,
1343 D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &cylinder
);
1349 hr
= cylinder
->lpVtbl
->LockVertexBuffer(cylinder
, D3DLOCK_DISCARD
, (LPVOID
*)&vertices
);
1352 cylinder
->lpVtbl
->Release(cylinder
);
1356 hr
= cylinder
->lpVtbl
->LockIndexBuffer(cylinder
, D3DLOCK_DISCARD
, (LPVOID
*)&faces
);
1359 cylinder
->lpVtbl
->UnlockVertexBuffer(cylinder
);
1360 cylinder
->lpVtbl
->Release(cylinder
);
1364 /* theta = angle on xy plane wrt x axis */
1365 theta_step
= -2 * M_PI
/ slices
;
1366 theta_start
= M_PI
/ 2;
1368 if (!compute_sincos_table(&theta
, theta_start
, theta_step
, slices
))
1370 cylinder
->lpVtbl
->UnlockIndexBuffer(cylinder
);
1371 cylinder
->lpVtbl
->UnlockVertexBuffer(cylinder
);
1372 cylinder
->lpVtbl
->Release(cylinder
);
1373 return E_OUTOFMEMORY
;
1380 delta_radius
= radius1
- radius2
;
1382 radius_step
= delta_radius
/ stacks
;
1385 z_step
= length
/ stacks
;
1386 z_normal
= delta_radius
/ length
;
1387 if (isnan(z_normal
))
1392 vertices
[vertex
].normal
.x
= 0.0f
;
1393 vertices
[vertex
].normal
.y
= 0.0f
;
1394 vertices
[vertex
].normal
.z
= -1.0f
;
1395 vertices
[vertex
].position
.x
= 0.0f
;
1396 vertices
[vertex
].position
.y
= 0.0f
;
1397 vertices
[vertex
++].position
.z
= z
;
1399 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1401 vertices
[vertex
].normal
.x
= 0.0f
;
1402 vertices
[vertex
].normal
.y
= 0.0f
;
1403 vertices
[vertex
].normal
.z
= -1.0f
;
1404 vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1405 vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1406 vertices
[vertex
].position
.z
= z
;
1411 faces
[face
][1] = slice
;
1412 faces
[face
++][2] = slice
+ 1;
1417 faces
[face
][1] = slice
;
1418 faces
[face
++][2] = 1;
1420 for (stack
= 1; stack
<= stacks
+1; stack
++)
1422 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1424 vertices
[vertex
].normal
.x
= theta
.cos
[slice
];
1425 vertices
[vertex
].normal
.y
= theta
.sin
[slice
];
1426 vertices
[vertex
].normal
.z
= z_normal
;
1427 D3DXVec3Normalize(&vertices
[vertex
].normal
, &vertices
[vertex
].normal
);
1428 vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1429 vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1430 vertices
[vertex
].position
.z
= z
;
1432 if (stack
> 1 && slice
> 0)
1434 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1435 faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1436 faces
[face
++][2] = vertex_index(slices
, slice
, stack
-1);
1438 faces
[face
][0] = vertex_index(slices
, slice
, stack
-1);
1439 faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1440 faces
[face
++][2] = vertex_index(slices
, slice
, stack
);
1446 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1447 faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1448 faces
[face
++][2] = vertex_index(slices
, 0, stack
-1);
1450 faces
[face
][0] = vertex_index(slices
, 0, stack
-1);
1451 faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1452 faces
[face
++][2] = vertex_index(slices
, 0, stack
);
1455 if (stack
< stacks
+ 1)
1458 radius
-= radius_step
;
1462 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1464 vertices
[vertex
].normal
.x
= 0.0f
;
1465 vertices
[vertex
].normal
.y
= 0.0f
;
1466 vertices
[vertex
].normal
.z
= 1.0f
;
1467 vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1468 vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1469 vertices
[vertex
].position
.z
= z
;
1473 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
);
1474 faces
[face
][1] = number_of_vertices
- 1;
1475 faces
[face
++][2] = vertex_index(slices
, slice
, stack
);
1479 vertices
[vertex
].position
.x
= 0.0f
;
1480 vertices
[vertex
].position
.y
= 0.0f
;
1481 vertices
[vertex
].position
.z
= z
;
1482 vertices
[vertex
].normal
.x
= 0.0f
;
1483 vertices
[vertex
].normal
.y
= 0.0f
;
1484 vertices
[vertex
].normal
.z
= 1.0f
;
1486 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
);
1487 faces
[face
][1] = number_of_vertices
- 1;
1488 faces
[face
][2] = vertex_index(slices
, 0, stack
);
1490 free_sincos_table(&theta
);
1491 cylinder
->lpVtbl
->UnlockIndexBuffer(cylinder
);
1492 cylinder
->lpVtbl
->UnlockVertexBuffer(cylinder
);
1498 HRESULT WINAPI
D3DXCreateTeapot(LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*mesh
, LPD3DXBUFFER
* adjacency
)
1500 FIXME("(%p, %p, %p): stub\n", device
, mesh
, adjacency
);