[PATCH v2] d3dx9: Implement ID3DXSkinInfo_Clone.

Gijs Vermeulen gijsvrm at gmail.com
Sun Jun 14 11:59:47 CDT 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48779
Signed-off-by: Gijs Vermeulen <gijsvrm at gmail.com>
---
v2: fix leak on error, thanks Nikolay

 dlls/d3dx9_36/skin.c       | 28 +++++++++++++++++--
 dlls/d3dx9_36/tests/mesh.c | 55 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/dlls/d3dx9_36/skin.c b/dlls/d3dx9_36/skin.c
index 2c10260e2a..99be6ca8e4 100644
--- a/dlls/d3dx9_36/skin.c
+++ b/dlls/d3dx9_36/skin.c
@@ -298,9 +298,33 @@ static D3DXMATRIX * WINAPI d3dx9_skin_info_GetBoneOffsetMatrix(ID3DXSkinInfo *if
 
 static HRESULT WINAPI d3dx9_skin_info_Clone(ID3DXSkinInfo *iface, ID3DXSkinInfo **skin_info)
 {
-    FIXME("iface %p, skin_info %p stub!\n", iface, skin_info);
+    struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface);
+    HRESULT hr;
+    DWORD i;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, skin_info %p.\n", iface, skin_info);
+
+    if (FAILED(hr = D3DXCreateSkinInfo(skin->num_vertices, skin->vertex_declaration, skin->num_bones, skin_info)))
+        return hr;
+
+    for (i = 0; i < skin->num_bones; ++i)
+    {
+        struct bone *current_bone = &skin->bones[i];
+
+        if (current_bone->name && FAILED(hr = (*skin_info)->lpVtbl->SetBoneName(*skin_info, i, current_bone->name)))
+            break;
+        if (&current_bone->transform
+                && FAILED(hr = (*skin_info)->lpVtbl->SetBoneOffsetMatrix(*skin_info, i, &current_bone->transform)))
+            break;
+        if (current_bone->vertices && current_bone->weights
+                && FAILED(hr = (*skin_info)->lpVtbl->SetBoneInfluence(*skin_info, i, current_bone->num_influences,
+                            current_bone->vertices, current_bone->weights)))
+            break;
+    }
+
+    if (FAILED(hr)) (*skin_info)->lpVtbl->Release(*skin_info);
+
+    return D3D_OK;
 }
 
 static HRESULT WINAPI d3dx9_skin_info_Remap(ID3DXSkinInfo *iface, DWORD num_vertices, DWORD *vertex_remap)
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index 81f902291d..cc2f158888 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -4990,6 +4990,7 @@ static void test_create_skin_info(void)
     ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
     if (skininfo)
     {
+        ID3DXSkinInfo *clone = NULL;
         DWORD dword_result;
         float flt_result;
         const char *string_result;
@@ -5023,6 +5024,10 @@ static void test_create_skin_info(void)
         transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1);
         ok(transform == NULL, "Expected NULL, got %p\n", transform);
 
+        hr = skininfo->lpVtbl->Clone(skininfo, &clone);
+        ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+        IUnknown_Release(clone);
+
         {
             /* test [GS]etBoneOffsetMatrix */
             hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix);
@@ -5139,6 +5144,9 @@ static void test_create_skin_info(void)
             ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
             ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]);
             ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]);
+
+            hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights);
+            ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
         }
 
         {
@@ -5182,6 +5190,53 @@ static void test_create_skin_info(void)
             ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
             compare_elements(declaration_out, declaration_in, __LINE__, 0);
         }
+
+        {
+            /* test Clone */
+            D3DVERTEXELEMENT9 got_declaration[MAX_FVF_DECL_SIZE];
+            DWORD exp_vertices[2], got_vertices[2];
+            FLOAT exp_weights[2], got_weights[2];
+            const char *exp_string, *got_string;
+            DWORD exp_fvf, got_fvf;
+            int i;
+
+            hr = skininfo->lpVtbl->Clone(skininfo, NULL);
+            ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
+
+            clone = NULL;
+            hr = skininfo->lpVtbl->Clone(skininfo, &clone);
+            ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+
+            hr = clone->lpVtbl->GetDeclaration(clone, got_declaration);
+            ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+            compare_elements(got_declaration, declaration_out, __LINE__, 0);
+
+            hr = D3DXFVFFromDeclarator(declaration_out, &exp_fvf);
+            ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+            got_fvf = clone->lpVtbl->GetFVF(clone);
+            ok(got_fvf == exp_fvf, "Expected %#x, got %#x\n", exp_fvf, got_fvf);
+
+            exp_string = skininfo->lpVtbl->GetBoneName(skininfo, 0);
+            got_string = clone->lpVtbl->GetBoneName(clone, 0);
+            ok(!strcmp(got_string, exp_string), "Expected '%s', got '%s'\n", exp_string, got_string);
+
+            transform = clone->lpVtbl->GetBoneOffsetMatrix(clone, 0);
+            check_matrix(transform, &identity_matrix);
+
+            hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, exp_vertices, exp_weights);
+            ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+            hr = clone->lpVtbl->GetBoneInfluence(clone, 0, got_vertices, got_weights);
+            ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+
+            for (i = 0; i < 2; i++) {
+                ok(got_vertices[i] == exp_vertices[i],
+                   "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], got_vertices[i]);
+                ok((isnan(got_weights[i]) && isnan(exp_weights[i])) || got_weights[i] == exp_weights[i],
+                   "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], got_weights[i]);
+            }
+
+            IUnknown_Release(clone);
+        }
     }
     if (skininfo) IUnknown_Release(skininfo);
     skininfo = NULL;
-- 
2.27.0




More information about the wine-devel mailing list