Dylan Smith : d3dx9: Implement D3DXMESHOPT_COMPACT for ID3DXMesh:: OptimizeInplace.
Alexandre Julliard
julliard at winehq.org
Tue May 10 13:33:40 CDT 2011
Module: wine
Branch: master
Commit: 61ba38635b7deb316fb569d6becebf605bcbd98e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=61ba38635b7deb316fb569d6becebf605bcbd98e
Author: Dylan Smith <dylan.ah.smith at gmail.com>
Date: Mon May 9 06:30:51 2011 -0400
d3dx9: Implement D3DXMESHOPT_COMPACT for ID3DXMesh::OptimizeInplace.
---
dlls/d3dx9_36/mesh.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 149 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c
index cfb19bc..eca9332 100644
--- a/dlls/d3dx9_36/mesh.c
+++ b/dlls/d3dx9_36/mesh.c
@@ -653,13 +653,159 @@ static HRESULT WINAPI ID3DXMeshImpl_Optimize(ID3DXMesh *iface, DWORD flags, CONS
}
static HRESULT WINAPI ID3DXMeshImpl_OptimizeInplace(ID3DXMesh *iface, DWORD flags, CONST DWORD *adjacency_in, DWORD *adjacency_out,
- DWORD *face_remap, LPD3DXBUFFER *vertex_remap)
+ DWORD *face_remap_out, LPD3DXBUFFER *vertex_remap_out)
{
ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface);
+ void *indices = NULL;
+ HRESULT hr;
+ ID3DXBuffer *vertex_remap = NULL;
+ DWORD *dword_indices = NULL;
+ DWORD new_num_vertices = 0;
+ DWORD new_vertex_buffer_size = 0;
+ IDirect3DVertexBuffer9 *vertex_buffer = NULL;
+ DWORD i;
- FIXME("(%p)->(%u,%p,%p,%p,%p): stub\n", This, flags, adjacency_in, adjacency_out, face_remap, vertex_remap);
+ TRACE("(%p)->(%x,%p,%p,%p,%p)\n", This, flags, adjacency_in, adjacency_out, face_remap_out, vertex_remap_out);
- return E_NOTIMPL;
+ if (!flags)
+ return D3DERR_INVALIDCALL;
+ if (!adjacency_in && (flags & (D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_STRIPREORDER)))
+ return D3DERR_INVALIDCALL;
+ if ((flags & (D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_STRIPREORDER)) == (D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_STRIPREORDER))
+ return D3DERR_INVALIDCALL;
+
+ if (flags & (D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_STRIPREORDER))
+ {
+ if (flags & D3DXMESHOPT_ATTRSORT)
+ FIXME("D3DXMESHOPT_ATTRSORT not implemented.\n");
+ if (flags & D3DXMESHOPT_VERTEXCACHE)
+ FIXME("D3DXMESHOPT_VERTEXCACHE not implemented.\n");
+ if (flags & D3DXMESHOPT_STRIPREORDER)
+ FIXME("D3DXMESHOPT_STRIPREORDER not implemented.\n");
+ return E_NOTIMPL;
+ }
+
+ hr = iface->lpVtbl->LockIndexBuffer(iface, 0, (void**)&indices);
+ if (FAILED(hr)) goto cleanup;
+
+ dword_indices = HeapAlloc(GetProcessHeap(), 0, This->numfaces * 3 * sizeof(DWORD));
+ if (!dword_indices) return E_OUTOFMEMORY;
+ if (This->options & D3DXMESH_32BIT) {
+ memcpy(dword_indices, indices, This->numfaces * 3 * sizeof(DWORD));
+ } else {
+ WORD *word_indices = indices;
+ for (i = 0; i < This->numfaces * 3; i++)
+ dword_indices[i] = *word_indices++;
+ }
+
+ if ((flags & (D3DXMESHOPT_COMPACT | D3DXMESHOPT_IGNOREVERTS)) == D3DXMESHOPT_COMPACT)
+ {
+ /* Remove unused vertices. */
+ DWORD *vertex_remap_ptr;
+
+ new_vertex_buffer_size = This->numvertices;
+ hr = D3DXCreateBuffer(This->numvertices * sizeof(DWORD), &vertex_remap);
+ if (FAILED(hr)) goto cleanup;
+ vertex_remap_ptr = ID3DXBuffer_GetBufferPointer(vertex_remap);
+
+ for (i = 0; i < This->numfaces * 3; i++)
+ vertex_remap_ptr[dword_indices[i]] = 1;
+
+ /* create old->new vertex mapping */
+ for (i = 0; i < This->numvertices; i++) {
+ if (vertex_remap_ptr[i])
+ vertex_remap_ptr[i] = new_num_vertices++;
+ else
+ vertex_remap_ptr[i] = -1;
+ }
+ /* convert indices */
+ for (i = 0; i < This->numfaces * 3; i++)
+ dword_indices[i] = vertex_remap_ptr[dword_indices[i]];
+
+ /* create new->old vertex mapping */
+ new_num_vertices = 0;
+ for (i = 0; i < This->numvertices; i++) {
+ if (vertex_remap_ptr[i] != -1)
+ vertex_remap_ptr[new_num_vertices++] = i;
+ }
+ for (i = new_num_vertices; i < This->numvertices; i++)
+ vertex_remap_ptr[i] = -1;
+ }
+
+ if (vertex_remap)
+ {
+ /* reorder the vertices using vertex_remap */
+ D3DVERTEXBUFFER_DESC vertex_desc;
+ DWORD *vertex_remap_ptr = ID3DXBuffer_GetBufferPointer(vertex_remap);
+ DWORD vertex_size = iface->lpVtbl->GetNumBytesPerVertex(iface);
+ BYTE *orig_vertices;
+ BYTE *new_vertices;
+
+ hr = IDirect3DVertexBuffer9_GetDesc(This->vertex_buffer, &vertex_desc);
+ if (FAILED(hr)) goto cleanup;
+
+ new_vertex_buffer_size *= vertex_size;
+ hr = IDirect3DDevice9_CreateVertexBuffer(This->device, new_vertex_buffer_size,
+ vertex_desc.Usage, This->fvf, vertex_desc.Pool, &vertex_buffer, NULL);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IDirect3DVertexBuffer9_Lock(This->vertex_buffer, 0, 0, (void**)&orig_vertices, D3DLOCK_READONLY);
+ if (FAILED(hr)) goto cleanup;
+
+ hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, (void**)&new_vertices, D3DLOCK_DISCARD);
+ if (FAILED(hr)) {
+ IDirect3DVertexBuffer9_Unlock(This->vertex_buffer);
+ goto cleanup;
+ }
+
+ for (i = 0; i < new_num_vertices; i++)
+ memcpy(new_vertices + i * vertex_size, orig_vertices + vertex_remap_ptr[i] * vertex_size, vertex_size);
+
+ IDirect3DVertexBuffer9_Unlock(This->vertex_buffer);
+ IDirect3DVertexBuffer9_Unlock(vertex_buffer);
+ } else if (vertex_remap_out) {
+ DWORD *vertex_remap_ptr;
+
+ hr = D3DXCreateBuffer(This->numvertices * sizeof(DWORD), &vertex_remap);
+ if (FAILED(hr)) goto cleanup;
+ vertex_remap_ptr = ID3DXBuffer_GetBufferPointer(vertex_remap);
+ for (i = 0; i < This->numvertices; i++)
+ *vertex_remap_ptr++ = i;
+ }
+
+ if (This->options & D3DXMESH_32BIT) {
+ memcpy(indices, dword_indices, This->numfaces * 3 * sizeof(DWORD));
+ } else {
+ WORD *word_indices = indices;
+ for (i = 0; i < This->numfaces * 3; i++)
+ *word_indices++ = dword_indices[i];
+ }
+
+ if (adjacency_out) {
+ memcpy(adjacency_out, adjacency_in, This->numfaces * 3 * sizeof(*adjacency_out));
+ }
+ if (face_remap_out) {
+ for (i = 0; i < This->numfaces; i++)
+ face_remap_out[i] = i;
+ }
+ if (vertex_remap_out)
+ *vertex_remap_out = vertex_remap;
+ vertex_remap = NULL;
+
+ if (vertex_buffer) {
+ IDirect3DVertexBuffer9_Release(This->vertex_buffer);
+ This->vertex_buffer = vertex_buffer;
+ vertex_buffer = NULL;
+ This->numvertices = new_num_vertices;
+ }
+
+ hr = D3D_OK;
+cleanup:
+ HeapFree(GetProcessHeap(), 0, dword_indices);
+ if (vertex_remap) ID3DXBuffer_Release(vertex_remap);
+ if (vertex_buffer) IDirect3DVertexBuffer9_Release(vertex_buffer);
+ if (indices) iface->lpVtbl->UnlockIndexBuffer(iface);
+ return hr;
}
static HRESULT WINAPI ID3DXMeshImpl_SetAttributeTable(ID3DXMesh *iface, CONST D3DXATTRIBUTERANGE *attrib_table, DWORD attrib_table_size)
More information about the wine-cvs
mailing list