2 * Copyright (C) 2009 Tony Wasserka
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/debug.h"
21 #include "d3dx9_36_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
26 /************************************************************
29 * initalizes an empty mesh from the given parameters
32 * dwNumFaces [I] number of triangular faces
33 * dwNumVertices [I] number of vertices
34 * dwOptions [I] combination of D3DXMESH flags
35 * dwFVF [I] FVF to use
36 * pDevice [I] pointer to a Direct3D device
39 HRESULT
basemesh_init(ID3DXBaseMesh
*iface
, DWORD dwNumFaces
, DWORD dwNumVertices
, DWORD dwOptions
, DWORD dwFVF
, LPDIRECT3DDEVICE9 pDevice
)
41 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
42 D3DPOOL VBPool
, IBPool
;
43 DWORD dwVBFlags
= 0, dwIBFlags
= 0;
44 DWORD dwVBSize
, dwIBSize
;
47 if(dwNumFaces
> 65534) return D3DERR_INVALIDCALL
;
48 if(dwOptions
& 0xFF000000) return D3DERR_INVALIDCALL
;
50 This
->basemesh
.ref
= 1;
51 This
->basemesh
.pDevice
= pDevice
;
52 This
->basemesh
.dwNumFaces
= dwNumFaces
;
53 This
->basemesh
.dwNumVertices
= dwNumVertices
;
54 This
->basemesh
.dwOptions
= dwOptions
;
55 This
->basemesh
.dwFvf
= dwFVF
;
57 hr
= D3DXDeclaratorFromFVF(dwFVF
, This
->basemesh
.Declaration
);
58 if(FAILED(hr
)) return hr
;
60 if(dwOptions
& D3DXMESH_DONOTCLIP
) {
61 dwVBFlags
|= D3DUSAGE_DONOTCLIP
;
62 dwIBFlags
|= D3DUSAGE_DONOTCLIP
;
64 if(dwOptions
& D3DXMESH_RTPATCHES
) {
65 dwVBFlags
|= D3DUSAGE_RTPATCHES
;
66 dwIBFlags
|= D3DUSAGE_RTPATCHES
;
68 if(dwOptions
& D3DXMESH_NPATCHES
) {
69 dwVBFlags
|= D3DUSAGE_NPATCHES
;
70 dwIBFlags
|= D3DUSAGE_NPATCHES
;
72 if(dwOptions
& D3DXMESH_POINTS
) {
73 dwVBFlags
|= D3DUSAGE_POINTS
;
74 dwIBFlags
|= D3DUSAGE_POINTS
;
76 if(dwOptions
& D3DXMESH_VB_WRITEONLY
) dwVBFlags
|= D3DUSAGE_WRITEONLY
;
77 if(dwOptions
& D3DXMESH_VB_DYNAMIC
) dwVBFlags
|= D3DUSAGE_DYNAMIC
;
78 if(dwOptions
& D3DXMESH_VB_SOFTWAREPROCESSING
) dwVBFlags
|= D3DUSAGE_SOFTWAREPROCESSING
;
79 if(dwOptions
& D3DXMESH_IB_WRITEONLY
) dwIBFlags
|= D3DUSAGE_WRITEONLY
;
80 if(dwOptions
& D3DXMESH_IB_DYNAMIC
) dwIBFlags
|= D3DUSAGE_DYNAMIC
;
81 if(dwOptions
& D3DXMESH_IB_SOFTWAREPROCESSING
) dwIBFlags
|= D3DUSAGE_SOFTWAREPROCESSING
;
83 if(dwOptions
& D3DXMESH_VB_SYSTEMMEM
) VBPool
= D3DPOOL_SYSTEMMEM
;
84 else if(dwOptions
& D3DXMESH_VB_MANAGED
) VBPool
= D3DPOOL_MANAGED
;
85 else VBPool
= D3DPOOL_DEFAULT
;
87 if(dwOptions
& D3DXMESH_IB_SYSTEMMEM
) IBPool
= D3DPOOL_SYSTEMMEM
;
88 else if(dwOptions
& D3DXMESH_IB_MANAGED
) IBPool
= D3DPOOL_MANAGED
;
89 else IBPool
= D3DPOOL_DEFAULT
;
91 dwVBSize
= dwNumVertices
* D3DXGetFVFVertexSize(dwFVF
);
92 dwIBSize
= 3 * dwNumFaces
* ((dwOptions
& D3DXMESH_32BIT
) ? 4 : 2);
94 This
->basemesh
.pAttribBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DWORD
) * dwNumFaces
);
95 if( !This
->basemesh
.pAttribBuf
) return E_OUTOFMEMORY
;
97 if( !(dwOptions
& D3DXMESH_VB_SHARE
) ) {
98 hr
= IDirect3DDevice9_CreateVertexBuffer(pDevice
, dwVBSize
, dwVBFlags
,
99 dwFVF
, VBPool
, &This
->basemesh
.pVBuf
, NULL
);
101 HeapFree(GetProcessHeap(), 0, This
->basemesh
.pAttribBuf
);
104 } else This
->basemesh
.pVBuf
= NULL
;
106 hr
= IDirect3DDevice9_CreateIndexBuffer(pDevice
, dwIBSize
, dwIBFlags
,
107 (dwOptions
& D3DXMESH_32BIT
) ? D3DFMT_INDEX32
: D3DFMT_INDEX16
,
108 IBPool
, &This
->basemesh
.pIBuf
, NULL
);
110 HeapFree(GetProcessHeap(), 0, This
->basemesh
.pAttribBuf
);
111 if(This
->basemesh
.pVBuf
) IDirect3DVertexBuffer9_Release(This
->basemesh
.pVBuf
);
115 IDirect3DDevice9_AddRef(pDevice
);
120 HRESULT
basemesh_cleanup(ID3DXBaseMesh
*iface
)
122 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
124 if(This
->basemesh
.pAttribTable
) HeapFree(GetProcessHeap(), 0, This
->basemesh
.pAttribTable
);
125 IDirect3DIndexBuffer9_Release(This
->basemesh
.pIBuf
);
126 IDirect3DVertexBuffer9_Release(This
->basemesh
.pVBuf
);
127 IDirect3DDevice9_Release(This
->basemesh
.pDevice
);
132 HRESULT WINAPI
basemesh_draw_subset(LPD3DXBASEMESH iface
, DWORD dwAttribId
)
134 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
135 UINT startface
= 0, endface
= 0;
136 TRACE("(%p)\n", This
);
138 while(endface
< This
->basemesh
.dwNumFaces
) {
139 /* find faces with equal attribute id */
141 while(This
->basemesh
.pAttribBuf
[endface
] == This
->basemesh
.pAttribBuf
[startface
]) {
143 if(endface
>= This
->basemesh
.dwNumFaces
) break;
145 if(This
->basemesh
.pAttribBuf
[startface
] != dwAttribId
) continue;
148 IDirect3DDevice9_SetFVF(This
->basemesh
.pDevice
, This
->basemesh
.dwFvf
);
149 IDirect3DDevice9_SetStreamSource(This
->basemesh
.pDevice
, 0, This
->basemesh
.pVBuf
, 0, ID3DXMesh_GetNumBytesPerVertex(iface
));
150 IDirect3DDevice9_SetIndices(This
->basemesh
.pDevice
, This
->basemesh
.pIBuf
);
151 IDirect3DDevice9_DrawIndexedPrimitive(This
->basemesh
.pDevice
, D3DPT_TRIANGLELIST
, 0, 0, This
->basemesh
.dwNumVertices
, startface
* 3, endface
- startface
);
156 DWORD WINAPI
basemesh_get_num_faces(LPD3DXBASEMESH iface
)
158 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
159 TRACE("(%p)\n", This
);
160 return This
->basemesh
.dwNumFaces
;
163 DWORD WINAPI
basemesh_get_num_vertices(LPD3DXBASEMESH iface
)
165 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
166 TRACE("(%p)\n", This
);
167 return This
->basemesh
.dwNumVertices
;
170 DWORD WINAPI
basemesh_get_fvf(LPD3DXBASEMESH iface
)
172 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
173 TRACE("(%p)\n", This
);
174 return This
->basemesh
.dwFvf
;
177 HRESULT WINAPI
basemesh_get_declaration(LPD3DXBASEMESH iface
, D3DVERTEXELEMENT9 Declaration
[MAX_FVF_DECL_SIZE
])
179 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
180 D3DVERTEXELEMENT9 EndElement
= D3DDECL_END();
181 UINT NumElements
= 0;
182 TRACE("(%p)\n", This
);
184 if( !Declaration
) return D3DERR_INVALIDCALL
;
186 while( memcmp(&This
->basemesh
.Declaration
[NumElements
], &EndElement
, sizeof(D3DVERTEXELEMENT9
)) != 0 ) NumElements
++;
187 memcpy(Declaration
, This
->basemesh
.Declaration
, (NumElements
+ 1) * sizeof(D3DVERTEXELEMENT9
));
192 DWORD WINAPI
basemesh_get_num_bytes_per_vertex(LPD3DXBASEMESH iface
)
194 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
195 TRACE("(%p)\n", This
);
196 return D3DXGetFVFVertexSize(This
->basemesh
.dwFvf
);
199 DWORD WINAPI
basemesh_get_options(LPD3DXBASEMESH iface
)
201 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
202 TRACE("(%p)\n", This
);
203 return This
->basemesh
.dwOptions
;
206 HRESULT WINAPI
basemesh_get_device(LPD3DXBASEMESH iface
, LPDIRECT3DDEVICE9
*ppDevice
)
208 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
209 TRACE("(%p)\n", This
);
211 if( !ppDevice
) return D3DERR_INVALIDCALL
;
213 *ppDevice
= This
->basemesh
.pDevice
;
214 IDirect3DDevice9_AddRef(This
->basemesh
.pDevice
);
219 HRESULT WINAPI
basemesh_clone_mesh_fvf(LPD3DXBASEMESH iface
,
222 LPDIRECT3DDEVICE9 pDevice
,
223 LPD3DXMESH
*ppCloneMesh
)
225 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
226 D3DVERTEXELEMENT9 Declaration
[MAX_FVF_DECL_SIZE
];
227 TRACE("(%p): relay\n", This
);
229 if( !dwFVF
) return D3DERR_INVALIDCALL
;
231 D3DXDeclaratorFromFVF(dwFVF
, Declaration
);
232 return basemesh_clone_mesh((ID3DXBaseMesh
*)iface
, dwOptions
, Declaration
, pDevice
, ppCloneMesh
);
235 HRESULT WINAPI
basemesh_clone_mesh(LPD3DXBASEMESH iface
,
237 CONST D3DVERTEXELEMENT9
*pDeclaration
,
238 LPDIRECT3DDEVICE9 pDevice
,
239 LPD3DXMESH
*ppCloneMesh
)
241 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
242 ID3DXMeshImpl
*object
;
244 BYTE
*pSrcVertices
, *pDestVertices
;
245 void *pSrcIndices
, *pDestIndices
;
246 BYTE
*pSrcIndex
, *pDestIndex
;
247 DWORD dwSrcVertexSize
, dwDestVertexSize
;
248 DWORD dwSrcIndexSize
, dwDestIndexSize
;
250 UINT destelement
, srcelement
, num
;
254 TRACE("(%p)\n", This
);
256 if( !pDeclaration
) {
257 D3DVERTEXELEMENT9 bufdecl
[2];
258 D3DXDeclaratorFromFVF(D3DFVF_XYZ
, bufdecl
);
259 pDeclaration
= (CONST D3DVERTEXELEMENT9
*)&bufdecl
;
262 hr
= D3DXFVFFromDeclarator(pDeclaration
, &dwFVF
);
263 if(FAILED(hr
)) return hr
;
265 dwSrcVertexSize
= D3DXGetDeclVertexSize(This
->basemesh
.Declaration
, 0);
266 dwDestVertexSize
= D3DXGetDeclVertexSize(pDeclaration
, 0);
267 dwSrcIndexSize
= (This
->basemesh
.dwOptions
& D3DXMESH_32BIT
) ? 4 : 2;
268 dwDestIndexSize
= (dwOptions
& D3DXMESH_32BIT
) ? 4 : 2;
270 if(dwDestVertexSize
> dwSrcVertexSize
&& dwOptions
& D3DXMESH_VB_SHARE
) return D3DERR_INVALIDCALL
;
272 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ID3DXMeshImpl
));
273 if( !object
) return E_OUTOFMEMORY
;
275 object
->lpVtbl
= &D3DXMesh_Vtbl
;
276 hr
= basemesh_init((ID3DXBaseMesh
*)object
, This
->basemesh
.dwNumFaces
, This
->basemesh
.dwNumVertices
, dwOptions
, dwFVF
, pDevice
);
278 HeapFree(GetProcessHeap(), 0, object
);
281 if(dwOptions
& D3DXMESH_VB_SHARE
) {
282 object
->basemesh
.pVBuf
= This
->basemesh
.pVBuf
;
283 IDirect3DVertexBuffer9_AddRef(This
->basemesh
.pVBuf
);
285 *ppCloneMesh
= (ID3DXMesh
*)object
;
287 if( !(dwOptions
& D3DXMESH_VB_SHARE
) ) {
288 ID3DXBaseMesh_LockVertexBuffer(iface
, D3DLOCK_READONLY
, (void**)&pSrcVertices
);
289 ID3DXMesh_LockVertexBuffer(*ppCloneMesh
, D3DLOCK_DISCARD
, (void**)&pDestVertices
);
291 for(destelement
= 0;pDeclaration
[destelement
].Stream
!= 0xFF;destelement
++) {
292 for(srcelement
= 0;This
->basemesh
.Declaration
[srcelement
].Stream
!= 0xFF;srcelement
++) { /* Find corresponding source element */
293 if(memcmp(&pDeclaration
[destelement
], &This
->basemesh
.Declaration
[srcelement
], sizeof(D3DVERTEXELEMENT9
)) == 0) {
294 /* copy vertex elements */
295 for(num
= 0;num
< This
->basemesh
.dwNumVertices
;num
++)
296 memcpy(pDestVertices
+ dwDestVertexSize
* num
+ pDeclaration
[destelement
].Offset
,
297 pSrcVertices
+ dwSrcVertexSize
* num
+ This
->basemesh
.Declaration
[srcelement
].Offset
,
298 vertex_element_size(pDeclaration
[destelement
].Type
));
303 if(This
->basemesh
.Declaration
[srcelement
].Stream
!= 0xFF) continue;
305 /* zero new vertex elements */
306 for(num
= 0;num
< This
->basemesh
.dwNumVertices
;num
++)
307 ZeroMemory(pDestVertices
+ dwDestVertexSize
* num
+ pDeclaration
[destelement
].Offset
, vertex_element_size(pDeclaration
[destelement
].Type
));
311 ID3DXBaseMesh_UnlockVertexBuffer(iface
);
312 ID3DXMesh_UnlockVertexBuffer(*ppCloneMesh
);
315 ID3DXBaseMesh_LockIndexBuffer(iface
, D3DLOCK_READONLY
, (void**)&pSrcIndices
);
316 ID3DXMesh_LockIndexBuffer(*ppCloneMesh
, D3DLOCK_DISCARD
, (void**)&pDestIndices
);
318 pSrcIndex
= pSrcIndices
;
319 pDestIndex
= pDestIndices
;
321 if(dwSrcIndexSize
== dwDestIndexSize
) memcpy(pDestIndices
, pSrcIndices
, dwSrcIndexSize
* This
->basemesh
.dwNumFaces
* 3);
322 else for(num
= 0;num
< This
->basemesh
.dwNumFaces
* 3;num
++) {
323 if(dwDestIndexSize
== 2) *(WORD
*)pDestIndex
= *(DWORD
*)pSrcIndex
;
324 else /* if(dwDestIndexSize == 4) */ *(DWORD
*)pDestIndex
= *(WORD
*)pSrcIndex
;
326 pSrcIndex
+= dwSrcIndexSize
;
327 pDestIndex
+= dwDestIndexSize
;
330 ID3DXBaseMesh_UnlockIndexBuffer(iface
);
331 ID3DXMesh_UnlockIndexBuffer(*ppCloneMesh
);
333 /* TODO: Clone attribute buffer */
338 HRESULT WINAPI
basemesh_get_vertex_buffer(LPD3DXBASEMESH iface
, LPDIRECT3DVERTEXBUFFER9
*ppVB
)
340 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
341 TRACE("(%p)\n", This
);
343 if( !ppVB
) return D3DERR_INVALIDCALL
;
345 IDirect3DVertexBuffer9_AddRef(This
->basemesh
.pVBuf
);
346 *ppVB
= This
->basemesh
.pVBuf
;
351 HRESULT WINAPI
basemesh_get_index_buffer(LPD3DXBASEMESH iface
, LPDIRECT3DINDEXBUFFER9
*ppIB
)
353 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
354 TRACE("(%p)\n", This
);
356 if( !ppIB
) return D3DERR_INVALIDCALL
;
358 IDirect3DIndexBuffer9_AddRef(This
->basemesh
.pIBuf
);
359 *ppIB
= This
->basemesh
.pIBuf
;
364 HRESULT WINAPI
basemesh_lock_vertex_buffer(LPD3DXBASEMESH iface
, DWORD dwFlags
, LPVOID
*ppData
)
366 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
367 TRACE("(%p)\n", This
);
368 return IDirect3DVertexBuffer9_Lock(This
->basemesh
.pVBuf
, 0, 0, ppData
, dwFlags
);
371 HRESULT WINAPI
basemesh_unlock_vertex_buffer(LPD3DXBASEMESH iface
)
373 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
374 TRACE("(%p)\n", This
);
375 return IDirect3DVertexBuffer9_Unlock(This
->basemesh
.pVBuf
);
378 HRESULT WINAPI
basemesh_lock_index_buffer(LPD3DXBASEMESH iface
, DWORD dwFlags
, LPVOID
*ppData
)
380 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
381 TRACE("(%p)\n", This
);
382 return IDirect3DIndexBuffer9_Lock(This
->basemesh
.pIBuf
, 0, 0, ppData
, dwFlags
);
385 HRESULT WINAPI
basemesh_unlock_index_buffer(LPD3DXBASEMESH iface
)
387 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
388 TRACE("(%p)\n", This
);
389 return IDirect3DIndexBuffer9_Unlock(This
->basemesh
.pIBuf
);
392 HRESULT WINAPI
basemesh_get_attribute_table(LPD3DXBASEMESH iface
, D3DXATTRIBUTERANGE
*pAttribTable
, DWORD
*pAttribTableSize
)
394 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
395 TRACE("(%p)\n", This
);
397 if(This
->basemesh
.pAttribTable
) memcpy(pAttribTable
, This
->basemesh
.pAttribTable
, sizeof(D3DXATTRIBUTERANGE
) * This
->basemesh
.dwTableSize
);
398 if(pAttribTableSize
) *pAttribTableSize
= This
->basemesh
.dwTableSize
;
403 HRESULT WINAPI
basemesh_convert_point_reps_to_adjacency(LPD3DXBASEMESH iface
, CONST DWORD
*pPRep
, DWORD
*pAdjacency
)
405 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
406 FIXME("(%p): stub\n", This
);
410 HRESULT WINAPI
basemesh_convert_adjacency_to_point_reps(LPD3DXBASEMESH iface
, CONST DWORD
*pAdjacency
, DWORD
*pPRep
)
412 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
413 FIXME("(%p): stub\n", This
);
417 /************************************************************
420 * checks whether a face is part of the triangle
423 BOOL
face_shared(FLOAT fEpsilonSq
, D3DXVECTOR3 face1
, D3DXVECTOR3 face2
, D3DXVECTOR3 tri1
, D3DXVECTOR3 tri2
, D3DXVECTOR3 tri3
)
426 D3DXVECTOR3 buf
= { 0.f
, 0.f
, 0.f
};
428 D3DXVec3Subtract(&buf
, &face1
, &tri1
);
429 if(D3DXVec3LengthSq(&buf
) <= fEpsilonSq
) fit
= 1;
431 D3DXVec3Subtract(&buf
, &face1
, &tri2
);
432 if(D3DXVec3LengthSq(&buf
) <= fEpsilonSq
) fit
= 2;
434 D3DXVec3Subtract(&buf
, &face1
, &tri3
);
435 if(D3DXVec3LengthSq(&buf
) <= fEpsilonSq
) fit
= 3;
439 if(fit
== 0) return FALSE
;
441 D3DXVec3Subtract(&buf
, &face2
, &tri1
);
442 if(D3DXVec3LengthSq(&buf
) <= fEpsilonSq
&& fit
!= 1) fit
= 4;
444 D3DXVec3Subtract(&buf
, &face2
, &tri2
);
445 if(D3DXVec3LengthSq(&buf
) <= fEpsilonSq
&& fit
!= 2) fit
= 4;
447 D3DXVec3Subtract(&buf
, &face2
, &tri3
);
448 if(D3DXVec3LengthSq(&buf
) <= fEpsilonSq
&& fit
!= 3) fit
= 4;
454 HRESULT WINAPI
basemesh_generate_adjacency(LPD3DXBASEMESH iface
, FLOAT fEpsilon
, DWORD
*pAdjacency
)
456 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
457 LPVOID pVertices
, pIndices
;
459 TRACE("(%p)\n", This
);
461 if( !pAdjacency
) return D3DERR_INVALIDCALL
;
462 if(!(This
->basemesh
.dwFvf
& D3DFVF_XYZ
)) return D3DERR_INVALIDCALL
;
465 for(i
= 0;i
< 3 * This
->basemesh
.dwNumFaces
;i
++) pAdjacency
[i
] = D3DX_DEFAULT
;
469 basemesh_lock_vertex_buffer(iface
, D3DLOCK_READONLY
, &pVertices
);
470 basemesh_lock_index_buffer(iface
, D3DLOCK_READONLY
, &pIndices
);
472 bytes
= basemesh_get_num_bytes_per_vertex(iface
);
474 fEpsilon
*= fEpsilon
; /* use the square for calculations */
476 for(i
= 0;i
< This
->basemesh
.dwNumFaces
;i
++) {
477 BOOL have_face1
= FALSE
, have_face2
= FALSE
, have_face3
= FALSE
;
478 D3DXVECTOR3 cmpvector1
= *(D3DXVECTOR3
*)(((BYTE
*)pVertices
) + ((WORD
*)pIndices
)[3*i
] * bytes
); /* face i, index 0 */
479 D3DXVECTOR3 cmpvector2
= *(D3DXVECTOR3
*)(((BYTE
*)pVertices
) + ((WORD
*)pIndices
)[3*i
+1] * bytes
); /* face i, index 1 */
480 D3DXVECTOR3 cmpvector3
= *(D3DXVECTOR3
*)(((BYTE
*)pVertices
) + ((WORD
*)pIndices
)[3*i
+2] * bytes
); /* face i, index 2 */
482 for(k
= 0;k
< This
->basemesh
.dwNumFaces
;k
++) {
483 D3DXVECTOR3 othervector
[3];
487 othervector
[0] = *(D3DXVECTOR3
*)((BYTE
*)pVertices
+ ((WORD
*)pIndices
)[3*k
] * bytes
); /* face k, index 0 */
488 othervector
[1] = *(D3DXVECTOR3
*)((BYTE
*)pVertices
+ ((WORD
*)pIndices
)[3*k
+1] * bytes
); /* face k, index 1 */
489 othervector
[2] = *(D3DXVECTOR3
*)((BYTE
*)pVertices
+ ((WORD
*)pIndices
)[3*k
+2] * bytes
); /* face k, index 2 */
492 if( face_shared(fEpsilon
, cmpvector1
, cmpvector2
, othervector
[0], othervector
[1], othervector
[2]) ) {
499 if( face_shared(fEpsilon
, cmpvector2
, cmpvector3
, othervector
[0], othervector
[1], othervector
[2]) ) {
500 pAdjacency
[3*i
+1] = k
;
506 if( face_shared(fEpsilon
, cmpvector3
, cmpvector1
, othervector
[0], othervector
[1], othervector
[2]) ) {
507 pAdjacency
[3*i
+2] = k
;
513 if(!have_face1
) pAdjacency
[3*i
] = D3DX_DEFAULT
;
514 if(!have_face2
) pAdjacency
[3*i
+1] = D3DX_DEFAULT
;
515 if(!have_face3
) pAdjacency
[3*i
+2] = D3DX_DEFAULT
;
518 basemesh_unlock_index_buffer(iface
);
519 basemesh_unlock_vertex_buffer(iface
);
524 HRESULT WINAPI
basemesh_update_semantics(LPD3DXBASEMESH iface
, D3DVERTEXELEMENT9 Declaration
[MAX_FVF_DECL_SIZE
])
526 ID3DXBaseMeshImpl
*This
= (ID3DXBaseMeshImpl
*)iface
;
527 FIXME("(%p): stub\n", This
);
532 static HRESULT WINAPI
ID3DXBaseMeshImpl_QueryInterface(LPD3DXBASEMESH iface
, REFIID riid
, LPVOID
*object
)
534 ID3DXBaseMeshImpl
*This
=(ID3DXBaseMeshImpl
*)iface
;
536 TRACE("(%p): QueryInterface from %s\n", This
, debugstr_guid(riid
));
537 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ID3DXBaseMesh
) || IsEqualGUID(riid
, &IID_ID3DXMesh
)) {
538 IUnknown_AddRef(iface
);
542 WARN("(%p)->(%s, %p): not found\n", iface
, debugstr_guid(riid
), *object
);
543 return E_NOINTERFACE
;
546 static ULONG WINAPI
ID3DXBaseMeshImpl_AddRef(LPD3DXBASEMESH iface
)
548 ID3DXBaseMeshImpl
*This
=(ID3DXBaseMeshImpl
*)iface
;
549 TRACE("(%p): AddRef from %d\n", This
, This
->basemesh
.ref
);
550 return InterlockedIncrement(&This
->basemesh
.ref
);
553 static ULONG WINAPI
ID3DXBaseMeshImpl_Release(LPD3DXBASEMESH iface
)
555 ID3DXBaseMeshImpl
*This
=(ID3DXBaseMeshImpl
*)iface
;
556 ULONG ref
=InterlockedDecrement(&This
->basemesh
.ref
);
557 TRACE("(%p): ReleaseRef to %d\n", This
, ref
);
560 basemesh_cleanup(iface
);
561 HeapFree(GetProcessHeap(), 0, This
);
566 static HRESULT WINAPI
ID3DXBaseMeshImpl_DrawSubset(LPD3DXBASEMESH iface
, DWORD dwAttribId
)
568 return basemesh_draw_subset(iface
, dwAttribId
);
571 static DWORD WINAPI
ID3DXBaseMeshImpl_GetNumFaces(LPD3DXBASEMESH iface
)
573 return basemesh_get_num_faces(iface
);
576 static DWORD WINAPI
ID3DXBaseMeshImpl_GetNumVertices(LPD3DXBASEMESH iface
)
578 return basemesh_get_num_vertices(iface
);
581 static DWORD WINAPI
ID3DXBaseMeshImpl_GetFVF(LPD3DXBASEMESH iface
)
583 return basemesh_get_fvf(iface
);
586 static HRESULT WINAPI
ID3DXBaseMeshImpl_GetDeclaration(LPD3DXBASEMESH iface
, D3DVERTEXELEMENT9 Declaration
[MAX_FVF_DECL_SIZE
])
588 return basemesh_get_declaration(iface
, Declaration
);
591 static DWORD WINAPI
ID3DXBaseMeshImpl_GetNumBytesPerVertex(LPD3DXBASEMESH iface
)
593 return basemesh_get_num_bytes_per_vertex(iface
);
596 static DWORD WINAPI
ID3DXBaseMeshImpl_GetOptions(LPD3DXBASEMESH iface
)
598 return basemesh_get_options(iface
);
601 static HRESULT WINAPI
ID3DXBaseMeshImpl_GetDevice(LPD3DXBASEMESH iface
, LPDIRECT3DDEVICE9
*ppDevice
)
603 return basemesh_get_device(iface
, ppDevice
);
606 static HRESULT WINAPI
ID3DXBaseMeshImpl_CloneMeshFVF(LPD3DXBASEMESH iface
,
609 LPDIRECT3DDEVICE9 pDevice
,
610 LPD3DXMESH
*ppCloneMesh
)
612 return basemesh_clone_mesh_fvf(iface
, dwOptions
, dwFVF
, pDevice
, ppCloneMesh
);
615 static HRESULT WINAPI
ID3DXBaseMeshImpl_CloneMesh(LPD3DXBASEMESH iface
,
617 CONST D3DVERTEXELEMENT9
*pDeclaration
,
618 LPDIRECT3DDEVICE9 pDevice
,
619 LPD3DXMESH
*ppCloneMesh
)
621 return basemesh_clone_mesh(iface
, dwOptions
, pDeclaration
, pDevice
, ppCloneMesh
);
624 static HRESULT WINAPI
ID3DXBaseMeshImpl_GetVertexBuffer(LPD3DXBASEMESH iface
, LPDIRECT3DVERTEXBUFFER9
*ppVB
)
626 return basemesh_get_vertex_buffer(iface
, ppVB
);
629 static HRESULT WINAPI
ID3DXBaseMeshImpl_GetIndexBuffer(LPD3DXBASEMESH iface
, LPDIRECT3DINDEXBUFFER9
*ppIB
)
631 return basemesh_get_index_buffer(iface
, ppIB
);
634 static HRESULT WINAPI
ID3DXBaseMeshImpl_LockVertexBuffer(LPD3DXBASEMESH iface
, DWORD dwFlags
, LPVOID
*ppData
)
636 return basemesh_lock_vertex_buffer(iface
, dwFlags
, ppData
);
639 static HRESULT WINAPI
ID3DXBaseMeshImpl_UnlockVertexBuffer(LPD3DXBASEMESH iface
)
641 return basemesh_unlock_vertex_buffer(iface
);
644 static HRESULT WINAPI
ID3DXBaseMeshImpl_LockIndexBuffer(LPD3DXBASEMESH iface
, DWORD dwFlags
, LPVOID
*ppData
)
646 return basemesh_lock_index_buffer(iface
, dwFlags
, ppData
);
649 static HRESULT WINAPI
ID3DXBaseMeshImpl_UnlockIndexBuffer(LPD3DXBASEMESH iface
)
651 return basemesh_unlock_index_buffer(iface
);
654 static HRESULT WINAPI
ID3DXBaseMeshImpl_GetAttributeTable(LPD3DXBASEMESH iface
, D3DXATTRIBUTERANGE
*pAttribTable
, DWORD
*pAttribTableSize
)
656 return basemesh_get_attribute_table(iface
, pAttribTable
, pAttribTableSize
);
660 static HRESULT WINAPI
ID3DXBaseMeshImpl_ConvertPointRepsToAdjacency(LPD3DXBASEMESH iface
, CONST DWORD
*pPRep
, DWORD
*pAdjacency
)
662 return basemesh_convert_point_reps_to_adjacency(iface
, pPRep
, pAdjacency
);
665 static HRESULT WINAPI
ID3DXBaseMeshImpl_ConvertAdjacencyToPointReps(LPD3DXBASEMESH iface
, CONST DWORD
*pAdjacency
, DWORD
*pPRep
)
667 return basemesh_convert_adjacency_to_point_reps(iface
, pAdjacency
, pPRep
);
670 static HRESULT WINAPI
ID3DXBaseMeshImpl_GenerateAdjacency(LPD3DXBASEMESH iface
, FLOAT fEpsilon
, DWORD
*pAdjacency
)
672 return basemesh_generate_adjacency(iface
, fEpsilon
, pAdjacency
);
675 static HRESULT WINAPI
ID3DXBaseMeshImpl_UpdateSemantics(LPD3DXBASEMESH iface
, D3DVERTEXELEMENT9 Declaration
[MAX_FVF_DECL_SIZE
])
677 return basemesh_update_semantics(iface
, Declaration
);
681 static const ID3DXBaseMeshVtbl D3DXBaseMesh_Vtbl
=
683 /*** IUnknown methods ***/
684 ID3DXBaseMeshImpl_QueryInterface
,
685 ID3DXBaseMeshImpl_AddRef
,
686 ID3DXBaseMeshImpl_Release
,
687 /*** ID3DXBaseMesh methods ***/
688 ID3DXBaseMeshImpl_DrawSubset
,
689 ID3DXBaseMeshImpl_GetNumFaces
,
690 ID3DXBaseMeshImpl_GetNumVertices
,
691 ID3DXBaseMeshImpl_GetFVF
,
692 ID3DXBaseMeshImpl_GetDeclaration
,
693 ID3DXBaseMeshImpl_GetNumBytesPerVertex
,
694 ID3DXBaseMeshImpl_GetOptions
,
695 ID3DXBaseMeshImpl_GetDevice
,
696 ID3DXBaseMeshImpl_CloneMeshFVF
,
697 ID3DXBaseMeshImpl_CloneMesh
,
698 ID3DXBaseMeshImpl_GetVertexBuffer
,
699 ID3DXBaseMeshImpl_GetIndexBuffer
,
700 ID3DXBaseMeshImpl_LockVertexBuffer
,
701 ID3DXBaseMeshImpl_UnlockVertexBuffer
,
702 ID3DXBaseMeshImpl_LockIndexBuffer
,
703 ID3DXBaseMeshImpl_UnlockIndexBuffer
,
704 ID3DXBaseMeshImpl_GetAttributeTable
,
705 ID3DXBaseMeshImpl_ConvertPointRepsToAdjacency
,
706 ID3DXBaseMeshImpl_ConvertAdjacencyToPointReps
,
707 ID3DXBaseMeshImpl_GenerateAdjacency
,
708 ID3DXBaseMeshImpl_UpdateSemantics
,