Michael Mc Donnell : d3dx9: Implemented ConvertPointRepsToAdjacency.
Alexandre Julliard
julliard at winehq.org
Tue Aug 2 14:18:29 CDT 2011
Module: wine
Branch: master
Commit: 507daa2154688d7b294591c078fb42b078eb3710
URL: http://source.winehq.org/git/wine.git/?a=commit;h=507daa2154688d7b294591c078fb42b078eb3710
Author: Michael Mc Donnell <michael at mcdonnell.dk>
Date: Mon Jun 27 22:44:33 2011 +0200
d3dx9: Implemented ConvertPointRepsToAdjacency.
---
dlls/d3dx9_36/mesh.c | 177 +++++++++++++++++++++++++++++++++++++++++++-
dlls/d3dx9_36/tests/mesh.c | 30 ++++----
2 files changed, 190 insertions(+), 17 deletions(-)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c
index 0d17941..9a0fd03 100644
--- a/dlls/d3dx9_36/mesh.c
+++ b/dlls/d3dx9_36/mesh.c
@@ -432,13 +432,186 @@ static HRESULT WINAPI ID3DXMeshImpl_GetAttributeTable(ID3DXMesh *iface, D3DXATTR
return D3D_OK;
}
+struct edge_face
+{
+ struct list entry;
+ DWORD v2;
+ DWORD face;
+};
+
+struct edge_face_map
+{
+ struct list *lists;
+ struct edge_face *entries;
+};
+
+/* Builds up a map of which face a new edge belongs to. That way the adjacency
+ * of another edge can be looked up. An edge has an adjacent face if there
+ * is an edge going in the opposite direction in the map. For example if the
+ * edge (v1, v2) belongs to face 4, and there is a mapping (v2, v1)->7, then
+ * face 4 and 7 are adjacent.
+ *
+ * Each edge might have been replaced with another edge, or none at all. There
+ * is at most one edge to face mapping, i.e. an edge can only belong to one
+ * face.
+ */
+static HRESULT init_edge_face_map(struct edge_face_map *edge_face_map, CONST DWORD *index_buffer, CONST DWORD *point_reps, CONST DWORD num_faces)
+{
+ DWORD face, edge;
+ DWORD i;
+
+ edge_face_map->lists = HeapAlloc(GetProcessHeap(), 0, 3 * num_faces * sizeof(*edge_face_map->lists));
+ if (!edge_face_map->lists) return E_OUTOFMEMORY;
+
+ edge_face_map->entries = HeapAlloc(GetProcessHeap(), 0, 3 * num_faces * sizeof(*edge_face_map->entries));
+ if (!edge_face_map->entries) return E_OUTOFMEMORY;
+
+
+ /* Initialize all lists */
+ for (i = 0; i < 3 * num_faces; i++)
+ {
+ list_init(&edge_face_map->lists[i]);
+ }
+ /* Build edge face mapping */
+ for (face = 0; face < num_faces; face++)
+ {
+ for (edge = 0; edge < 3; edge++)
+ {
+ DWORD v1 = index_buffer[3*face + edge];
+ DWORD v2 = index_buffer[3*face + (edge+1)%3];
+ DWORD new_v1 = point_reps[v1]; /* What v1 has been replaced with */
+ DWORD new_v2 = point_reps[v2];
+
+ if (v1 != v2) /* Only map non-collapsed edges */
+ {
+ i = 3*face + edge;
+ edge_face_map->entries[i].v2 = new_v2;
+ edge_face_map->entries[i].face = face;
+ list_add_head(&edge_face_map->lists[new_v1], &edge_face_map->entries[i].entry);
+ }
+ }
+ }
+
+ return D3D_OK;
+}
+
+static DWORD find_adjacent_face(struct edge_face_map *edge_face_map, DWORD vertex1, DWORD vertex2, CONST DWORD num_faces)
+{
+ struct edge_face *edge_face_ptr;
+
+ LIST_FOR_EACH_ENTRY(edge_face_ptr, &edge_face_map->lists[vertex2], struct edge_face, entry)
+ {
+ if (edge_face_ptr->v2 == vertex1)
+ return edge_face_ptr->face;
+ }
+
+ return -1;
+}
+
+static DWORD *generate_identity_point_reps(DWORD num_vertices)
+{
+ DWORD *id_point_reps;
+ DWORD i;
+
+ id_point_reps = HeapAlloc(GetProcessHeap(), 0, num_vertices * sizeof(*id_point_reps));
+ if (!id_point_reps)
+ return NULL;
+
+ for (i = 0; i < num_vertices; i++)
+ {
+ id_point_reps[i] = i;
+ }
+
+ return id_point_reps;
+}
+
static HRESULT WINAPI ID3DXMeshImpl_ConvertPointRepsToAdjacency(ID3DXMesh *iface, CONST DWORD *point_reps, DWORD *adjacency)
{
ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface);
+ HRESULT hr;
+ DWORD num_faces = iface->lpVtbl->GetNumFaces(iface);
+ DWORD num_vertices = iface->lpVtbl->GetNumVertices(iface);
+ DWORD options = iface->lpVtbl->GetOptions(iface);
+ BOOL indices_are_16_bit = !(options & D3DXMESH_32BIT);
+ DWORD *ib = NULL;
+ void *ib_ptr = NULL;
+ DWORD face;
+ DWORD edge;
+ struct edge_face_map edge_face_map = {0};
+ CONST DWORD *point_reps_ptr = NULL;
+ DWORD *id_point_reps = NULL;
- FIXME("(%p)->(%p,%p): stub\n", This, point_reps, adjacency);
+ TRACE("(%p)->(%p,%p)\n", This, point_reps, adjacency);
- return E_NOTIMPL;
+ if (!adjacency) return D3DERR_INVALIDCALL;
+
+ if (!point_reps) /* Identity point reps */
+ {
+ id_point_reps = generate_identity_point_reps(num_vertices);
+ if (!id_point_reps)
+ {
+ hr = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ point_reps_ptr = id_point_reps;
+ }
+ else
+ {
+ point_reps_ptr = point_reps;
+ }
+
+ hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, &ib_ptr);
+ if (FAILED(hr)) goto cleanup;
+
+ if (indices_are_16_bit)
+ {
+ /* Widen 16 bit to 32 bit */
+ DWORD i;
+ WORD *ib_16bit = ib_ptr;
+ ib = HeapAlloc(GetProcessHeap(), 0, 3 * num_faces * sizeof(DWORD));
+ if (!ib)
+ {
+ hr = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+ for (i = 0; i < 3 * num_faces; i++)
+ {
+ ib[i] = ib_16bit[i];
+ }
+ }
+ else
+ {
+ ib = ib_ptr;
+ }
+
+ hr = init_edge_face_map(&edge_face_map, ib, point_reps_ptr, num_faces);
+ if (FAILED(hr)) goto cleanup;
+
+ /* Create adjacency */
+ for (face = 0; face < num_faces; face++)
+ {
+ for (edge = 0; edge < 3; edge++)
+ {
+ DWORD v1 = ib[3*face + edge];
+ DWORD v2 = ib[3*face + (edge+1)%3];
+ DWORD new_v1 = point_reps_ptr[v1];
+ DWORD new_v2 = point_reps_ptr[v2];
+ DWORD adj_face;
+
+ adj_face = find_adjacent_face(&edge_face_map, new_v1, new_v2, num_faces);
+ adjacency[3*face + edge] = adj_face;
+ }
+ }
+
+ hr = D3D_OK;
+cleanup:
+ HeapFree(GetProcessHeap(), 0, id_point_reps);
+ if (indices_are_16_bit) HeapFree(GetProcessHeap(), 0, ib);
+ HeapFree(GetProcessHeap(), 0, edge_face_map.lists);
+ HeapFree(GetProcessHeap(), 0, edge_face_map.entries);
+ if(ib_ptr) iface->lpVtbl->UnlockIndexBuffer(iface);
+ return hr;
}
/* ConvertAdjacencyToPointReps helper function.
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index d8f9b97..39c78e6 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -5923,28 +5923,28 @@ static void test_convert_point_reps_to_adjacency(void)
/* Convert point representation to adjacency*/
memset(adjacency, -2, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency);
- todo_wine ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
- "Got %x expected D3D_OK\n", i, hr);
+ ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. "
+ "Got %x expected D3D_OK\n", i, hr);
/* Check adjacency */
for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
{
- todo_wine ok(adjacency[j] == tc[i].exp_adjacency[j],
- "Unexpected adjacency information at (%d, %d)."
- " Got %d expected %d\n",
- i, j, adjacency[j], tc[i].exp_adjacency[j]);
+ ok(adjacency[j] == tc[i].exp_adjacency[j],
+ "Unexpected adjacency information at (%d, %d)."
+ " Got %d expected %d\n",
+ i, j, adjacency[j], tc[i].exp_adjacency[j]);
}
/* NULL point representation is considered identity. */
memset(adjacency, -2, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency));
hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency);
- todo_wine ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
+ ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. "
"Got %x expected D3D_OK\n", hr);
for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++)
{
- todo_wine ok(adjacency[j] == tc[i].exp_id_adjacency[j],
- "Unexpected adjacency information (id) at (%d, %d)."
- " Got %d expected %d\n",
- i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
+ ok(adjacency[j] == tc[i].exp_id_adjacency[j],
+ "Unexpected adjacency information (id) at (%d, %d)."
+ " Got %d expected %d\n",
+ i, j, adjacency[j], tc[i].exp_id_adjacency[j]);
}
HeapFree(GetProcessHeap(), 0, adjacency);
@@ -5954,11 +5954,11 @@ static void test_convert_point_reps_to_adjacency(void)
/* NULL checks */
hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL);
- todo_wine ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
- "Got %x expected D3DERR_INVALIDCALL\n", hr);
+ ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. "
+ "Got %x expected D3DERR_INVALIDCALL\n", hr);
hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL);
- todo_wine ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
- "Got %x expected D3DERR_INVALIDCALL\n", hr);
+ ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. "
+ "Got %x expected D3DERR_INVALIDCALL\n", hr);
cleanup:
if (mesh_null_check)
More information about the wine-cvs
mailing list