From: Paul Gofman pgofman@codeweavers.com
--- include/d3dx9anim.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/d3dx9anim.h b/include/d3dx9anim.h index 81b8e2f6b2c..741ed5a3a56 100644 --- a/include/d3dx9anim.h +++ b/include/d3dx9anim.h @@ -183,9 +183,9 @@ DECLARE_INTERFACE(ID3DXAllocateHierarchy) #define INTERFACE ID3DXLoadUserData DECLARE_INTERFACE(ID3DXLoadUserData) { - STDMETHOD(LoadTopLevelData)(ID3DXFileData *child_data) PURE; - STDMETHOD(LoadFrameChildData)(D3DXFRAME *frame, ID3DXFileData *child_data) PURE; - STDMETHOD(LoadMeshChildData)(D3DXMESHCONTAINER *mesh_container, ID3DXFileData *child_data) PURE; + STDMETHOD(LoadTopLevelData)(ID3DXLoadUserData *user_data, ID3DXFileData *child_data) PURE; + STDMETHOD(LoadFrameChildData)(ID3DXLoadUserData *user_data, D3DXFRAME *frame, ID3DXFileData *child_data) PURE; + STDMETHOD(LoadMeshChildData)(ID3DXLoadUserData *user_data, D3DXMESHCONTAINER *mesh_container, ID3DXFileData *child_data) PURE; }; #undef INTERFACE
From: Paul Gofman pgofman@codeweavers.com
--- dlls/d3dx9_36/tests/mesh.c | 212 ++++++++++++++++++++++++++++++++++++- 1 file changed, 211 insertions(+), 1 deletion(-)
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c index ce68903572b..6796a40b360 100644 --- a/dlls/d3dx9_36/tests/mesh.c +++ b/dlls/d3dx9_36/tests/mesh.c @@ -2030,6 +2030,132 @@ static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char * } }
+#define MAX_USER_DATA_COUNT 32 +enum user_data_type +{ + USER_DATA_TYPE_TOP, + USER_DATA_TYPE_FRAME_CHILD, + USER_DATA_TYPE_MESH_CHILD, +}; + +struct test_user_data +{ + enum user_data_type data_type; + GUID type; + SIZE_T size; + unsigned int value; + BOOL mesh_container; + unsigned int num_materials; +}; + +struct test_load_user_data +{ + ID3DXLoadUserData iface; + + unsigned int data_count; + struct test_user_data data[MAX_USER_DATA_COUNT]; +}; + +static void record_common_user_data(struct test_load_user_data *data, ID3DXFileData *filedata, + enum user_data_type data_type) +{ + struct test_user_data *d = &data->data[data->data_count]; + const void *ptr; + HRESULT hr; + SIZE_T sz; + + ok(data->data_count < MAX_USER_DATA_COUNT, "got %u.\n", data->data_count); + + d->data_type = data_type; + hr = filedata->lpVtbl->GetType(filedata, &d->type); + ok(hr == S_OK, "got %#lx.\n", hr); + hr = filedata->lpVtbl->Lock(filedata, &sz, &ptr); + ok(hr == S_OK, "got %#lx.\n", hr); + d->size = sz; + ok(sz >= sizeof(int), "got %Iu.\n", sz); + d->value = *(unsigned int *)ptr; + hr = filedata->lpVtbl->Unlock(filedata); + ok(hr == S_OK, "got %#lx.\n", hr); + ++data->data_count; +} + +static struct test_load_user_data *impl_from_ID3DXLoadUserData(ID3DXLoadUserData *iface) +{ + return CONTAINING_RECORD(iface, struct test_load_user_data, iface); +} + +static HRESULT STDMETHODCALLTYPE load_top_level_data(ID3DXLoadUserData *iface, ID3DXFileData *filedata) +{ + struct test_load_user_data *user_data = impl_from_ID3DXLoadUserData(iface); + + record_common_user_data(user_data, filedata, USER_DATA_TYPE_TOP); + return S_OK; +} +static HRESULT STDMETHODCALLTYPE load_frame_child_data(ID3DXLoadUserData *iface, D3DXFRAME *frame, + ID3DXFileData *filedata) +{ + struct test_load_user_data *user_data = impl_from_ID3DXLoadUserData(iface); + + ok(!frame->pFrameSibling, "got %p.\n", frame->pFrameSibling); + ok(!frame->pFrameFirstChild, "got %p.\n", frame->pFrameFirstChild); + + user_data->data[user_data->data_count].mesh_container = !!frame->pMeshContainer; + record_common_user_data(user_data, filedata, USER_DATA_TYPE_FRAME_CHILD); + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE load_mesh_child_data(ID3DXLoadUserData *iface, D3DXMESHCONTAINER *mesh_container, + ID3DXFileData *filedata) +{ + struct test_load_user_data *user_data = impl_from_ID3DXLoadUserData(iface); + + user_data->data[user_data->data_count].num_materials = mesh_container->NumMaterials; + + record_common_user_data(user_data, filedata, USER_DATA_TYPE_MESH_CHILD); + return S_OK; +} + +static const struct ID3DXLoadUserDataVtbl load_user_data_vtbl = +{ + load_top_level_data, + load_frame_child_data, + load_mesh_child_data, +}; + +static void init_load_user_data(struct test_load_user_data *data) +{ + memset(data, 0, sizeof(*data)); + data->iface.lpVtbl = &load_user_data_vtbl; +} + +static void check_user_data(struct test_load_user_data *user_data, unsigned int expected_count, + struct test_user_data *expected) +{ + unsigned int i; + + ok(user_data->data_count == expected_count, "got %u, expected %u.\n", user_data->data_count, expected_count); + expected_count = min(expected_count, user_data->data_count); + for (i = 0; i < expected_count; ++i) + { + winetest_push_context("i %u", i); + ok(user_data->data[i].data_type == expected[i].data_type, "got %u, expected %u.\n", + user_data->data[i].data_type, expected[i].data_type); + ok(IsEqualGUID(&user_data->data[i].type, &expected[i].type), "got %s, expected %s.\n", + debugstr_guid(&user_data->data[i].type), debugstr_guid(&expected[i].type)); + ok(user_data->data[i].size == expected[i].size, "got %Iu, expected %Iu.\n", + user_data->data[i].size, expected[i].size); + ok(user_data->data[i].value == expected[i].value, "got %u, expected %u.\n", + user_data->data[i].value, expected[i].value); + ok(user_data->data[i].mesh_container == expected[i].mesh_container, "got %u, expected %u.\n", + user_data->data[i].mesh_container, expected[i].mesh_container); + ok(user_data->data[i].num_materials == expected[i].num_materials, "got %u, expected %u.\n", + user_data->data[i].num_materials, expected[i].num_materials); + winetest_pop_context(); + } +} + +DEFINE_GUID(TID_TestDataGuid, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11); + static void D3DXLoadMeshTest(void) { static const char empty_xfile[] = "xof 0303txt 0032"; @@ -2051,14 +2177,42 @@ static void D3DXLoadMeshTest(void) const DWORD simple_fvf = D3DFVF_XYZ; static const char framed_xfile[] = "xof 0303txt 0032" + "template TestData {" + "<12345678-1234-1234-1234-111111111111>" + "DWORD value;" + "}" + "TestData {" + "1;;" + "}" + "Material {" + /* ColorRGBA faceColor; */ + "0.0; 0.0; 1.0; 1.0;;" + /* FLOAT power; */ + "0.5;" + /* ColorRGB specularColor; */ + "1.0; 1.0; 1.0;;" + /* ColorRGB emissiveColor; */ + "0.0; 0.0; 0.0;;" + "}" + "Frame {" - "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 1.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" + "TestData {" + "2;;" + "}" + "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 1.0; 1.0; 0.0;; 1; 3; 0, 1, 2;;" + "TestData {" + "3;;" + "}" + "}" "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */ "1.0, 0.0, 0.0, 0.0," "0.0, 1.0, 0.0, 0.0," "0.0, 0.0, 1.0, 0.0," "0.0, 0.0, 2.0, 1.0;;" "}" + "TestData {" + "4;;" + "}" "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 2.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */ "1.0, 0.0, 0.0, 0.0," @@ -2068,6 +2222,16 @@ static void D3DXLoadMeshTest(void) "}" "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 3.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" "}"; + + struct test_user_data framed_xfile_expected_user_data[] = + { + { USER_DATA_TYPE_TOP, TID_TestDataGuid, 4, 1, 0, 0}, + { USER_DATA_TYPE_TOP, TID_D3DRMMaterial, 44, 0, 0, 0}, + { USER_DATA_TYPE_FRAME_CHILD, TID_TestDataGuid, 4, 2, 0, 0}, + { USER_DATA_TYPE_MESH_CHILD, TID_TestDataGuid, 4, 3, 0, 0}, + { USER_DATA_TYPE_FRAME_CHILD, TID_TestDataGuid, 4, 4, 1, 0}, + }; + static const char framed_xfile_empty[] = "xof 0303txt 0032" "Frame Box01 {" @@ -2093,6 +2257,10 @@ static void D3DXLoadMeshTest(void) /*________________________*/ static const char box_xfile[] = "xof 0303txt 0032" + "template TestData {" + "<12345678-1234-1234-1234-111111111111>" + "DWORD value;" + "}" "Mesh {" "8;" /* DWORD nVertices; */ /* array Vector vertices[nVertices]; */ @@ -2130,6 +2298,9 @@ static void D3DXLoadMeshTest(void) "4; 4, 4, 4, 4;," "4; 5, 5, 5, 5;;" "}" + "TestData {" + "1;;" + "}" "MeshMaterialList materials {" "2;" /* DWORD nMaterials; */ "6;" /* DWORD nFaceIndexes; */ @@ -2157,6 +2328,10 @@ static void D3DXLoadMeshTest(void) "TextureFilename { "texture.jpg"; }" "}" "}" + "TestData {" + "2;;" + "}" + "MeshVertexColors {" "8;" /* DWORD nVertexColors; */ /* array IndexedColor vertexColors[nVertexColors]; */ @@ -2182,6 +2357,12 @@ static void D3DXLoadMeshTest(void) "0.0; 0.0;;" "}" "}"; + struct test_user_data box_xfile_expected_user_data[] = + { + { USER_DATA_TYPE_MESH_CHILD, TID_TestDataGuid, 4, 1, 0, 2}, + { USER_DATA_TYPE_MESH_CHILD, TID_TestDataGuid, 4, 2, 0, 2}, + }; + static const WORD box_index_buffer[] = { 0, 1, 3, 0, 3, 2, @@ -2393,6 +2574,7 @@ static void D3DXLoadMeshTest(void) ID3DXAnimationController *controller; D3DXMESHCONTAINER *container; unsigned int i; + struct test_load_user_data load_user_data;
if (!(test_context = new_test_context())) { @@ -2487,6 +2669,20 @@ static void D3DXLoadMeshTest(void) ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); frame_hier = NULL;
+ init_load_user_data(&load_user_data); + hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, &load_user_data.iface, &frame_hier, &controller); + todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + winetest_push_context("box_xfile"); + check_user_data(&load_user_data, ARRAY_SIZE(box_xfile_expected_user_data), box_xfile_expected_user_data); + winetest_pop_context(); + hr = D3DXFrameDestroy(frame_hier, &alloc_hier); + ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); + } + frame_hier = NULL; + hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1, D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); @@ -2516,6 +2712,20 @@ static void D3DXLoadMeshTest(void) ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); frame_hier = NULL;
+ init_load_user_data(&load_user_data); + hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, &load_user_data.iface, &frame_hier, NULL); + todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); + if (SUCCEEDED(hr)) + { + hr = D3DXFrameDestroy(frame_hier, &alloc_hier); + ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); + winetest_push_context("framed_xfile"); + check_user_data(&load_user_data, ARRAY_SIZE(framed_xfile_expected_user_data), framed_xfile_expected_user_data); + winetest_pop_context(); + } + frame_hier = NULL; + hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile_empty, sizeof(framed_xfile_empty) - 1, D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
From: Paul Gofman pgofman@codeweavers.com
--- dlls/d3dx9_36/mesh.c | 17 ++++++++++------- dlls/d3dx9_36/tests/mesh.c | 38 ++++++++++++++++---------------------- 2 files changed, 26 insertions(+), 29 deletions(-)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c index d6c13007126..7b2b91c0590 100644 --- a/dlls/d3dx9_36/mesh.c +++ b/dlls/d3dx9_36/mesh.c @@ -3880,7 +3880,7 @@ static HRESULT parse_transform_matrix(ID3DXFileData *filedata, D3DXMATRIX *trans }
static HRESULT load_frame(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device, - struct ID3DXAllocateHierarchy *alloc_hier, D3DXFRAME **frame_out) + struct ID3DXAllocateHierarchy *alloc_hier, D3DXFRAME **frame_out, struct ID3DXLoadUserData *load_user_data) { HRESULT hr; GUID type; @@ -3923,9 +3923,12 @@ static HRESULT load_frame(struct ID3DXFileData *filedata, DWORD options, struct } else if (IsEqualGUID(&type, &TID_D3DRMFrameTransformMatrix)) { hr = parse_transform_matrix(child, &frame->TransformationMatrix); } else if (IsEqualGUID(&type, &TID_D3DRMFrame)) { - hr = load_frame(child, options, device, alloc_hier, next_child); + hr = load_frame(child, options, device, alloc_hier, next_child, load_user_data); if (SUCCEEDED(hr)) next_child = &(*next_child)->pFrameSibling; + } else if (load_user_data) { + TRACE("Loading %s as user data.\n", debugstr_guid(&type)); + hr = load_user_data->lpVtbl->LoadFrameChildData(load_user_data, frame, child); } if (FAILED(hr)) goto err; @@ -3961,10 +3964,7 @@ HRESULT WINAPI D3DXLoadMeshHierarchyFromXInMemory(const void *memory, DWORD memo if (!memory || !memory_size || !device || !frame_hierarchy || !alloc_hier) return D3DERR_INVALIDCALL; if (load_user_data) - { - FIXME("Loading user data not implemented.\n"); - return E_NOTIMPL; - } + FIXME("Loading mesh user data not implemented for mesh.\n");
hr = D3DXFileCreate(&d3dxfile); if (FAILED(hr)) goto cleanup; @@ -4001,8 +4001,11 @@ HRESULT WINAPI D3DXLoadMeshHierarchyFromXInMemory(const void *memory, DWORD memo hr = load_mesh_container(filedata, options, device, alloc_hier, &(*next_frame)->pMeshContainer); if (FAILED(hr)) goto cleanup; } else if (IsEqualGUID(&guid, &TID_D3DRMFrame)) { - hr = load_frame(filedata, options, device, alloc_hier, next_frame); + hr = load_frame(filedata, options, device, alloc_hier, next_frame, load_user_data); if (FAILED(hr)) goto cleanup; + } else if (load_user_data) { + TRACE("Loading %s as user data.\n", debugstr_guid(&guid)); + hr = load_user_data->lpVtbl->LoadTopLevelData(load_user_data, filedata); } while (*next_frame) next_frame = &(*next_frame)->pFrameSibling; diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c index 6796a40b360..78752b641a2 100644 --- a/dlls/d3dx9_36/tests/mesh.c +++ b/dlls/d3dx9_36/tests/mesh.c @@ -2133,20 +2133,20 @@ static void check_user_data(struct test_load_user_data *user_data, unsigned int { unsigned int i;
- ok(user_data->data_count == expected_count, "got %u, expected %u.\n", user_data->data_count, expected_count); + todo_wine ok(user_data->data_count == expected_count, "got %u, expected %u.\n", user_data->data_count, expected_count); expected_count = min(expected_count, user_data->data_count); for (i = 0; i < expected_count; ++i) { winetest_push_context("i %u", i); - ok(user_data->data[i].data_type == expected[i].data_type, "got %u, expected %u.\n", + todo_wine_if(i == 3) ok(user_data->data[i].data_type == expected[i].data_type, "got %u, expected %u.\n", user_data->data[i].data_type, expected[i].data_type); ok(IsEqualGUID(&user_data->data[i].type, &expected[i].type), "got %s, expected %s.\n", debugstr_guid(&user_data->data[i].type), debugstr_guid(&expected[i].type)); ok(user_data->data[i].size == expected[i].size, "got %Iu, expected %Iu.\n", user_data->data[i].size, expected[i].size); - ok(user_data->data[i].value == expected[i].value, "got %u, expected %u.\n", + todo_wine_if(i == 3) ok(user_data->data[i].value == expected[i].value, "got %u, expected %u.\n", user_data->data[i].value, expected[i].value); - ok(user_data->data[i].mesh_container == expected[i].mesh_container, "got %u, expected %u.\n", + todo_wine_if(i == 3) ok(user_data->data[i].mesh_container == expected[i].mesh_container, "got %u, expected %u.\n", user_data->data[i].mesh_container, expected[i].mesh_container); ok(user_data->data[i].num_materials == expected[i].num_materials, "got %u, expected %u.\n", user_data->data[i].num_materials, expected[i].num_materials); @@ -2672,15 +2672,12 @@ static void D3DXLoadMeshTest(void) init_load_user_data(&load_user_data); hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1, D3DXMESH_MANAGED, device, &alloc_hier, &load_user_data.iface, &frame_hier, &controller); - todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); - if (SUCCEEDED(hr)) - { - winetest_push_context("box_xfile"); - check_user_data(&load_user_data, ARRAY_SIZE(box_xfile_expected_user_data), box_xfile_expected_user_data); - winetest_pop_context(); - hr = D3DXFrameDestroy(frame_hier, &alloc_hier); - ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); - } + ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); + winetest_push_context("box_xfile"); + check_user_data(&load_user_data, ARRAY_SIZE(box_xfile_expected_user_data), box_xfile_expected_user_data); + winetest_pop_context(); + hr = D3DXFrameDestroy(frame_hier, &alloc_hier); + ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); frame_hier = NULL;
hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1, @@ -2715,15 +2712,12 @@ static void D3DXLoadMeshTest(void) init_load_user_data(&load_user_data); hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1, D3DXMESH_MANAGED, device, &alloc_hier, &load_user_data.iface, &frame_hier, NULL); - todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); - if (SUCCEEDED(hr)) - { - hr = D3DXFrameDestroy(frame_hier, &alloc_hier); - ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); - winetest_push_context("framed_xfile"); - check_user_data(&load_user_data, ARRAY_SIZE(framed_xfile_expected_user_data), framed_xfile_expected_user_data); - winetest_pop_context(); - } + ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); + hr = D3DXFrameDestroy(frame_hier, &alloc_hier); + ok(hr == D3D_OK, "Expected D3D_OK, got %#lx\n", hr); + winetest_push_context("framed_xfile"); + check_user_data(&load_user_data, ARRAY_SIZE(framed_xfile_expected_user_data), framed_xfile_expected_user_data); + winetest_pop_context(); frame_hier = NULL;
hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile_empty, sizeof(framed_xfile_empty) - 1,
From: Paul Gofman pgofman@codeweavers.com
--- dlls/d3dx9_36/mesh.c | 92 ++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 42 deletions(-)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c index 7b2b91c0590..3a35a4caa91 100644 --- a/dlls/d3dx9_36/mesh.c +++ b/dlls/d3dx9_36/mesh.c @@ -37,6 +37,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+/* for provide_flags parameters */ +#define PROVIDE_MATERIALS 0x1 +#define PROVIDE_SKININFO 0x2 +#define PROVIDE_ADJACENCY 0x4 + struct d3dx9_mesh { ID3DXMesh ID3DXMesh_iface; @@ -2611,6 +2616,7 @@ struct mesh_data {
struct ID3DXSkinInfo *skin_info; unsigned int bone_count; + unsigned int skin_weights_info_count; };
static HRESULT parse_texture_filename(ID3DXFileData *filedata, char **filename_out) @@ -2752,7 +2758,7 @@ static void destroy_materials(struct mesh_data *mesh) mesh->material_indices = NULL; }
-static HRESULT parse_material_list(ID3DXFileData *filedata, struct mesh_data *mesh) +static HRESULT parse_material_list(ID3DXFileData *filedata, struct mesh_data *mesh, DWORD flags) { ID3DXFileData *child = NULL; unsigned int material_count; @@ -2764,6 +2770,9 @@ static HRESULT parse_material_list(ID3DXFileData *filedata, struct mesh_data *me HRESULT hr; GUID type;
+ if (!(flags & PROVIDE_MATERIALS)) + return S_OK; + destroy_materials(mesh);
hr = filedata->lpVtbl->Lock(filedata, &data_size, &data); @@ -2867,7 +2876,7 @@ end: return hr; }
-static HRESULT parse_texture_coords(ID3DXFileData *filedata, struct mesh_data *mesh) +static HRESULT parse_texture_coords(ID3DXFileData *filedata, struct mesh_data *mesh, DWORD flags) { const uint32_t *data; SIZE_T data_size; @@ -2925,7 +2934,7 @@ end: return hr; }
-static HRESULT parse_vertex_colors(ID3DXFileData *filedata, struct mesh_data *mesh) +static HRESULT parse_vertex_colors(ID3DXFileData *filedata, struct mesh_data *mesh, DWORD flags) { unsigned int color_count, i; const uint32_t *data; @@ -3004,7 +3013,7 @@ end: return hr; }
-static HRESULT parse_normals(ID3DXFileData *filedata, struct mesh_data *mesh) +static HRESULT parse_normals(ID3DXFileData *filedata, struct mesh_data *mesh, DWORD flags) { unsigned int num_face_indices = mesh->num_poly_faces * 2 + mesh->num_tri_faces; DWORD *index_out_ptr; @@ -3110,7 +3119,7 @@ end: return hr; }
-static HRESULT parse_skin_mesh_header(ID3DXFileData *filedata, struct mesh_data *mesh_data) +static HRESULT parse_skin_mesh_header(ID3DXFileData *filedata, struct mesh_data *mesh_data, DWORD flags) { const BYTE *data; SIZE_T data_size; @@ -3118,6 +3127,15 @@ static HRESULT parse_skin_mesh_header(ID3DXFileData *filedata, struct mesh_data
TRACE("filedata %p, mesh_data %p.\n", filedata, mesh_data);
+ if (!(flags & PROVIDE_SKININFO)) + return S_OK; + + if (mesh_data->skin_info) + { + WARN("Skin mesh header already encountered\n"); + return E_FAIL; + } + if (FAILED(hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void **)&data))) return hr;
@@ -3136,8 +3154,9 @@ static HRESULT parse_skin_mesh_header(ID3DXFileData *filedata, struct mesh_data return hr; }
-static HRESULT parse_skin_weights_info(ID3DXFileData *filedata, struct mesh_data *mesh_data, unsigned int index) +static HRESULT parse_skin_weights_info(ID3DXFileData *filedata, struct mesh_data *mesh_data, DWORD flags) { + unsigned int index = mesh_data->skin_weights_info_count; unsigned int influence_count; const char *name; const BYTE *data; @@ -3146,6 +3165,15 @@ static HRESULT parse_skin_weights_info(ID3DXFileData *filedata, struct mesh_data
TRACE("filedata %p, mesh_data %p, index %u.\n", filedata, mesh_data, index);
+ if (!(flags & PROVIDE_SKININFO)) + return S_OK; + + if (!mesh_data->skin_info) + { + WARN("Skin weights found but skin mesh header not encountered yet.\n"); + return E_FAIL; + } + if (FAILED(hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void **)&data))) return hr;
@@ -3173,17 +3201,13 @@ static HRESULT parse_skin_weights_info(ID3DXFileData *filedata, struct mesh_data hr = mesh_data->skin_info->lpVtbl->SetBoneOffsetMatrix(mesh_data->skin_info, index, (const D3DMATRIX *)(data + influence_count * (sizeof(uint32_t) + sizeof(float))));
+ if (SUCCEEDED(hr)) + ++mesh_data->skin_weights_info_count; return hr; }
-/* for provide_flags parameters */ -#define PROVIDE_MATERIALS 0x1 -#define PROVIDE_SKININFO 0x2 -#define PROVIDE_ADJACENCY 0x4 - static HRESULT parse_mesh(ID3DXFileData *filedata, struct mesh_data *mesh_data, DWORD provide_flags) { - unsigned int skin_weights_info_count = 0; ID3DXFileData *child = NULL; const BYTE *data, *in_ptr; DWORD *index_out_ptr; @@ -3203,6 +3227,8 @@ static HRESULT parse_mesh(ID3DXFileData *filedata, struct mesh_data *mesh_data, * } */
+ mesh_data->skin_weights_info_count = 0; + hr = filedata->lpVtbl->Lock(filedata, &data_size, (const void **)&data); if (FAILED(hr)) return hr;
@@ -3308,37 +3334,19 @@ static HRESULT parse_mesh(ID3DXFileData *filedata, struct mesh_data *mesh_data, goto end;
if (IsEqualGUID(&type, &TID_D3DRMMeshNormals)) { - hr = parse_normals(child, mesh_data); + hr = parse_normals(child, mesh_data, provide_flags); } else if (IsEqualGUID(&type, &TID_D3DRMMeshVertexColors)) { - hr = parse_vertex_colors(child, mesh_data); + hr = parse_vertex_colors(child, mesh_data, provide_flags); } else if (IsEqualGUID(&type, &TID_D3DRMMeshTextureCoords)) { - hr = parse_texture_coords(child, mesh_data); - } else if (IsEqualGUID(&type, &TID_D3DRMMeshMaterialList) && - (provide_flags & PROVIDE_MATERIALS)) - { - hr = parse_material_list(child, mesh_data); - } else if (provide_flags & PROVIDE_SKININFO) { - if (IsEqualGUID(&type, &DXFILEOBJ_XSkinMeshHeader)) { - if (mesh_data->skin_info) { - WARN("Skin mesh header already encountered\n"); - hr = E_FAIL; - goto end; - } - hr = parse_skin_mesh_header(child, mesh_data); - if (FAILED(hr)) - goto end; - } else if (IsEqualGUID(&type, &DXFILEOBJ_SkinWeights)) { - if (!mesh_data->skin_info) { - WARN("Skin weights found but skin mesh header not encountered yet\n"); - hr = E_FAIL; - goto end; - } - hr = parse_skin_weights_info(child, mesh_data, skin_weights_info_count); - if (FAILED(hr)) - goto end; - skin_weights_info_count++; - } + hr = parse_texture_coords(child, mesh_data, provide_flags); + } else if (IsEqualGUID(&type, &TID_D3DRMMeshMaterialList)) { + hr = parse_material_list(child, mesh_data, provide_flags); + } else if (IsEqualGUID(&type, &DXFILEOBJ_XSkinMeshHeader)) { + hr = parse_skin_mesh_header(child, mesh_data, provide_flags); + } else if (IsEqualGUID(&type, &DXFILEOBJ_SkinWeights)) { + hr = parse_skin_weights_info(child, mesh_data, provide_flags); } + if (FAILED(hr)) goto end;
@@ -3346,10 +3354,10 @@ static HRESULT parse_mesh(ID3DXFileData *filedata, struct mesh_data *mesh_data, child = NULL; }
- if (mesh_data->skin_info && (skin_weights_info_count != mesh_data->bone_count)) + if (mesh_data->skin_info && (mesh_data->skin_weights_info_count != mesh_data->bone_count)) { WARN("Mismatch between skin weights info count %u and bones count %u from skin mesh header.\n", - skin_weights_info_count, mesh_data->bone_count); + mesh_data->skin_weights_info_count, mesh_data->bone_count); hr = E_FAIL; goto end; }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/d3dx9_36/mesh.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c index 3a35a4caa91..338ca1eaefe 100644 --- a/dlls/d3dx9_36/mesh.c +++ b/dlls/d3dx9_36/mesh.c @@ -3206,9 +3206,37 @@ static HRESULT parse_skin_weights_info(ID3DXFileData *filedata, struct mesh_data return hr; }
+typedef HRESULT (*mesh_parse_func)(ID3DXFileData *, struct mesh_data *, DWORD); + +static mesh_parse_func mesh_get_parse_func(const GUID *type) +{ + static const struct + { + const GUID *type; + mesh_parse_func func; + } + funcs[] = + { + {&TID_D3DRMMeshNormals, parse_normals}, + {&TID_D3DRMMeshVertexColors, parse_vertex_colors}, + {&TID_D3DRMMeshTextureCoords, parse_texture_coords}, + {&TID_D3DRMMeshMaterialList, parse_material_list}, + {&DXFILEOBJ_XSkinMeshHeader, parse_skin_mesh_header}, + {&DXFILEOBJ_SkinWeights, parse_skin_weights_info}, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(funcs); ++i) + if (IsEqualGUID(type, funcs[i].type)) + return funcs[i].func; + + return NULL; +} + static HRESULT parse_mesh(ID3DXFileData *filedata, struct mesh_data *mesh_data, DWORD provide_flags) { ID3DXFileData *child = NULL; + mesh_parse_func parse_func; const BYTE *data, *in_ptr; DWORD *index_out_ptr; SIZE_T child_count; @@ -3333,20 +3361,8 @@ static HRESULT parse_mesh(ID3DXFileData *filedata, struct mesh_data *mesh_data, if (FAILED(hr)) goto end;
- if (IsEqualGUID(&type, &TID_D3DRMMeshNormals)) { - hr = parse_normals(child, mesh_data, provide_flags); - } else if (IsEqualGUID(&type, &TID_D3DRMMeshVertexColors)) { - hr = parse_vertex_colors(child, mesh_data, provide_flags); - } else if (IsEqualGUID(&type, &TID_D3DRMMeshTextureCoords)) { - hr = parse_texture_coords(child, mesh_data, provide_flags); - } else if (IsEqualGUID(&type, &TID_D3DRMMeshMaterialList)) { - hr = parse_material_list(child, mesh_data, provide_flags); - } else if (IsEqualGUID(&type, &DXFILEOBJ_XSkinMeshHeader)) { - hr = parse_skin_mesh_header(child, mesh_data, provide_flags); - } else if (IsEqualGUID(&type, &DXFILEOBJ_SkinWeights)) { - hr = parse_skin_weights_info(child, mesh_data, provide_flags); - } - + if ((parse_func = mesh_get_parse_func(&type))) + hr = parse_func(child, mesh_data, provide_flags); if (FAILED(hr)) goto end;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/d3dx9_36/mesh.c | 49 ++++++++++++++++++++++++++++---------- dlls/d3dx9_36/tests/mesh.c | 8 +++---- 2 files changed, 41 insertions(+), 16 deletions(-)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c index 338ca1eaefe..7d2b2c0071d 100644 --- a/dlls/d3dx9_36/mesh.c +++ b/dlls/d3dx9_36/mesh.c @@ -3830,7 +3830,8 @@ static HRESULT filedata_get_name(ID3DXFileData *filedata, char **name) }
static HRESULT load_mesh_container(struct ID3DXFileData *filedata, DWORD options, struct IDirect3DDevice9 *device, - struct ID3DXAllocateHierarchy *alloc_hier, D3DXMESHCONTAINER **mesh_container) + struct ID3DXAllocateHierarchy *alloc_hier, D3DXMESHCONTAINER **mesh_container, + struct ID3DXLoadUserData *load_user_data) { HRESULT hr; ID3DXBuffer *adjacency = NULL; @@ -3840,6 +3841,10 @@ static HRESULT load_mesh_container(struct ID3DXFileData *filedata, DWORD options D3DXMESHDATA mesh_data; DWORD num_materials = 0; char *name = NULL; + SIZE_T child_count; + ID3DXFileData *child = NULL; + GUID type; + unsigned int i;
mesh_data.Type = D3DXMESHTYPE_MESH; mesh_data.pMesh = NULL; @@ -3852,17 +3857,38 @@ static HRESULT load_mesh_container(struct ID3DXFileData *filedata, DWORD options hr = filedata_get_name(filedata, &name); if (FAILED(hr)) goto cleanup;
- if (mesh_data.pMesh) + if (!mesh_data.pMesh) + goto cleanup; + hr = alloc_hier->lpVtbl->CreateMeshContainer(alloc_hier, name, &mesh_data, + materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL, + effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL, + num_materials, + adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL, + skin_info, mesh_container); + if (FAILED(hr) || !load_user_data) + goto cleanup; + + hr = filedata->lpVtbl->GetChildren(filedata, &child_count); + if (FAILED(hr)) + goto cleanup; + + for (i = 0; i < child_count; i++) { - hr = alloc_hier->lpVtbl->CreateMeshContainer(alloc_hier, name, &mesh_data, - materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL, - effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL, - num_materials, - adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL, - skin_info, mesh_container); + if (FAILED(hr = filedata->lpVtbl->GetChild(filedata, i, &child))) + goto cleanup; + if (FAILED(hr = child->lpVtbl->GetType(child, &type))) + goto cleanup; + + if (!mesh_get_parse_func(&type) + && FAILED(hr = load_user_data->lpVtbl->LoadMeshChildData(load_user_data, *mesh_container, child))) + goto cleanup; + + IUnknown_Release(child); + child = NULL; }
cleanup: + if (child) IUnknown_Release(child); if (materials) ID3DXBuffer_Release(materials); if (effects) ID3DXBuffer_Release(effects); if (adjacency) ID3DXBuffer_Release(adjacency); @@ -3941,7 +3967,7 @@ static HRESULT load_frame(struct ID3DXFileData *filedata, DWORD options, struct goto err;
if (IsEqualGUID(&type, &TID_D3DRMMesh)) { - hr = load_mesh_container(child, options, device, alloc_hier, next_container); + hr = load_mesh_container(child, options, device, alloc_hier, next_container, load_user_data); if (SUCCEEDED(hr)) next_container = &(*next_container)->pNextMeshContainer; } else if (IsEqualGUID(&type, &TID_D3DRMFrameTransformMatrix)) { @@ -3987,8 +4013,6 @@ HRESULT WINAPI D3DXLoadMeshHierarchyFromXInMemory(const void *memory, DWORD memo
if (!memory || !memory_size || !device || !frame_hierarchy || !alloc_hier) return D3DERR_INVALIDCALL; - if (load_user_data) - FIXME("Loading mesh user data not implemented for mesh.\n");
hr = D3DXFileCreate(&d3dxfile); if (FAILED(hr)) goto cleanup; @@ -4022,7 +4046,8 @@ HRESULT WINAPI D3DXLoadMeshHierarchyFromXInMemory(const void *memory, DWORD memo
D3DXMatrixIdentity(&(*next_frame)->TransformationMatrix);
- hr = load_mesh_container(filedata, options, device, alloc_hier, &(*next_frame)->pMeshContainer); + hr = load_mesh_container(filedata, options, device, alloc_hier, &(*next_frame)->pMeshContainer, + load_user_data); if (FAILED(hr)) goto cleanup; } else if (IsEqualGUID(&guid, &TID_D3DRMFrame)) { hr = load_frame(filedata, options, device, alloc_hier, next_frame, load_user_data); diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c index 78752b641a2..b00b0105963 100644 --- a/dlls/d3dx9_36/tests/mesh.c +++ b/dlls/d3dx9_36/tests/mesh.c @@ -2133,20 +2133,20 @@ static void check_user_data(struct test_load_user_data *user_data, unsigned int { unsigned int i;
- todo_wine ok(user_data->data_count == expected_count, "got %u, expected %u.\n", user_data->data_count, expected_count); + ok(user_data->data_count == expected_count, "got %u, expected %u.\n", user_data->data_count, expected_count); expected_count = min(expected_count, user_data->data_count); for (i = 0; i < expected_count; ++i) { winetest_push_context("i %u", i); - todo_wine_if(i == 3) ok(user_data->data[i].data_type == expected[i].data_type, "got %u, expected %u.\n", + ok(user_data->data[i].data_type == expected[i].data_type, "got %u, expected %u.\n", user_data->data[i].data_type, expected[i].data_type); ok(IsEqualGUID(&user_data->data[i].type, &expected[i].type), "got %s, expected %s.\n", debugstr_guid(&user_data->data[i].type), debugstr_guid(&expected[i].type)); ok(user_data->data[i].size == expected[i].size, "got %Iu, expected %Iu.\n", user_data->data[i].size, expected[i].size); - todo_wine_if(i == 3) ok(user_data->data[i].value == expected[i].value, "got %u, expected %u.\n", + ok(user_data->data[i].value == expected[i].value, "got %u, expected %u.\n", user_data->data[i].value, expected[i].value); - todo_wine_if(i == 3) ok(user_data->data[i].mesh_container == expected[i].mesh_container, "got %u, expected %u.\n", + ok(user_data->data[i].mesh_container == expected[i].mesh_container, "got %u, expected %u.\n", user_data->data[i].mesh_container, expected[i].mesh_container); ok(user_data->data[i].num_materials == expected[i].num_materials, "got %u, expected %u.\n", user_data->data[i].num_materials, expected[i].num_materials);
Matteo Bruni (@Mystral) commented about include/d3dx9anim.h:
#define INTERFACE ID3DXLoadUserData DECLARE_INTERFACE(ID3DXLoadUserData) {
- STDMETHOD(LoadTopLevelData)(ID3DXFileData *child_data) PURE;
- STDMETHOD(LoadFrameChildData)(D3DXFRAME *frame, ID3DXFileData *child_data) PURE;
- STDMETHOD(LoadMeshChildData)(D3DXMESHCONTAINER *mesh_container, ID3DXFileData *child_data) PURE;
- STDMETHOD(LoadTopLevelData)(ID3DXLoadUserData *user_data, ID3DXFileData *child_data) PURE;
- STDMETHOD(LoadFrameChildData)(ID3DXLoadUserData *user_data, D3DXFRAME *frame, ID3DXFileData *child_data) PURE;
- STDMETHOD(LoadMeshChildData)(ID3DXLoadUserData *user_data, D3DXMESHCONTAINER *mesh_container, ID3DXFileData *child_data) PURE;
Soooo, this is awkward...
This would be more idiomatic as: ``` STDMETHOD(LoadTopLevelData)(THIS_ ID3DXFileData *child_data) PURE; ``` and such. But that's no big deal.
Except, in all the copies of the DX SDK I have readily around (30, 41 and 43, for the records) the MS header is incredibly missing the This pointer as well :expressionless:
We probably still want the correct definitions but this is quite unfortunate. I'd at least add a comment clarifying that we're intentionally diverging from the broken DX SDK header here.
I'll review the rest of the MR later today.
On Wed Nov 22 08:15:30 2023 +0000, Matteo Bruni wrote:
Soooo, this is awkward... This would be more idiomatic as:
STDMETHOD(LoadTopLevelData)(THIS_ ID3DXFileData *child_data) PURE;
and such. But that's no big deal. Except, in all the copies of the DX SDK I have readily around (30, 41 and 43, for the records) the MS header is incredibly missing the This pointer as well :expressionless: We probably still want the correct definitions but this is quite unfortunate. I'd at least add a comment clarifying that we're intentionally diverging from the broken DX SDK header here.
As an alternative we could use private definition in implementation and test, but not sure if keeping the broken definition in public headers helps anything?
As an alternative we could use private definition in implementation and test, but not sure if keeping the broken definition in public headers helps anything?
No, it don't see how. It's just annoying, a comment to document MS's mess would do it I think.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/mesh.c:
+{
- ID3DXLoadUserData iface;
- unsigned int data_count;
- struct test_user_data data[MAX_USER_DATA_COUNT];
+};
+static void record_common_user_data(struct test_load_user_data *data, ID3DXFileData *filedata,
enum user_data_type data_type)
+{
- struct test_user_data *d = &data->data[data->data_count];
- const void *ptr;
- HRESULT hr;
- SIZE_T sz;
- ok(data->data_count < MAX_USER_DATA_COUNT, "got %u.\n", data->data_count);
Isn't this checking that the test doesn't exceed its own upper limit? It doesn't seem like it should be an ok(); maybe an assert?
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/mesh.c:
{ unsigned int i;
- todo_wine ok(user_data->data_count == expected_count, "got %u, expected %u.\n", user_data->data_count, expected_count);
- ok(user_data->data_count == expected_count, "got %u, expected %u.\n", user_data->data_count, expected_count); expected_count = min(expected_count, user_data->data_count);
Nitpick, this could be simplified at this point.
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/mesh.c:
"}" "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 3.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" "}";
- struct test_user_data framed_xfile_expected_user_data[] =
Here and below, it should be static const (the check_user_data() prototype also needs to be updated).
Matteo Bruni (@Mystral) commented about dlls/d3dx9_36/tests/mesh.c:
+}
+static struct test_load_user_data *impl_from_ID3DXLoadUserData(ID3DXLoadUserData *iface) +{
- return CONTAINING_RECORD(iface, struct test_load_user_data, iface);
+}
+static HRESULT STDMETHODCALLTYPE load_top_level_data(ID3DXLoadUserData *iface, ID3DXFileData *filedata) +{
- struct test_load_user_data *user_data = impl_from_ID3DXLoadUserData(iface);
- record_common_user_data(user_data, filedata, USER_DATA_TYPE_TOP);
- return S_OK;
+} +static HRESULT STDMETHODCALLTYPE load_frame_child_data(ID3DXLoadUserData *iface, D3DXFRAME *frame,
ID3DXFileData *filedata)
Nitpick, there should be a blank line between these two functions.
This seems generally good. I left a few minor comments and I'd prefer to have the couple of tweaks I previously mentioned about patch 1/6 (THIS_ instead of the explicit "This" pointer and an additional comment mentioning that we're intentionally diverging from MS's header since it's broken).