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