d3dx9: Implement D3DXMESHOPT_COMPACT for ID3DXMesh::OptimizeInplace.

This commit is contained in:
Dylan Smith 2011-05-09 06:30:51 -04:00 committed by Alexandre Julliard
parent e62a4276ed
commit 61ba38635b
1 changed files with 149 additions and 3 deletions

View File

@ -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)