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 /*** IUnknown methods ***/
37 static HRESULT WINAPI
ID3DXMeshImpl_QueryInterface(ID3DXMesh
*iface
, REFIID riid
, LPVOID
*object
)
39 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
41 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), object
);
43 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
44 IsEqualGUID(riid
, &IID_ID3DXBaseMesh
) ||
45 IsEqualGUID(riid
, &IID_ID3DXMesh
))
47 iface
->lpVtbl
->AddRef(iface
);
52 WARN("Interface %s not found.\n", debugstr_guid(riid
));
57 static ULONG WINAPI
ID3DXMeshImpl_AddRef(ID3DXMesh
*iface
)
59 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
61 TRACE("(%p)->(): AddRef from %d\n", This
, This
->ref
);
63 return InterlockedIncrement(&This
->ref
);
66 static ULONG WINAPI
ID3DXMeshImpl_Release(ID3DXMesh
*iface
)
68 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
69 ULONG ref
= InterlockedDecrement(&This
->ref
);
71 TRACE("(%p)->(): Release from %d\n", This
, ref
+ 1);
75 IDirect3DIndexBuffer9_Release(This
->index_buffer
);
76 IDirect3DVertexBuffer9_Release(This
->vertex_buffer
);
77 IDirect3DVertexDeclaration9_Release(This
->vertex_declaration
);
78 IDirect3DDevice9_Release(This
->device
);
79 HeapFree(GetProcessHeap(), 0, This
);
85 /*** ID3DXBaseMesh ***/
86 static HRESULT WINAPI
ID3DXMeshImpl_DrawSubset(ID3DXMesh
*iface
, DWORD attrib_id
)
88 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
90 FIXME("(%p)->(%u): stub\n", This
, attrib_id
);
95 static DWORD WINAPI
ID3DXMeshImpl_GetNumFaces(ID3DXMesh
*iface
)
97 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
99 TRACE("(%p)\n", This
);
101 return This
->numfaces
;
104 static DWORD WINAPI
ID3DXMeshImpl_GetNumVertices(ID3DXMesh
*iface
)
106 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
108 TRACE("(%p)\n", This
);
110 return This
->numvertices
;
113 static DWORD WINAPI
ID3DXMeshImpl_GetFVF(ID3DXMesh
*iface
)
115 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
117 TRACE("(%p)\n", This
);
122 static HRESULT WINAPI
ID3DXMeshImpl_GetDeclaration(ID3DXMesh
*iface
, D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
])
124 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
127 TRACE("(%p)\n", This
);
129 if (declaration
== NULL
) return D3DERR_INVALIDCALL
;
131 return IDirect3DVertexDeclaration9_GetDeclaration(This
->vertex_declaration
,
136 static DWORD WINAPI
ID3DXMeshImpl_GetNumBytesPerVertex(ID3DXMesh
*iface
)
138 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
140 FIXME("(%p): stub\n", This
);
142 return 0; /* arbitrary since we cannot return E_NOTIMPL */
145 static DWORD WINAPI
ID3DXMeshImpl_GetOptions(ID3DXMesh
*iface
)
147 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
149 TRACE("(%p)\n", This
);
151 return This
->options
;
154 static HRESULT WINAPI
ID3DXMeshImpl_GetDevice(ID3DXMesh
*iface
, LPDIRECT3DDEVICE9
*device
)
156 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
158 TRACE("(%p)->(%p)\n", This
, device
);
160 if (device
== NULL
) return D3DERR_INVALIDCALL
;
161 *device
= This
->device
;
162 IDirect3DDevice9_AddRef(This
->device
);
167 static HRESULT WINAPI
ID3DXMeshImpl_CloneMeshFVF(ID3DXMesh
*iface
, DWORD options
, DWORD fvf
, LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*clone_mesh
)
169 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
171 FIXME("(%p)->(%u,%u,%p,%p): stub\n", This
, options
, fvf
, device
, clone_mesh
);
176 static HRESULT WINAPI
ID3DXMeshImpl_CloneMesh(ID3DXMesh
*iface
, DWORD options
, CONST D3DVERTEXELEMENT9
*declaration
, LPDIRECT3DDEVICE9 device
,
177 LPD3DXMESH
*clone_mesh
)
179 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
181 FIXME("(%p)->(%u,%p,%p,%p): stub\n", This
, options
, declaration
, device
, clone_mesh
);
186 static HRESULT WINAPI
ID3DXMeshImpl_GetVertexBuffer(ID3DXMesh
*iface
, LPDIRECT3DVERTEXBUFFER9
*vertex_buffer
)
188 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
190 TRACE("(%p)->(%p)\n", This
, vertex_buffer
);
192 if (vertex_buffer
== NULL
) return D3DERR_INVALIDCALL
;
193 *vertex_buffer
= This
->vertex_buffer
;
194 IDirect3DVertexBuffer9_AddRef(This
->vertex_buffer
);
199 static HRESULT WINAPI
ID3DXMeshImpl_GetIndexBuffer(ID3DXMesh
*iface
, LPDIRECT3DINDEXBUFFER9
*index_buffer
)
201 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
203 TRACE("(%p)->(%p)\n", This
, index_buffer
);
205 if (index_buffer
== NULL
) return D3DERR_INVALIDCALL
;
206 *index_buffer
= This
->index_buffer
;
207 IDirect3DIndexBuffer9_AddRef(This
->index_buffer
);
212 static HRESULT WINAPI
ID3DXMeshImpl_LockVertexBuffer(ID3DXMesh
*iface
, DWORD flags
, LPVOID
*data
)
214 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
216 TRACE("(%p)->(%u,%p)\n", This
, flags
, data
);
218 return IDirect3DVertexBuffer9_Lock(This
->vertex_buffer
, 0, 0, data
, flags
);
221 static HRESULT WINAPI
ID3DXMeshImpl_UnlockVertexBuffer(ID3DXMesh
*iface
)
223 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
225 TRACE("(%p)\n", This
);
227 return IDirect3DVertexBuffer9_Unlock(This
->vertex_buffer
);
230 static HRESULT WINAPI
ID3DXMeshImpl_LockIndexBuffer(ID3DXMesh
*iface
, DWORD flags
, LPVOID
*data
)
232 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
234 TRACE("(%p)->(%u,%p)\n", This
, flags
, data
);
236 return IDirect3DIndexBuffer9_Lock(This
->index_buffer
, 0, 0, data
, flags
);
239 static HRESULT WINAPI
ID3DXMeshImpl_UnlockIndexBuffer(ID3DXMesh
*iface
)
241 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
243 TRACE("(%p)\n", This
);
245 return IDirect3DIndexBuffer9_Unlock(This
->index_buffer
);
248 static HRESULT WINAPI
ID3DXMeshImpl_GetAttributeTable(ID3DXMesh
*iface
, D3DXATTRIBUTERANGE
*attrib_table
, DWORD
*attrib_table_size
)
250 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
252 FIXME("(%p)->(%p,%p): stub\n", This
, attrib_table
, attrib_table_size
);
257 static HRESULT WINAPI
ID3DXMeshImpl_ConvertPointRepsToAdjacency(ID3DXMesh
*iface
, CONST DWORD
*point_reps
, DWORD
*adjacency
)
259 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
261 FIXME("(%p)->(%p,%p): stub\n", This
, point_reps
, adjacency
);
266 static HRESULT WINAPI
ID3DXMeshImpl_ConvertAdjacencyToPointReps(ID3DXMesh
*iface
, CONST DWORD
*adjacency
, DWORD
*point_reps
)
268 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
270 FIXME("(%p)->(%p,%p): stub\n", This
, adjacency
, point_reps
);
275 static HRESULT WINAPI
ID3DXMeshImpl_GenerateAdjacency(ID3DXMesh
*iface
, FLOAT epsilon
, DWORD
*adjacency
)
277 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
279 FIXME("(%p)->(%f,%p): stub\n", This
, epsilon
, adjacency
);
284 static HRESULT WINAPI
ID3DXMeshImpl_UpdateSemantics(ID3DXMesh
*iface
, D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
])
286 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
288 FIXME("(%p)->(%p): stub\n", This
, declaration
);
294 static HRESULT WINAPI
ID3DXMeshImpl_LockAttributeBuffer(ID3DXMesh
*iface
, DWORD flags
, DWORD
**data
)
296 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
298 FIXME("(%p)->(%u,%p): stub\n", This
, flags
, data
);
303 static HRESULT WINAPI
ID3DXMeshImpl_UnlockAttributeBuffer(ID3DXMesh
*iface
)
305 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
307 FIXME("(%p): stub\n", This
);
312 static HRESULT WINAPI
ID3DXMeshImpl_Optimize(ID3DXMesh
*iface
, DWORD flags
, CONST DWORD
*adjacency_in
, DWORD
*adjacency_out
,
313 DWORD
*face_remap
, LPD3DXBUFFER
*vertex_remap
, LPD3DXMESH
*opt_mesh
)
315 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
317 FIXME("(%p)->(%u,%p,%p,%p,%p,%p): stub\n", This
, flags
, adjacency_in
, adjacency_out
, face_remap
, vertex_remap
, opt_mesh
);
322 static HRESULT WINAPI
ID3DXMeshImpl_OptimizeInplace(ID3DXMesh
*iface
, DWORD flags
, CONST DWORD
*adjacency_in
, DWORD
*adjacency_out
,
323 DWORD
*face_remap
, LPD3DXBUFFER
*vertex_remap
)
325 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
327 FIXME("(%p)->(%u,%p,%p,%p,%p): stub\n", This
, flags
, adjacency_in
, adjacency_out
, face_remap
, vertex_remap
);
332 static HRESULT WINAPI
ID3DXMeshImpl_SetAttributeTable(ID3DXMesh
*iface
, CONST D3DXATTRIBUTERANGE
*attrib_table
, DWORD attrib_table_size
)
334 ID3DXMeshImpl
*This
= (ID3DXMeshImpl
*)iface
;
336 FIXME("(%p)->(%p,%u): stub\n", This
, attrib_table
, attrib_table_size
);
341 static const struct ID3DXMeshVtbl D3DXMesh_Vtbl
=
343 /*** IUnknown methods ***/
344 ID3DXMeshImpl_QueryInterface
,
345 ID3DXMeshImpl_AddRef
,
346 ID3DXMeshImpl_Release
,
347 /*** ID3DXBaseMesh ***/
348 ID3DXMeshImpl_DrawSubset
,
349 ID3DXMeshImpl_GetNumFaces
,
350 ID3DXMeshImpl_GetNumVertices
,
351 ID3DXMeshImpl_GetFVF
,
352 ID3DXMeshImpl_GetDeclaration
,
353 ID3DXMeshImpl_GetNumBytesPerVertex
,
354 ID3DXMeshImpl_GetOptions
,
355 ID3DXMeshImpl_GetDevice
,
356 ID3DXMeshImpl_CloneMeshFVF
,
357 ID3DXMeshImpl_CloneMesh
,
358 ID3DXMeshImpl_GetVertexBuffer
,
359 ID3DXMeshImpl_GetIndexBuffer
,
360 ID3DXMeshImpl_LockVertexBuffer
,
361 ID3DXMeshImpl_UnlockVertexBuffer
,
362 ID3DXMeshImpl_LockIndexBuffer
,
363 ID3DXMeshImpl_UnlockIndexBuffer
,
364 ID3DXMeshImpl_GetAttributeTable
,
365 ID3DXMeshImpl_ConvertPointRepsToAdjacency
,
366 ID3DXMeshImpl_ConvertAdjacencyToPointReps
,
367 ID3DXMeshImpl_GenerateAdjacency
,
368 ID3DXMeshImpl_UpdateSemantics
,
370 ID3DXMeshImpl_LockAttributeBuffer
,
371 ID3DXMeshImpl_UnlockAttributeBuffer
,
372 ID3DXMeshImpl_Optimize
,
373 ID3DXMeshImpl_OptimizeInplace
,
374 ID3DXMeshImpl_SetAttributeTable
377 /*************************************************************************
380 BOOL WINAPI
D3DXBoxBoundProbe(CONST D3DXVECTOR3
*pmin
, CONST D3DXVECTOR3
*pmax
, CONST D3DXVECTOR3
*prayposition
, CONST D3DXVECTOR3
*praydirection
)
382 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
383 Amy Williams University of Utah
384 Steve Barrus University of Utah
385 R. Keith Morley University of Utah
386 Peter Shirley University of Utah
388 International Conference on Computer Graphics and Interactive Techniques archive
389 ACM SIGGRAPH 2005 Courses
390 Los Angeles, California
392 This algorithm is free of patents or of copyrights, as confirmed by Peter Shirley himself.
394 Algorithm: Consider the box as the intersection of three slabs. Clip the ray
395 against each slab, if there's anything left of the ray after we're
396 done we've got an intersection of the ray with the box.
400 FLOAT div
, tmin
, tmax
, tymin
, tymax
, tzmin
, tzmax
;
402 div
= 1.0f
/ praydirection
->x
;
405 tmin
= ( pmin
->x
- prayposition
->x
) * div
;
406 tmax
= ( pmax
->x
- prayposition
->x
) * div
;
410 tmin
= ( pmax
->x
- prayposition
->x
) * div
;
411 tmax
= ( pmin
->x
- prayposition
->x
) * div
;
414 if ( tmax
< 0.0f
) return FALSE
;
416 div
= 1.0f
/ praydirection
->y
;
419 tymin
= ( pmin
->y
- prayposition
->y
) * div
;
420 tymax
= ( pmax
->y
- prayposition
->y
) * div
;
424 tymin
= ( pmax
->y
- prayposition
->y
) * div
;
425 tymax
= ( pmin
->y
- prayposition
->y
) * div
;
428 if ( ( tymax
< 0.0f
) || ( tmin
> tymax
) || ( tymin
> tmax
) ) return FALSE
;
430 if ( tymin
> tmin
) tmin
= tymin
;
431 if ( tymax
< tmax
) tmax
= tymax
;
433 div
= 1.0f
/ praydirection
->z
;
436 tzmin
= ( pmin
->z
- prayposition
->z
) * div
;
437 tzmax
= ( pmax
->z
- prayposition
->z
) * div
;
441 tzmin
= ( pmax
->z
- prayposition
->z
) * div
;
442 tzmax
= ( pmin
->z
- prayposition
->z
) * div
;
445 if ( (tzmax
< 0.0f
) || ( tmin
> tzmax
) || ( tzmin
> tmax
) ) return FALSE
;
450 /*************************************************************************
451 * D3DXComputeBoundingBox
453 HRESULT WINAPI
D3DXComputeBoundingBox(CONST D3DXVECTOR3
*pfirstposition
, DWORD numvertices
, DWORD dwstride
, D3DXVECTOR3
*pmin
, D3DXVECTOR3
*pmax
)
458 if( !pfirstposition
|| !pmin
|| !pmax
) return D3DERR_INVALIDCALL
;
460 *pmin
= *pfirstposition
;
463 for(i
=0; i
<numvertices
; i
++)
465 vec
= *( (const D3DXVECTOR3
*)((const char*)pfirstposition
+ dwstride
* i
) );
467 if ( vec
.x
< pmin
->x
) pmin
->x
= vec
.x
;
468 if ( vec
.x
> pmax
->x
) pmax
->x
= vec
.x
;
470 if ( vec
.y
< pmin
->y
) pmin
->y
= vec
.y
;
471 if ( vec
.y
> pmax
->y
) pmax
->y
= vec
.y
;
473 if ( vec
.z
< pmin
->z
) pmin
->z
= vec
.z
;
474 if ( vec
.z
> pmax
->z
) pmax
->z
= vec
.z
;
480 /*************************************************************************
481 * D3DXComputeBoundingSphere
483 HRESULT WINAPI
D3DXComputeBoundingSphere(CONST D3DXVECTOR3
* pfirstposition
, DWORD numvertices
, DWORD dwstride
, D3DXVECTOR3
*pcenter
, FLOAT
*pradius
)
485 D3DXVECTOR3 temp
, temp1
;
489 if( !pfirstposition
|| !pcenter
|| !pradius
) return D3DERR_INVALIDCALL
;
498 for(i
=0; i
<numvertices
; i
++)
500 D3DXVec3Add(&temp1
, &temp
, (const D3DXVECTOR3
*)((const char*)pfirstposition
+ dwstride
* i
));
504 D3DXVec3Scale(pcenter
, &temp
, 1.0f
/((FLOAT
)numvertices
));
506 for(i
=0; i
<numvertices
; i
++)
508 d
= D3DXVec3Length(D3DXVec3Subtract(&temp
, (const D3DXVECTOR3
*)((const char*)pfirstposition
+ dwstride
* i
), pcenter
));
509 if ( d
> *pradius
) *pradius
= d
;
514 static const UINT d3dx_decltype_size
[D3DDECLTYPE_UNUSED
] =
516 /* D3DDECLTYPE_FLOAT1 */ 1 * 4,
517 /* D3DDECLTYPE_FLOAT2 */ 2 * 4,
518 /* D3DDECLTYPE_FLOAT3 */ 3 * 4,
519 /* D3DDECLTYPE_FLOAT4 */ 4 * 4,
520 /* D3DDECLTYPE_D3DCOLOR */ 4 * 1,
521 /* D3DDECLTYPE_UBYTE4 */ 4 * 1,
522 /* D3DDECLTYPE_SHORT2 */ 2 * 2,
523 /* D3DDECLTYPE_SHORT4 */ 4 * 2,
524 /* D3DDECLTYPE_UBYTE4N */ 4 * 1,
525 /* D3DDECLTYPE_SHORT2N */ 2 * 2,
526 /* D3DDECLTYPE_SHORT4N */ 4 * 2,
527 /* D3DDECLTYPE_USHORT2N */ 2 * 2,
528 /* D3DDECLTYPE_USHORT4N */ 4 * 2,
529 /* D3DDECLTYPE_UDEC3 */ 4, /* 3 * 10 bits + 2 padding */
530 /* D3DDECLTYPE_DEC3N */ 4,
531 /* D3DDECLTYPE_FLOAT16_2 */ 2 * 2,
532 /* D3DDECLTYPE_FLOAT16_4 */ 4 * 2,
535 static void append_decl_element(D3DVERTEXELEMENT9
*declaration
, UINT
*idx
, UINT
*offset
,
536 D3DDECLTYPE type
, D3DDECLUSAGE usage
, UINT usage_idx
)
538 declaration
[*idx
].Stream
= 0;
539 declaration
[*idx
].Offset
= *offset
;
540 declaration
[*idx
].Type
= type
;
541 declaration
[*idx
].Method
= D3DDECLMETHOD_DEFAULT
;
542 declaration
[*idx
].Usage
= usage
;
543 declaration
[*idx
].UsageIndex
= usage_idx
;
545 *offset
+= d3dx_decltype_size
[type
];
549 /*************************************************************************
550 * D3DXDeclaratorFromFVF
552 HRESULT WINAPI
D3DXDeclaratorFromFVF(DWORD fvf
, D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
])
554 static const D3DVERTEXELEMENT9 end_element
= D3DDECL_END();
555 DWORD tex_count
= (fvf
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
556 unsigned int offset
= 0;
557 unsigned int idx
= 0;
560 TRACE("fvf %#x, declaration %p.\n", fvf
, declaration
);
562 if (fvf
& (D3DFVF_RESERVED0
| D3DFVF_RESERVED2
)) return D3DERR_INVALIDCALL
;
564 if (fvf
& D3DFVF_POSITION_MASK
)
566 BOOL has_blend
= (fvf
& D3DFVF_XYZB5
) >= D3DFVF_XYZB1
;
567 DWORD blend_count
= 1 + (((fvf
& D3DFVF_XYZB5
) - D3DFVF_XYZB1
) >> 1);
568 BOOL has_blend_idx
= (fvf
& D3DFVF_LASTBETA_D3DCOLOR
) || (fvf
& D3DFVF_LASTBETA_UBYTE4
);
570 if (has_blend_idx
) --blend_count
;
572 if ((fvf
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZW
573 || (has_blend
&& blend_count
> 4))
574 return D3DERR_INVALIDCALL
;
576 if ((fvf
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
)
577 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_POSITIONT
, 0);
579 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_POSITION
, 0);
588 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
591 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT2
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
594 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
597 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_BLENDWEIGHT
, 0);
600 ERR("Invalid blend count %u.\n", blend_count
);
606 if (fvf
& D3DFVF_LASTBETA_UBYTE4
)
607 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_UBYTE4
, D3DDECLUSAGE_BLENDINDICES
, 0);
608 else if (fvf
& D3DFVF_LASTBETA_D3DCOLOR
)
609 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_BLENDINDICES
, 0);
614 if (fvf
& D3DFVF_NORMAL
)
615 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_NORMAL
, 0);
616 if (fvf
& D3DFVF_PSIZE
)
617 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_PSIZE
, 0);
618 if (fvf
& D3DFVF_DIFFUSE
)
619 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_COLOR
, 0);
620 if (fvf
& D3DFVF_SPECULAR
)
621 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_D3DCOLOR
, D3DDECLUSAGE_COLOR
, 1);
623 for (i
= 0; i
< tex_count
; ++i
)
625 switch ((fvf
>> (16 + 2 * i
)) & 0x03)
627 case D3DFVF_TEXTUREFORMAT1
:
628 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT1
, D3DDECLUSAGE_TEXCOORD
, i
);
630 case D3DFVF_TEXTUREFORMAT2
:
631 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT2
, D3DDECLUSAGE_TEXCOORD
, i
);
633 case D3DFVF_TEXTUREFORMAT3
:
634 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT3
, D3DDECLUSAGE_TEXCOORD
, i
);
636 case D3DFVF_TEXTUREFORMAT4
:
637 append_decl_element(declaration
, &idx
, &offset
, D3DDECLTYPE_FLOAT4
, D3DDECLUSAGE_TEXCOORD
, i
);
642 declaration
[idx
] = end_element
;
647 /*************************************************************************
648 * D3DXFVFFromDeclarator
650 HRESULT WINAPI
D3DXFVFFromDeclarator(const D3DVERTEXELEMENT9
*declaration
, DWORD
*fvf
)
652 unsigned int i
= 0, texture
, offset
;
654 TRACE("(%p, %p)\n", declaration
, fvf
);
657 if (declaration
[0].Type
== D3DDECLTYPE_FLOAT3
&& declaration
[0].Usage
== D3DDECLUSAGE_POSITION
)
659 if ((declaration
[1].Type
== D3DDECLTYPE_FLOAT4
&& declaration
[1].Usage
== D3DDECLUSAGE_BLENDWEIGHT
&&
660 declaration
[1].UsageIndex
== 0) &&
661 (declaration
[2].Type
== D3DDECLTYPE_FLOAT1
&& declaration
[2].Usage
== D3DDECLUSAGE_BLENDINDICES
&&
662 declaration
[2].UsageIndex
== 0))
664 return D3DERR_INVALIDCALL
;
666 else if ((declaration
[1].Type
== D3DDECLTYPE_UBYTE4
|| declaration
[1].Type
== D3DDECLTYPE_D3DCOLOR
) &&
667 declaration
[1].Usage
== D3DDECLUSAGE_BLENDINDICES
&& declaration
[1].UsageIndex
== 0)
669 if (declaration
[1].Type
== D3DDECLTYPE_UBYTE4
)
671 *fvf
|= D3DFVF_XYZB1
| D3DFVF_LASTBETA_UBYTE4
;
675 *fvf
|= D3DFVF_XYZB1
| D3DFVF_LASTBETA_D3DCOLOR
;
679 else if (declaration
[1].Type
<= D3DDECLTYPE_FLOAT4
&& declaration
[1].Usage
== D3DDECLUSAGE_BLENDWEIGHT
&&
680 declaration
[1].UsageIndex
== 0)
682 if ((declaration
[2].Type
== D3DDECLTYPE_UBYTE4
|| declaration
[2].Type
== D3DDECLTYPE_D3DCOLOR
) &&
683 declaration
[2].Usage
== D3DDECLUSAGE_BLENDINDICES
&& declaration
[2].UsageIndex
== 0)
685 if (declaration
[2].Type
== D3DDECLTYPE_UBYTE4
)
687 *fvf
|= D3DFVF_LASTBETA_UBYTE4
;
691 *fvf
|= D3DFVF_LASTBETA_D3DCOLOR
;
693 switch (declaration
[1].Type
)
695 case D3DDECLTYPE_FLOAT1
: *fvf
|= D3DFVF_XYZB2
; break;
696 case D3DDECLTYPE_FLOAT2
: *fvf
|= D3DFVF_XYZB3
; break;
697 case D3DDECLTYPE_FLOAT3
: *fvf
|= D3DFVF_XYZB4
; break;
698 case D3DDECLTYPE_FLOAT4
: *fvf
|= D3DFVF_XYZB5
; break;
704 switch (declaration
[1].Type
)
706 case D3DDECLTYPE_FLOAT1
: *fvf
|= D3DFVF_XYZB1
; break;
707 case D3DDECLTYPE_FLOAT2
: *fvf
|= D3DFVF_XYZB2
; break;
708 case D3DDECLTYPE_FLOAT3
: *fvf
|= D3DFVF_XYZB3
; break;
709 case D3DDECLTYPE_FLOAT4
: *fvf
|= D3DFVF_XYZB4
; break;
720 else if (declaration
[0].Type
== D3DDECLTYPE_FLOAT4
&& declaration
[0].Usage
== D3DDECLUSAGE_POSITIONT
&&
721 declaration
[0].UsageIndex
== 0)
723 *fvf
|= D3DFVF_XYZRHW
;
727 if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT3
&& declaration
[i
].Usage
== D3DDECLUSAGE_NORMAL
)
729 *fvf
|= D3DFVF_NORMAL
;
732 if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT1
&& declaration
[i
].Usage
== D3DDECLUSAGE_PSIZE
&&
733 declaration
[i
].UsageIndex
== 0)
735 *fvf
|= D3DFVF_PSIZE
;
738 if (declaration
[i
].Type
== D3DDECLTYPE_D3DCOLOR
&& declaration
[i
].Usage
== D3DDECLUSAGE_COLOR
&&
739 declaration
[i
].UsageIndex
== 0)
741 *fvf
|= D3DFVF_DIFFUSE
;
744 if (declaration
[i
].Type
== D3DDECLTYPE_D3DCOLOR
&& declaration
[i
].Usage
== D3DDECLUSAGE_COLOR
&&
745 declaration
[i
].UsageIndex
== 1)
747 *fvf
|= D3DFVF_SPECULAR
;
751 for (texture
= 0; texture
< D3DDP_MAXTEXCOORD
; i
++, texture
++)
753 if (declaration
[i
].Stream
== 0xFF)
757 else if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT1
&& declaration
[i
].Usage
== D3DDECLUSAGE_TEXCOORD
&&
758 declaration
[i
].UsageIndex
== texture
)
760 *fvf
|= D3DFVF_TEXCOORDSIZE1(declaration
[i
].UsageIndex
);
762 else if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT2
&& declaration
[i
].Usage
== D3DDECLUSAGE_TEXCOORD
&&
763 declaration
[i
].UsageIndex
== texture
)
765 *fvf
|= D3DFVF_TEXCOORDSIZE2(declaration
[i
].UsageIndex
);
767 else if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT3
&& declaration
[i
].Usage
== D3DDECLUSAGE_TEXCOORD
&&
768 declaration
[i
].UsageIndex
== texture
)
770 *fvf
|= D3DFVF_TEXCOORDSIZE3(declaration
[i
].UsageIndex
);
772 else if (declaration
[i
].Type
== D3DDECLTYPE_FLOAT4
&& declaration
[i
].Usage
== D3DDECLUSAGE_TEXCOORD
&&
773 declaration
[i
].UsageIndex
== texture
)
775 *fvf
|= D3DFVF_TEXCOORDSIZE4(declaration
[i
].UsageIndex
);
779 return D3DERR_INVALIDCALL
;
783 *fvf
|= (texture
<< D3DFVF_TEXCOUNT_SHIFT
);
785 for (offset
= 0, i
= 0; declaration
[i
].Stream
!= 0xFF;
786 offset
+= d3dx_decltype_size
[declaration
[i
].Type
], i
++)
788 if (declaration
[i
].Offset
!= offset
)
790 return D3DERR_INVALIDCALL
;
797 /*************************************************************************
798 * D3DXGetFVFVertexSize
800 static UINT
Get_TexCoord_Size_From_FVF(DWORD FVF
, int tex_num
)
802 return (((((FVF
) >> (16 + (2 * (tex_num
)))) + 1) & 0x03) + 1);
805 UINT WINAPI
D3DXGetFVFVertexSize(DWORD FVF
)
809 UINT numTextures
= (FVF
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
811 if (FVF
& D3DFVF_NORMAL
) size
+= sizeof(D3DXVECTOR3
);
812 if (FVF
& D3DFVF_DIFFUSE
) size
+= sizeof(DWORD
);
813 if (FVF
& D3DFVF_SPECULAR
) size
+= sizeof(DWORD
);
814 if (FVF
& D3DFVF_PSIZE
) size
+= sizeof(DWORD
);
816 switch (FVF
& D3DFVF_POSITION_MASK
)
818 case D3DFVF_XYZ
: size
+= sizeof(D3DXVECTOR3
); break;
819 case D3DFVF_XYZRHW
: size
+= 4 * sizeof(FLOAT
); break;
820 case D3DFVF_XYZB1
: size
+= 4 * sizeof(FLOAT
); break;
821 case D3DFVF_XYZB2
: size
+= 5 * sizeof(FLOAT
); break;
822 case D3DFVF_XYZB3
: size
+= 6 * sizeof(FLOAT
); break;
823 case D3DFVF_XYZB4
: size
+= 7 * sizeof(FLOAT
); break;
824 case D3DFVF_XYZB5
: size
+= 8 * sizeof(FLOAT
); break;
825 case D3DFVF_XYZW
: size
+= 4 * sizeof(FLOAT
); break;
828 for (i
= 0; i
< numTextures
; i
++)
830 size
+= Get_TexCoord_Size_From_FVF(FVF
, i
) * sizeof(FLOAT
);
836 /*************************************************************************
837 * D3DXGetDeclVertexSize
839 UINT WINAPI
D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9
*decl
, DWORD stream_idx
)
841 const D3DVERTEXELEMENT9
*element
;
844 TRACE("decl %p, stream_idx %u\n", decl
, stream_idx
);
848 for (element
= decl
; element
->Stream
!= 0xff; ++element
)
852 if (element
->Stream
!= stream_idx
) continue;
854 if (element
->Type
>= sizeof(d3dx_decltype_size
) / sizeof(*d3dx_decltype_size
))
856 FIXME("Unhandled element type %#x, size will be incorrect.\n", element
->Type
);
860 type_size
= d3dx_decltype_size
[element
->Type
];
861 if (element
->Offset
+ type_size
> size
) size
= element
->Offset
+ type_size
;
867 /*************************************************************************
870 UINT WINAPI
D3DXGetDeclLength(const D3DVERTEXELEMENT9
*decl
)
872 const D3DVERTEXELEMENT9
*element
;
874 TRACE("decl %p\n", decl
);
876 /* null decl results in exception on Windows XP */
878 for (element
= decl
; element
->Stream
!= 0xff; ++element
);
880 return element
- decl
;
883 /*************************************************************************
886 BOOL WINAPI
D3DXIntersectTri(CONST D3DXVECTOR3
*p0
, CONST D3DXVECTOR3
*p1
, CONST D3DXVECTOR3
*p2
, CONST D3DXVECTOR3
*praypos
, CONST D3DXVECTOR3
*praydir
, FLOAT
*pu
, FLOAT
*pv
, FLOAT
*pdist
)
891 m
.u
.m
[0][0] = p1
->x
- p0
->x
;
892 m
.u
.m
[1][0] = p2
->x
- p0
->x
;
893 m
.u
.m
[2][0] = -praydir
->x
;
895 m
.u
.m
[0][1] = p1
->y
- p0
->z
;
896 m
.u
.m
[1][1] = p2
->y
- p0
->z
;
897 m
.u
.m
[2][1] = -praydir
->y
;
899 m
.u
.m
[0][2] = p1
->z
- p0
->z
;
900 m
.u
.m
[1][2] = p2
->z
- p0
->z
;
901 m
.u
.m
[2][2] = -praydir
->z
;
908 vec
.x
= praypos
->x
- p0
->x
;
909 vec
.y
= praypos
->y
- p0
->y
;
910 vec
.z
= praypos
->z
- p0
->z
;
913 if ( D3DXMatrixInverse(&m
, NULL
, &m
) )
915 D3DXVec4Transform(&vec
, &vec
, &m
);
916 if ( (vec
.x
>= 0.0f
) && (vec
.y
>= 0.0f
) && (vec
.x
+ vec
.y
<= 1.0f
) && (vec
.z
>= 0.0f
) )
920 *pdist
= fabs( vec
.z
);
928 /*************************************************************************
929 * D3DXSphereBoundProbe
931 BOOL WINAPI
D3DXSphereBoundProbe(CONST D3DXVECTOR3
*pcenter
, FLOAT radius
, CONST D3DXVECTOR3
*prayposition
, CONST D3DXVECTOR3
*praydirection
)
933 D3DXVECTOR3 difference
;
936 a
= D3DXVec3LengthSq(praydirection
);
937 if (!D3DXVec3Subtract(&difference
, prayposition
, pcenter
)) return FALSE
;
938 b
= D3DXVec3Dot(&difference
, praydirection
);
939 c
= D3DXVec3LengthSq(&difference
) - radius
* radius
;
942 if ( ( d
<= 0.0f
) || ( sqrt(d
) <= b
) ) return FALSE
;
946 /*************************************************************************
949 HRESULT WINAPI
D3DXCreateMesh(DWORD numfaces
, DWORD numvertices
, DWORD options
, CONST D3DVERTEXELEMENT9
*declaration
,
950 LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*mesh
)
954 IDirect3DVertexDeclaration9
*vertex_declaration
;
955 IDirect3DVertexBuffer9
*vertex_buffer
;
956 IDirect3DIndexBuffer9
*index_buffer
;
957 ID3DXMeshImpl
*object
;
959 TRACE("(%d, %d, %d, %p, %p, %p)\n", numfaces
, numvertices
, options
, declaration
, device
, mesh
);
961 if (numfaces
== 0 || numvertices
== 0 || declaration
== NULL
|| device
== NULL
|| mesh
== NULL
)
963 return D3DERR_INVALIDCALL
;
966 hr
= D3DXFVFFromDeclarator(declaration
, &fvf
);
972 /* Create vertex declaration */
973 hr
= IDirect3DDevice9_CreateVertexDeclaration(device
,
975 &vertex_declaration
);
978 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexDeclaration.\n",hr
);
982 /* Create vertex buffer */
983 hr
= IDirect3DDevice9_CreateVertexBuffer(device
,
984 numvertices
* D3DXGetDeclVertexSize(declaration
, declaration
[0].Stream
),
992 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexBuffer.\n",hr
);
993 IDirect3DVertexDeclaration9_Release(vertex_declaration
);
997 /* Create index buffer */
998 hr
= IDirect3DDevice9_CreateIndexBuffer(device
,
999 numfaces
* 6, /* 3 vertices per triangle, 2 triangles per face */
1007 WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexBuffer.\n",hr
);
1008 IDirect3DVertexBuffer9_Release(vertex_buffer
);
1009 IDirect3DVertexDeclaration9_Release(vertex_declaration
);
1013 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ID3DXMeshImpl
));
1016 IDirect3DIndexBuffer9_Release(index_buffer
);
1017 IDirect3DVertexBuffer9_Release(vertex_buffer
);
1018 IDirect3DVertexDeclaration9_Release(vertex_declaration
);
1020 return E_OUTOFMEMORY
;
1022 object
->lpVtbl
= &D3DXMesh_Vtbl
;
1025 object
->numfaces
= numfaces
;
1026 object
->numvertices
= numvertices
;
1027 object
->options
= options
;
1029 object
->device
= device
;
1030 IDirect3DDevice9_AddRef(device
);
1032 object
->vertex_declaration
= vertex_declaration
;
1033 object
->vertex_buffer
= vertex_buffer
;
1034 object
->index_buffer
= index_buffer
;
1036 *mesh
= (ID3DXMesh
*)object
;
1041 /*************************************************************************
1044 HRESULT WINAPI
D3DXCreateMeshFVF(DWORD numfaces
, DWORD numvertices
, DWORD options
, DWORD fvf
,
1045 LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*mesh
)
1048 D3DVERTEXELEMENT9 declaration
[MAX_FVF_DECL_SIZE
];
1050 TRACE("(%u, %u, %u, %u, %p, %p)\n", numfaces
, numvertices
, options
, fvf
, device
, mesh
);
1052 hr
= D3DXDeclaratorFromFVF(fvf
, declaration
);
1053 if (FAILED(hr
)) return hr
;
1055 return D3DXCreateMesh(numfaces
, numvertices
, options
, declaration
, device
, mesh
);
1058 HRESULT WINAPI
D3DXCreateBox(LPDIRECT3DDEVICE9 device
, FLOAT width
, FLOAT height
,
1059 FLOAT depth
, LPD3DXMESH
* mesh
, LPD3DXBUFFER
* adjacency
)
1061 FIXME("(%p, %f, %f, %f, %p, %p): stub\n", device
, width
, height
, depth
, mesh
, adjacency
);
1068 D3DXVECTOR3 position
;
1072 typedef WORD face
[3];
1080 static void free_sincos_table(struct sincos_table
*sincos_table
)
1082 HeapFree(GetProcessHeap(), 0, sincos_table
->cos
);
1083 HeapFree(GetProcessHeap(), 0, sincos_table
->sin
);
1086 /* pre compute sine and cosine tables; caller must free */
1087 static BOOL
compute_sincos_table(struct sincos_table
*sincos_table
, float angle_start
, float angle_step
, int n
)
1092 sincos_table
->sin
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(*sincos_table
->sin
));
1093 if (!sincos_table
->sin
)
1097 sincos_table
->cos
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(*sincos_table
->cos
));
1098 if (!sincos_table
->cos
)
1100 HeapFree(GetProcessHeap(), 0, sincos_table
->sin
);
1104 angle
= angle_start
;
1105 for (i
= 0; i
< n
; i
++)
1107 sincos_table
->sin
[i
] = sin(angle
);
1108 sincos_table
->cos
[i
] = cos(angle
);
1109 angle
+= angle_step
;
1115 static WORD
vertex_index(UINT slices
, int slice
, int stack
)
1117 return stack
*slices
+slice
+1;
1120 HRESULT WINAPI
D3DXCreateSphere(LPDIRECT3DDEVICE9 device
, FLOAT radius
, UINT slices
,
1121 UINT stacks
, LPD3DXMESH
* mesh
, LPD3DXBUFFER
* adjacency
)
1123 DWORD number_of_vertices
, number_of_faces
;
1126 struct vertex
*vertices
;
1128 float phi_step
, phi_start
;
1129 struct sincos_table phi
;
1130 float theta_step
, theta
, sin_theta
, cos_theta
;
1134 TRACE("(%p, %f, %u, %u, %p, %p)\n", device
, radius
, slices
, stacks
, mesh
, adjacency
);
1136 if (!device
|| radius
< 0.0f
|| slices
< 2 || stacks
< 2 || !mesh
)
1138 return D3DERR_INVALIDCALL
;
1143 FIXME("Case of adjacency != NULL not implemented.\n");
1147 number_of_vertices
= 2 + slices
* (stacks
-1);
1148 number_of_faces
= 2 * slices
+ (stacks
- 2) * (2 * slices
);
1150 hr
= D3DXCreateMeshFVF(number_of_faces
, number_of_vertices
, D3DXMESH_MANAGED
,
1151 D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &sphere
);
1157 hr
= sphere
->lpVtbl
->LockVertexBuffer(sphere
, D3DLOCK_DISCARD
, (LPVOID
*)&vertices
);
1160 sphere
->lpVtbl
->Release(sphere
);
1164 hr
= sphere
->lpVtbl
->LockIndexBuffer(sphere
, D3DLOCK_DISCARD
, (LPVOID
*)&faces
);
1167 sphere
->lpVtbl
->UnlockVertexBuffer(sphere
);
1168 sphere
->lpVtbl
->Release(sphere
);
1172 /* phi = angle on xz plane wrt z axis */
1173 phi_step
= -2 * M_PI
/ slices
;
1174 phi_start
= M_PI
/ 2;
1176 if (!compute_sincos_table(&phi
, phi_start
, phi_step
, slices
))
1178 sphere
->lpVtbl
->UnlockIndexBuffer(sphere
);
1179 sphere
->lpVtbl
->UnlockVertexBuffer(sphere
);
1180 sphere
->lpVtbl
->Release(sphere
);
1181 return E_OUTOFMEMORY
;
1184 /* theta = angle on xy plane wrt x axis */
1185 theta_step
= M_PI
/ stacks
;
1192 vertices
[vertex
].normal
.x
= 0.0f
;
1193 vertices
[vertex
].normal
.y
= 0.0f
;
1194 vertices
[vertex
].normal
.z
= 1.0f
;
1195 vertices
[vertex
].position
.x
= 0.0f
;
1196 vertices
[vertex
].position
.y
= 0.0f
;
1197 vertices
[vertex
].position
.z
= radius
;
1200 for (stack
= 0; stack
< stacks
- 1; stack
++)
1202 sin_theta
= sin(theta
);
1203 cos_theta
= cos(theta
);
1205 for (slice
= 0; slice
< slices
; slice
++)
1207 vertices
[vertex
].normal
.x
= sin_theta
* phi
.cos
[slice
];
1208 vertices
[vertex
].normal
.y
= sin_theta
* phi
.sin
[slice
];
1209 vertices
[vertex
].normal
.z
= cos_theta
;
1210 vertices
[vertex
].position
.x
= radius
* sin_theta
* phi
.cos
[slice
];
1211 vertices
[vertex
].position
.y
= radius
* sin_theta
* phi
.sin
[slice
];
1212 vertices
[vertex
].position
.z
= radius
* cos_theta
;
1219 /* top stack is triangle fan */
1221 faces
[face
][1] = slice
+ 1;
1222 faces
[face
][2] = slice
;
1227 /* stacks in between top and bottom are quad strips */
1228 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1229 faces
[face
][1] = vertex_index(slices
, slice
, stack
-1);
1230 faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1233 faces
[face
][0] = vertex_index(slices
, slice
, stack
-1);
1234 faces
[face
][1] = vertex_index(slices
, slice
, stack
);
1235 faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1241 theta
+= theta_step
;
1247 faces
[face
][2] = slice
;
1252 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1253 faces
[face
][1] = vertex_index(slices
, 0, stack
-1);
1254 faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1257 faces
[face
][0] = vertex_index(slices
, 0, stack
-1);
1258 faces
[face
][1] = vertex_index(slices
, 0, stack
);
1259 faces
[face
][2] = vertex_index(slices
, slice
-1, stack
);
1264 vertices
[vertex
].position
.x
= 0.0f
;
1265 vertices
[vertex
].position
.y
= 0.0f
;
1266 vertices
[vertex
].position
.z
= -radius
;
1267 vertices
[vertex
].normal
.x
= 0.0f
;
1268 vertices
[vertex
].normal
.y
= 0.0f
;
1269 vertices
[vertex
].normal
.z
= -1.0f
;
1271 /* bottom stack is triangle fan */
1272 for (slice
= 1; slice
< slices
; slice
++)
1274 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1275 faces
[face
][1] = vertex_index(slices
, slice
, stack
-1);
1276 faces
[face
][2] = vertex
;
1280 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1281 faces
[face
][1] = vertex_index(slices
, 0, stack
-1);
1282 faces
[face
][2] = vertex
;
1284 free_sincos_table(&phi
);
1285 sphere
->lpVtbl
->UnlockIndexBuffer(sphere
);
1286 sphere
->lpVtbl
->UnlockVertexBuffer(sphere
);
1292 HRESULT WINAPI
D3DXCreateCylinder(LPDIRECT3DDEVICE9 device
, FLOAT radius1
, FLOAT radius2
, FLOAT length
, UINT slices
,
1293 UINT stacks
, LPD3DXMESH
* mesh
, LPD3DXBUFFER
* adjacency
)
1295 DWORD number_of_vertices
, number_of_faces
;
1297 ID3DXMesh
*cylinder
;
1298 struct vertex
*vertices
;
1300 float theta_step
, theta_start
;
1301 struct sincos_table theta
;
1302 float delta_radius
, radius
, radius_step
;
1303 float z
, z_step
, z_normal
;
1307 TRACE("(%p, %f, %f, %f, %u, %u, %p, %p)\n", device
, radius1
, radius2
, length
, slices
, stacks
, mesh
, adjacency
);
1309 if (device
== NULL
|| radius1
< 0.0f
|| radius2
< 0.0f
|| length
< 0.0f
|| slices
< 2 || stacks
< 1 || mesh
== NULL
)
1311 return D3DERR_INVALIDCALL
;
1316 FIXME("Case of adjacency != NULL not implemented.\n");
1320 number_of_vertices
= 2 + (slices
* (3 + stacks
));
1321 number_of_faces
= 2 * slices
+ stacks
* (2 * slices
);
1323 hr
= D3DXCreateMeshFVF(number_of_faces
, number_of_vertices
, D3DXMESH_MANAGED
,
1324 D3DFVF_XYZ
| D3DFVF_NORMAL
, device
, &cylinder
);
1330 hr
= cylinder
->lpVtbl
->LockVertexBuffer(cylinder
, D3DLOCK_DISCARD
, (LPVOID
*)&vertices
);
1333 cylinder
->lpVtbl
->Release(cylinder
);
1337 hr
= cylinder
->lpVtbl
->LockIndexBuffer(cylinder
, D3DLOCK_DISCARD
, (LPVOID
*)&faces
);
1340 cylinder
->lpVtbl
->UnlockVertexBuffer(cylinder
);
1341 cylinder
->lpVtbl
->Release(cylinder
);
1345 /* theta = angle on xy plane wrt x axis */
1346 theta_step
= -2 * M_PI
/ slices
;
1347 theta_start
= M_PI
/ 2;
1349 if (!compute_sincos_table(&theta
, theta_start
, theta_step
, slices
))
1351 cylinder
->lpVtbl
->UnlockIndexBuffer(cylinder
);
1352 cylinder
->lpVtbl
->UnlockVertexBuffer(cylinder
);
1353 cylinder
->lpVtbl
->Release(cylinder
);
1354 return E_OUTOFMEMORY
;
1361 delta_radius
= radius1
- radius2
;
1363 radius_step
= delta_radius
/ stacks
;
1366 z_step
= length
/ stacks
;
1367 z_normal
= delta_radius
/ length
;
1368 if (isnan(z_normal
))
1373 vertices
[vertex
].normal
.x
= 0.0f
;
1374 vertices
[vertex
].normal
.y
= 0.0f
;
1375 vertices
[vertex
].normal
.z
= -1.0f
;
1376 vertices
[vertex
].position
.x
= 0.0f
;
1377 vertices
[vertex
].position
.y
= 0.0f
;
1378 vertices
[vertex
++].position
.z
= z
;
1380 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1382 vertices
[vertex
].normal
.x
= 0.0f
;
1383 vertices
[vertex
].normal
.y
= 0.0f
;
1384 vertices
[vertex
].normal
.z
= -1.0f
;
1385 vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1386 vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1387 vertices
[vertex
].position
.z
= z
;
1392 faces
[face
][1] = slice
;
1393 faces
[face
++][2] = slice
+ 1;
1398 faces
[face
][1] = slice
;
1399 faces
[face
++][2] = 1;
1401 for (stack
= 1; stack
<= stacks
+1; stack
++)
1403 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1405 vertices
[vertex
].normal
.x
= theta
.cos
[slice
];
1406 vertices
[vertex
].normal
.y
= theta
.sin
[slice
];
1407 vertices
[vertex
].normal
.z
= z_normal
;
1408 D3DXVec3Normalize(&vertices
[vertex
].normal
, &vertices
[vertex
].normal
);
1409 vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1410 vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1411 vertices
[vertex
].position
.z
= z
;
1413 if (stack
> 1 && slice
> 0)
1415 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1416 faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1417 faces
[face
++][2] = vertex_index(slices
, slice
, stack
-1);
1419 faces
[face
][0] = vertex_index(slices
, slice
, stack
-1);
1420 faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1421 faces
[face
++][2] = vertex_index(slices
, slice
, stack
);
1427 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
-1);
1428 faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1429 faces
[face
++][2] = vertex_index(slices
, 0, stack
-1);
1431 faces
[face
][0] = vertex_index(slices
, 0, stack
-1);
1432 faces
[face
][1] = vertex_index(slices
, slice
-1, stack
);
1433 faces
[face
++][2] = vertex_index(slices
, 0, stack
);
1436 if (stack
< stacks
+ 1)
1439 radius
-= radius_step
;
1443 for (slice
= 0; slice
< slices
; slice
++, vertex
++)
1445 vertices
[vertex
].normal
.x
= 0.0f
;
1446 vertices
[vertex
].normal
.y
= 0.0f
;
1447 vertices
[vertex
].normal
.z
= 1.0f
;
1448 vertices
[vertex
].position
.x
= radius
* theta
.cos
[slice
];
1449 vertices
[vertex
].position
.y
= radius
* theta
.sin
[slice
];
1450 vertices
[vertex
].position
.z
= z
;
1454 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
);
1455 faces
[face
][1] = number_of_vertices
- 1;
1456 faces
[face
++][2] = vertex_index(slices
, slice
, stack
);
1460 vertices
[vertex
].position
.x
= 0.0f
;
1461 vertices
[vertex
].position
.y
= 0.0f
;
1462 vertices
[vertex
].position
.z
= z
;
1463 vertices
[vertex
].normal
.x
= 0.0f
;
1464 vertices
[vertex
].normal
.y
= 0.0f
;
1465 vertices
[vertex
].normal
.z
= 1.0f
;
1467 faces
[face
][0] = vertex_index(slices
, slice
-1, stack
);
1468 faces
[face
][1] = number_of_vertices
- 1;
1469 faces
[face
][2] = vertex_index(slices
, 0, stack
);
1471 free_sincos_table(&theta
);
1472 cylinder
->lpVtbl
->UnlockIndexBuffer(cylinder
);
1473 cylinder
->lpVtbl
->UnlockVertexBuffer(cylinder
);
1479 HRESULT WINAPI
D3DXCreateTeapot(LPDIRECT3DDEVICE9 device
, LPD3DXMESH
*mesh
, LPD3DXBUFFER
* adjacency
)
1481 FIXME("(%p, %p, %p): stub\n", device
, mesh
, adjacency
);