d3dx9: Apply current transform in ID3DXSprite_Draw instead of ID3DXSprite_Flush.
[wine/d3dx9TW.git] / dlls / d3dx9_36 / basemesh.c
blobfdf8556dea5a7e079a88d2b50b4216b4cb9d63a8
1 /*
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 /************************************************************
27 * basemesh_init
29 * initalizes an empty mesh from the given parameters
31 * PARAMS
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;
45 HRESULT hr;
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);
100 if(FAILED(hr)) {
101 HeapFree(GetProcessHeap(), 0, This->basemesh.pAttribBuf);
102 return hr;
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);
109 if(FAILED(hr)) {
110 HeapFree(GetProcessHeap(), 0, This->basemesh.pAttribBuf);
111 if(This->basemesh.pVBuf) IDirect3DVertexBuffer9_Release(This->basemesh.pVBuf);
112 return hr;
115 IDirect3DDevice9_AddRef(pDevice);
117 return D3D_OK;
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);
129 return D3D_OK;
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 */
140 startface = endface;
141 while(This->basemesh.pAttribBuf[endface] == This->basemesh.pAttribBuf[startface]) {
142 endface++;
143 if(endface >= This->basemesh.dwNumFaces) break;
145 if(This->basemesh.pAttribBuf[startface] != dwAttribId) continue;
147 /* draw subset */
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);
153 return D3D_OK;
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));
189 return D3D_OK;
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);
216 return D3D_OK;
219 HRESULT WINAPI basemesh_clone_mesh_fvf(LPD3DXBASEMESH iface,
220 DWORD dwOptions,
221 DWORD dwFVF,
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,
236 DWORD dwOptions,
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;
251 DWORD dwFVF;
252 HRESULT hr;
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);
277 if(FAILED(hr)) {
278 HeapFree(GetProcessHeap(), 0, object);
279 return hr;
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));
300 break;
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 */
335 return D3D_OK;
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;
348 return D3D_OK;
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;
361 return D3D_OK;
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;
400 return D3D_OK;
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);
407 return E_NOTIMPL;
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);
414 return E_NOTIMPL;
417 /************************************************************
418 * face_shared
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)
425 int fit = 0;
426 D3DXVECTOR3 buf = { 0.f, 0.f, 0.f };
428 D3DXVec3Subtract(&buf, &face1, &tri1);
429 if(D3DXVec3LengthSq(&buf) <= fEpsilonSq) fit = 1;
430 else {
431 D3DXVec3Subtract(&buf, &face1, &tri2);
432 if(D3DXVec3LengthSq(&buf) <= fEpsilonSq) fit = 2;
433 else {
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;
443 else {
444 D3DXVec3Subtract(&buf, &face2, &tri2);
445 if(D3DXVec3LengthSq(&buf) <= fEpsilonSq && fit != 2) fit = 4;
446 else {
447 D3DXVec3Subtract(&buf, &face2, &tri3);
448 if(D3DXVec3LengthSq(&buf) <= fEpsilonSq && fit != 3) fit = 4;
451 return (fit == 4);
454 HRESULT WINAPI basemesh_generate_adjacency(LPD3DXBASEMESH iface, FLOAT fEpsilon, DWORD *pAdjacency)
456 ID3DXBaseMeshImpl *This = (ID3DXBaseMeshImpl*)iface;
457 LPVOID pVertices, pIndices;
458 int i, k, bytes;
459 TRACE("(%p)\n", This);
461 if( !pAdjacency ) return D3DERR_INVALIDCALL;
462 if(!(This->basemesh.dwFvf & D3DFVF_XYZ)) return D3DERR_INVALIDCALL;
464 if(fEpsilon < 0.f) {
465 for(i = 0;i < 3 * This->basemesh.dwNumFaces;i++) pAdjacency[i] = D3DX_DEFAULT;
466 return D3D_OK;
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];
485 if(i == k) continue;
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 */
491 if(!have_face1) {
492 if( face_shared(fEpsilon, cmpvector1, cmpvector2, othervector[0], othervector[1], othervector[2]) ) {
493 pAdjacency[3*i] = k;
494 have_face1 = TRUE;
495 continue;
498 if(!have_face2) {
499 if( face_shared(fEpsilon, cmpvector2, cmpvector3, othervector[0], othervector[1], othervector[2]) ) {
500 pAdjacency[3*i+1] = k;
501 have_face2 = TRUE;
502 continue;
505 if(!have_face3) {
506 if( face_shared(fEpsilon, cmpvector3, cmpvector1, othervector[0], othervector[1], othervector[2]) ) {
507 pAdjacency[3*i+2] = k;
508 have_face3 = TRUE;
509 continue;
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);
521 return D3D_OK;
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);
528 return E_NOTIMPL;
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);
539 *object=This;
540 return S_OK;
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);
559 if(ref==0) {
560 basemesh_cleanup(iface);
561 HeapFree(GetProcessHeap(), 0, This);
563 return ref;
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,
607 DWORD dwOptions,
608 DWORD dwFVF,
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,
616 DWORD dwOptions,
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,