On Tue, Jun 21, 2011 at 5:36 PM, Dylan Smith <dylan.ah.sm...@gmail.com> wrote: > On Tue, Jun 21, 2011 at 6:32 AM, Michael Mc Donnell > <mich...@mcdonnell.dk> wrote: >> Here is my test and implementation of ConvertAdjacencyToPointReps. > > >> + hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, >> (void**)&indices); >> + if (FAILED(hr)) goto cleanup; >> + memcpy(new_indices, indices, This->numvertices * sizeof(*indices)); > > I think you want the number of faces * 3 rather than the number of > vertices. And the size of an index is not constant, it is 32-bit if > This->options has the D3DXMESH_32BIT bit set and 16-bit if the bit > isn't set.
Yes you're right, I'll change that. I had completely forgotten about 16-bit indices, so that required a lot more changes and a test. >> +static void test_convert_adjacency_to_point_reps(void) >> +{ > ... >> + /* All mesh data */ >> + struct vertex_pnc *vertices[] = {vertices0, vertices1, vertices2, >> vertices3, vertices4, vertices5, vertices6}; >> + ID3DXMesh *meshes[ARRAY_SIZE(vertices)]; >> + DWORD *indices[] = {indices0, indices1, indices2, indices3, indices4, >> indices5, indices6}; >> + DWORD num_vertices[] = {num_vertices0, num_vertices1, num_vertices2, >> num_vertices3, num_vertices4, num_vertices5, num_vertices6}; >> + DWORD num_faces[] = {num_faces0, num_faces1, num_faces2, num_faces3, >> num_faces4, num_faces5, num_faces6}; >> + DWORD *adjacencies[] = {adjacency0, adjacency1, adjacency2, adjacency3, >> adjacency4, adjacency5, adjacency6}; >> + DWORD *point_reps[] = {point_rep0, point_rep1, point_rep2, point_rep3, >> point_rep4, point_rep5, point_rep6}; >> + DWORD *exp_point_reps[] = {exp_point_rep0, exp_point_rep1, >> exp_point_rep2, exp_point_rep3, exp_point_rep4, exp_point_rep5, >> exp_point_rep6}; > > I think it would make sense to put all these arrays of the same length > into a structure (e.g. struct test_case) array. This would make it > clear what needs to be updated to add another test case, and less > error prone than making sure each relevant individual array is > updated. Ok I've tried to make a struct for them. > Also, several of these and similar array seem like they can be made constant. Check, I've const'ified everything I could find. >> +static void test_convert_adjacency_to_point_reps(void) >> +{ > ... >> + for (i = 0; i < ARRAY_SIZE(meshes); i++) >> + { > ... >> + hr = meshes[i]->lpVtbl->ConvertAdjacencyToPointReps(meshes[i], >> adjacencies[i], point_reps[i]); >> + todo_wine ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed. " >> + "Got %x expected D3D_OK\n", hr); > > The value i should probably be printed in this error message. > Otherwise, if you see a failure on test.winehq.org that you can't > reproduce, it will be hard to figure out what might have caused the > failure. Yes, good idea. > That's it for now. Thanks your comments. I've attached an updated version.
From be56fecfb515d3407d7fe133ba00a8463745a973 Mon Sep 17 00:00:00 2001 From: Michael Mc Donnell <mich...@mcdonnell.dk> Date: Fri, 27 May 2011 16:24:18 +0200 Subject: d3dx9/tests: Implemented ConvertAdjacencyToPointReps test. --- dlls/d3dx9_36/tests/mesh.c | 352 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 352 insertions(+), 0 deletions(-) diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c index 668097f..ae4dd26 100644 --- a/dlls/d3dx9_36/tests/mesh.c +++ b/dlls/d3dx9_36/tests/mesh.c @@ -2,6 +2,7 @@ * Copyright 2008 David Adam * Copyright 2008 Luis Busquets * Copyright 2009 Henri Verbeet for CodeWeavers + * Copyright 2011 Michael Mc Donnell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -89,6 +90,93 @@ static BOOL compare_face(face a, face b) return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]); } +struct test_context +{ + HWND hwnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; +}; + +/* Initializes a test context struct. Use it to initialize DirectX. + * + * Returns NULL if an error occured. + */ +static struct test_context *new_test_context(void) +{ + HRESULT hr; + HWND hwnd = NULL; + IDirect3D9 *d3d = NULL; + IDirect3DDevice9 *device = NULL; + D3DPRESENT_PARAMETERS d3dpp = {0}; + struct test_context *test_context; + + hwnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + if (!hwnd) + { + skip("Couldn't create application window\n"); + goto error; + } + + d3d = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) + { + skip("Couldn't create IDirect3D9 object\n"); + goto error; + } + + memset(&d3dpp, 0, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, + D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device); + if (FAILED(hr)) + { + skip("Couldn't create IDirect3DDevice9 object %#x\n", hr); + goto error; + } + + test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context)); + if (!test_context) + { + skip("Couldn't allocate memory for test_context\n"); + goto error; + } + test_context->hwnd = hwnd; + test_context->d3d = d3d; + test_context->device = device; + + return test_context; + +error: + if (device) + IDirect3DDevice9_Release(device); + + if (d3d) + IDirect3D9_Release(d3d); + + if (hwnd) + DestroyWindow(hwnd); + + return NULL; +} + +static void free_test_context(struct test_context *test_context) +{ + if (!test_context) + return; + + if (test_context->device) + IDirect3DDevice9_Release(test_context->device); + + if (test_context->d3d) + IDirect3D9_Release(test_context->d3d); + + if (test_context->hwnd) + DestroyWindow(test_context->hwnd); + + HeapFree(GetProcessHeap(), 0, test_context); +} + struct mesh { DWORD number_of_vertices; @@ -4259,6 +4347,269 @@ static void D3DXGenerateAdjacencyTest(void) if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); } +static void test_convert_adjacency_to_point_reps(void) +{ + HRESULT hr; + struct test_context *test_context = NULL; + const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; + const DWORD options_16bit = D3DXMESH_SYSTEMMEM; + const D3DVERTEXELEMENT9 declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + const unsigned int VERTS_PER_FACE = 3; + void *vertex_buffer; + void *index_buffer; + DWORD *attributes_buffer; + int i, j; + struct vertex_pnc + { + FLOAT x, y, z; /* Position */ + FLOAT nx, ny, nz; /* Normal */ + DWORD color; /* In case of manual visual inspection */ + }; + /* mesh0 (one face) */ + const struct vertex_pnc vertices0[] = + { + {0.0f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {-1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + }; + const DWORD indices0[] = {0, 1, 2}; + const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); + const DWORD adjacency0[] = {-1, -1, -1}; + DWORD point_rep0[num_vertices0]; + const DWORD exp_point_rep0[] = {0, 1, 2}; + /* mesh1 (right) */ + const struct vertex_pnc vertices1[] = + { + {0.0f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {-1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + + {0.1f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {2.1f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {1.1f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + }; + const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); + const DWORD adjacency1[] = {1, -1, -1, -1, -1, 0}; + DWORD point_rep1[num_vertices1]; + const DWORD exp_point_rep1[] = {0, 1, 2, 0, 4, 1}; + /* mesh2 (below) */ + struct vertex_pnc vertices2[] = + { + {0.0f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {-1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + + {-1.0f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {1.0f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {0.0f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + }; + const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); + const DWORD adjacency2[] = {-1, 1, -1, 0, -1, -1}; + DWORD point_rep2[num_vertices2]; + const DWORD exp_point_rep2[] = {0, 1, 2, 2, 1, 5}; + /* mesh3 (left) */ + const struct vertex_pnc vertices3[] = + { + {0.0f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {-1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + + {-2.0f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {-0.1f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {-1.1f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + }; + const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); + const DWORD adjacency3[] = {-1, -1, 1, 0, -1, -1}; + DWORD point_rep3[num_vertices3]; + const DWORD exp_point_rep3[] = {0, 1, 2, 0, 2, 5}; + /* mesh4 (above, tip against tip) */ + struct vertex_pnc vertices4[] = + { + {0.0f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {-1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + + {0.0f, 1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {-1.0f, 3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {1.0f, 3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + }; + const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); + const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1}; + DWORD point_rep4[num_vertices4]; + const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5}; + /* mesh5 (complex example) */ + const struct vertex_pnc vertices5[] = + { + {0.0f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {-1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + + {0.1f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {2.1f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {1.1f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + + {-1.0f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {1.0f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {0.0f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + + {1.1f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {2.1f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {0.1f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + + {1.2f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {3.2f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {2.2f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + + {2.2f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {3.2f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.2f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + }; + const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; + const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); + const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; + DWORD point_rep5[num_vertices5]; + const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; + /* mesh6 (complex example) */ + const struct vertex_pnc vertices6[] = + { + {0.0f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {-1.0f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + + {0.1f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {2.1f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {1.1f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + + {-1.0f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {1.0f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {0.0f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + + {1.1f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {2.1f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {0.1f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + + {1.2f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + {3.2f, -1.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {2.2f, -3.1f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + + {2.2f, 1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff0000ff}, + {3.2f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xffff0000}, + {1.2f, -1.0f, 0.f, 0.0f, 0.0f, 1.0f, 0xff00ff00}, + }; + const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 18}; + const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); + const DWORD adjacency6[] = {-1, 1, -1, 0, -1, -1, -1, 5, -1, 4, -1, -1, 5, -1, 3, -1, 4, 2, -1, -1, -1}; + DWORD point_rep6[num_vertices6]; + const DWORD exp_point_rep6[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5, 18, 19, 20}; + const WORD indices6_16bit[] = {0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 18}; + /* All mesh data */ + unsigned int attributes[] = {0}; + const struct vertex_pnc *vertices[] = {vertices0, vertices1, vertices2, vertices3, vertices4, vertices5, vertices6, vertices6}; + struct + { + ID3DXMesh *meshes[ARRAY_SIZE(vertices)]; + const DWORD *indices[ARRAY_SIZE(vertices)]; + const DWORD num_vertices[ARRAY_SIZE(vertices)]; + const DWORD *adjacencies[ARRAY_SIZE(vertices)]; + DWORD *point_reps[ARRAY_SIZE(vertices)]; + const DWORD *exp_point_reps[ARRAY_SIZE(vertices)]; + const DWORD options[ARRAY_SIZE(vertices)]; + } + tc = + { + {NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {indices0, indices1, indices2, indices3, indices4, indices5, indices6, (DWORD*)indices6_16bit}, + {num_vertices0, num_vertices1, num_vertices2, num_vertices3, num_vertices4, num_vertices5, num_vertices6, num_vertices6}, + {adjacency0, adjacency1, adjacency2, adjacency3, adjacency4, adjacency5, adjacency6, adjacency6}, + {point_rep0, point_rep1, point_rep2, point_rep3, point_rep4, point_rep5, point_rep6, point_rep6}, + {exp_point_rep0, exp_point_rep1, exp_point_rep2, exp_point_rep3, exp_point_rep4, exp_point_rep5, exp_point_rep6, exp_point_rep6}, + {options, options, options, options, options, options, options, options_16bit} + }; + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create test context\n"); + goto cleanup; + } + + for (i = 0; i < ARRAY_SIZE(vertices); i++) + { + DWORD num_faces = tc.num_vertices[i] / VERTS_PER_FACE; + hr = D3DXCreateMesh(num_faces, tc.num_vertices[i], tc.options[i], declaration, + test_context->device, &tc.meshes[i]); + if (FAILED(hr)) + { + skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); + goto cleanup; + } + + tc.meshes[i]->lpVtbl->LockVertexBuffer(tc.meshes[i], 0, &vertex_buffer); + memcpy(vertex_buffer, vertices[i], tc.num_vertices[i] * sizeof(*vertices[i])); + tc.meshes[i]->lpVtbl->UnlockVertexBuffer(tc.meshes[i]); + + tc.meshes[i]->lpVtbl->LockIndexBuffer(tc.meshes[i], 0, &index_buffer); + if (tc.options[i] & D3DXMESH_32BIT) + { + + memcpy(index_buffer, tc.indices[i], VERTS_PER_FACE * num_faces * sizeof(DWORD)); + } + else + { + memcpy(index_buffer, tc.indices[i], VERTS_PER_FACE * num_faces * sizeof(WORD)); + } + tc.meshes[i]->lpVtbl->UnlockIndexBuffer(tc.meshes[i]); + + tc.meshes[i]->lpVtbl->LockAttributeBuffer(tc.meshes[i], 0, &attributes_buffer); + memcpy(attributes_buffer, attributes, sizeof(attributes)); + tc.meshes[i]->lpVtbl->UnlockAttributeBuffer(tc.meshes[i]); + + /* Convert adjacency to point representation */ + memset(tc.point_reps[i], -1, tc.num_vertices[i] * sizeof(*tc.point_reps[i])); + hr = tc.meshes[i]->lpVtbl->ConvertAdjacencyToPointReps(tc.meshes[i], tc.adjacencies[i], tc.point_reps[i]); + todo_wine ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. " + "Got %x expected D3D_OK\n", i, hr); + /* Check point representation */ + for (j = 0; j < tc.num_vertices[i]; j++) + { + todo_wine ok(tc.point_reps[i][j] == tc.exp_point_reps[i][j], + "Unexpected point representation at (%d, %d)." + " Got %d expected %d\n", + i, j, tc.point_reps[i][j], tc.exp_point_reps[i][j]); + } + } + + /* NULL checks */ + hr = tc.meshes[0]->lpVtbl->ConvertAdjacencyToPointReps(tc.meshes[0], tc.adjacencies[0], NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); + hr = tc.meshes[0]->lpVtbl->ConvertAdjacencyToPointReps(tc.meshes[0], NULL, tc.point_reps[0]); + todo_wine ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacencies NULL. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); + hr = tc.meshes[0]->lpVtbl->ConvertAdjacencyToPointReps(tc.meshes[0], NULL, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacencies and point_reps NULL. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); + +cleanup: + for (i = 0; i < ARRAY_SIZE(vertices); i++) + { + if (tc.meshes[i]) + tc.meshes[i]->lpVtbl->Release(tc.meshes[i]); + } + + free_test_context(test_context); +} + START_TEST(mesh) { D3DXBoundProbeTest(); @@ -4277,4 +4628,5 @@ START_TEST(mesh) test_get_decl_vertex_size(); test_fvf_decl_conversion(); D3DXGenerateAdjacencyTest(); + test_convert_adjacency_to_point_reps(); } -- 1.7.5.4
From 41be1283d55a40a6dc6dfc57b87866f4aef4fc3e Mon Sep 17 00:00:00 2001 From: Michael Mc Donnell <mich...@mcdonnell.dk> Date: Tue, 7 Jun 2011 22:37:42 +0200 Subject: d3dx9: Implemented ConvertAdjacencyToPointReps mesh method --- dlls/d3dx9_36/mesh.c | 162 +++++++++++++++++++++++++++++++++++++++++++- dlls/d3dx9_36/tests/mesh.c | 24 +++--- 2 files changed, 172 insertions(+), 14 deletions(-) diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c index cfadb75..8b9e804 100644 --- a/dlls/d3dx9_36/mesh.c +++ b/dlls/d3dx9_36/mesh.c @@ -6,6 +6,7 @@ * Copyright (C) 2009 David Adam * Copyright (C) 2010 Tony Wasserka * Copyright (C) 2011 Dylan Smith + * Copyright (C) 2011 Michael Mc Donnell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -431,13 +432,170 @@ static HRESULT WINAPI ID3DXMeshImpl_ConvertPointRepsToAdjacency(ID3DXMesh *iface return E_NOTIMPL; } +/* ConvertAdjacencyToPointReps helper function. + * + * Goes around the edges of a face and replaces the vertices in any adjacent + * face's edge with its own vertices(if its vertices have a lower index). This + * way as few as possible low index vertices are shared among the faces. The + * re-ordered index buffer is stored in new_indices. + * + * The vertices in a point representation must be ordered sequentially, e.g. + * index 3 holds the index of the vertex that replaces vertex 3, i.e. if + * vertex 3 is replaced by vertex 5 then index 3 would contain 5. If no vertex + * replaces it, then it contains the same number as the index itself, e.g. + * index 3 would contain 3. */ +static HRESULT propagate_face_vertices(CONST DWORD *adjacency, DWORD *point_reps, + CONST DWORD *indices, DWORD *new_indices, + CONST DWORD face, CONST DWORD numfaces) +{ + const unsigned int VERTS_PER_FACE = 3; + DWORD edge, opp_edge; + DWORD face_base = VERTS_PER_FACE * face; + + for (edge = 0; edge < VERTS_PER_FACE; edge++) + { + DWORD adj_face = adjacency[face_base + edge]; + DWORD adj_face_base; + DWORD i,j; + if (adj_face == -1) /* No adjacent face. */ + continue; + else if (adj_face >= numfaces) + { + /* This throws exception on Windows */ + WARN("Index out of bounds. Got %d expected less than %d.\n", + adj_face, numfaces); + return D3DERR_INVALIDCALL; + } + adj_face_base = 3 * adj_face; + + /* Find opposite edge in adjacent face. */ + for (opp_edge = 0; opp_edge < VERTS_PER_FACE; opp_edge++) + { + DWORD opp_edge_index = adj_face_base + opp_edge; + if (adjacency[opp_edge_index] == face) + break; /* Found opposite edge. */ + } + + /* Replaces vertices in opposite edge with vertices from current edge. */ + for (i = 0, j = 1; i < 2 && (j+1) > 0; i++, j--) + { + DWORD from = face_base + (edge + j) % VERTS_PER_FACE; + DWORD to = adj_face_base + (opp_edge + i) % VERTS_PER_FACE; + + /* Propagate lowest index. */ + if (new_indices[to] > new_indices[from]) + { + new_indices[to] = new_indices[from]; + point_reps[indices[to]] = new_indices[from]; + } + } + } + + return D3D_OK; +} + static HRESULT WINAPI ID3DXMeshImpl_ConvertAdjacencyToPointReps(ID3DXMesh *iface, CONST DWORD *adjacency, DWORD *point_reps) { + HRESULT hr; + DWORD face; + DWORD i; + DWORD *indices = NULL; + WORD *indices_16bit = NULL; + DWORD *new_indices = NULL; + const unsigned int VERTS_PER_FACE = 3; + ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface); - FIXME("(%p)->(%p,%p): stub\n", This, adjacency, point_reps); + TRACE("(%p)->(%p,%p)\n", This, adjacency, point_reps); - return E_NOTIMPL; + if (!adjacency) + { + WARN("NULL adjacency.\n"); + hr = D3DERR_INVALIDCALL; + goto cleanup; + } + + if (!point_reps) + { + WARN("NULL point_reps.\n"); + hr = D3DERR_INVALIDCALL; + goto cleanup; + } + + /* Should never happen as CreateMesh does not allow meshes with 0 faces */ + if (This->numfaces == 0) + { + ERR("Number of faces was zero."); + hr = D3DERR_INVALIDCALL; + goto cleanup; + } + + new_indices = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * This->numfaces * sizeof(*indices)); + if (!new_indices) + { + hr = E_OUTOFMEMORY; + goto cleanup; + } + + if (This->options & D3DXMESH_32BIT) + { + hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, (void**)&indices); + if (FAILED(hr)) goto cleanup; + memcpy(new_indices, indices, VERTS_PER_FACE * This->numfaces * sizeof(*indices)); + } + else + { + /* Make a widening copy of indices_16bit into indices and new_indices + * in order to re-use the helper function */ + hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, (void**)&indices_16bit); + if (FAILED(hr)) goto cleanup; + indices = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * This->numfaces * sizeof(*indices)); + if (!indices) + { + hr = E_OUTOFMEMORY; + goto cleanup; + } + for (i = 0; i < VERTS_PER_FACE * This->numfaces; i++) + { + new_indices[i] = indices_16bit[i]; + indices[i] = indices_16bit[i]; + } + } + + /* Vertices are ordered sequentially in the point representation. */ + for (i = 0; i < This->numvertices; i++) + { + point_reps[i] = i; + } + + /* Propagate vertices with low indices so as few vertices as possible + * are used in the mesh. + */ + for (face = 0; face < This->numfaces; face++) + { + hr = propagate_face_vertices(adjacency, point_reps, indices, new_indices, face, This->numfaces); + if (FAILED(hr)) goto cleanup; + } + /* Go in opposite direction to catch all face orderings */ + for (face = This->numfaces - 1; face + 1 > 0; face--) + { + hr = propagate_face_vertices(adjacency, point_reps, indices, new_indices, face, This->numfaces); + if (FAILED(hr)) goto cleanup; + } + + hr = D3D_OK; +cleanup: + if (This->options & D3DXMESH_32BIT) + { + if (indices) iface->lpVtbl->UnlockIndexBuffer(iface); + } + else + { + if (indices_16bit) iface->lpVtbl->UnlockIndexBuffer(iface); + if (indices) HeapFree(GetProcessHeap(), 0, indices); + } + if (new_indices) HeapFree(GetProcessHeap(), 0, new_indices); + return hr; } struct vertex_metadata { diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c index ae4dd26..fbb8fc9 100644 --- a/dlls/d3dx9_36/tests/mesh.c +++ b/dlls/d3dx9_36/tests/mesh.c @@ -4577,28 +4577,28 @@ static void test_convert_adjacency_to_point_reps(void) /* Convert adjacency to point representation */ memset(tc.point_reps[i], -1, tc.num_vertices[i] * sizeof(*tc.point_reps[i])); hr = tc.meshes[i]->lpVtbl->ConvertAdjacencyToPointReps(tc.meshes[i], tc.adjacencies[i], tc.point_reps[i]); - todo_wine ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. " - "Got %x expected D3D_OK\n", i, hr); + ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. " + "Got %x expected D3D_OK\n", i, hr); /* Check point representation */ for (j = 0; j < tc.num_vertices[i]; j++) { - todo_wine ok(tc.point_reps[i][j] == tc.exp_point_reps[i][j], - "Unexpected point representation at (%d, %d)." - " Got %d expected %d\n", - i, j, tc.point_reps[i][j], tc.exp_point_reps[i][j]); + ok(tc.point_reps[i][j] == tc.exp_point_reps[i][j], + "Unexpected point representation at (%d, %d)." + " Got %d expected %d\n", + i, j, tc.point_reps[i][j], tc.exp_point_reps[i][j]); } } /* NULL checks */ hr = tc.meshes[0]->lpVtbl->ConvertAdjacencyToPointReps(tc.meshes[0], tc.adjacencies[0], NULL); - todo_wine ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. " - "Got %x expected D3DERR_INVALIDCALL\n", hr); + ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); hr = tc.meshes[0]->lpVtbl->ConvertAdjacencyToPointReps(tc.meshes[0], NULL, tc.point_reps[0]); - todo_wine ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacencies NULL. " - "Got %x expected D3DERR_INVALIDCALL\n", hr); + ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacencies NULL. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); hr = tc.meshes[0]->lpVtbl->ConvertAdjacencyToPointReps(tc.meshes[0], NULL, NULL); - todo_wine ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacencies and point_reps NULL. " - "Got %x expected D3DERR_INVALIDCALL\n", hr); + ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacencies and point_reps NULL. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); cleanup: for (i = 0; i < ARRAY_SIZE(vertices); i++) -- 1.7.5.4