d3drm: Handle all materials in material list and create corresponding mesh groups + tests.

This commit is contained in:
Christian Costa 2012-12-13 10:03:11 +01:00 committed by Alexandre Julliard
parent 39222f6ab7
commit 7a5b12c8ef
2 changed files with 307 additions and 79 deletions

View File

@ -59,6 +59,12 @@ typedef struct {
D3DVALUE v;
} Coords2d;
typedef struct {
D3DCOLOR color;
IDirect3DRMMaterial2 *material;
IDirect3DRMTexture3 *texture;
} mesh_material;
typedef struct {
IDirect3DRMMeshBuilder2 IDirect3DRMMeshBuilder2_iface;
IDirect3DRMMeshBuilder3 IDirect3DRMMeshBuilder3_iface;
@ -72,10 +78,13 @@ typedef struct {
DWORD face_data_size;
LPVOID pFaceData;
DWORD nb_coords2d;
Coords2d* pCoords2d;
Coords2d *pCoords2d;
D3DCOLOR color;
IDirect3DRMMaterial2* material;
IDirect3DRMTexture3* texture;
IDirect3DRMMaterial2 *material;
IDirect3DRMTexture3 *texture;
DWORD nb_materials;
mesh_material *materials;
DWORD *material_indices;
} IDirect3DRMMeshBuilderImpl;
char templates[] = {
@ -316,6 +325,8 @@ static inline IDirect3DRMMeshBuilderImpl *impl_from_IDirect3DRMMeshBuilder3(IDir
static void clean_mesh_builder_data(IDirect3DRMMeshBuilderImpl *mesh_builder)
{
int i;
HeapFree(GetProcessHeap(), 0, mesh_builder->name);
mesh_builder->name = NULL;
HeapFree(GetProcessHeap(), 0, mesh_builder->pVertices);
@ -331,6 +342,16 @@ static void clean_mesh_builder_data(IDirect3DRMMeshBuilderImpl *mesh_builder)
HeapFree(GetProcessHeap(), 0, mesh_builder->pCoords2d);
mesh_builder->pCoords2d = NULL;
mesh_builder->nb_coords2d = 0;
for (i = 0; i < mesh_builder->nb_materials; i++)
{
if (mesh_builder->materials[i].material)
IDirect3DRMMaterial2_Release(mesh_builder->materials[i].material);
if (mesh_builder->materials[i].texture)
IDirect3DRMTexture3_Release(mesh_builder->materials[i].texture);
}
mesh_builder->nb_materials = 0;
HeapFree(GetProcessHeap(), 0, mesh_builder->materials);
HeapFree(GetProcessHeap(), 0, mesh_builder->material_indices);
}
/*** IUnknown methods ***/
@ -1251,24 +1272,25 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3* iface, LPDIRECTXFILEDATA pData)
if (size != data_size)
WARN("Returned size %u does not match expected one %u\n", size, data_size);
if (nb_materials > 1)
FIXME("Only one material per mesh supported, first one applies to all faces\n");
This->material_indices = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->material_indices) * nb_face_indices);
if (!This->material_indices)
goto end;
memcpy(This->material_indices, ptr + 2 * sizeof(DWORD), sizeof(*This->material_indices) * nb_face_indices),
This->materials = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->materials) * nb_materials);
if (!This->materials)
{
HeapFree(GetProcessHeap(), 0, This->material_indices);
goto end;
}
This->nb_materials = nb_materials;
while (SUCCEEDED(hr = IDirectXFileData_GetNextObject(pData2, &child)) && (i < nb_materials))
{
LPDIRECTXFILEDATA data;
LPDIRECTXFILEDATAREFERENCE reference;
LPDIRECT3DRMMATERIAL2 material;
LPDIRECTXFILEOBJECT material_child;
if (i >= 1)
{
/* FIXME: Only handle first material but enum all of them */
IDirectXFileObject_Release(child);
i++;
continue;
}
hr = IDirectXFileObject_QueryInterface(child, &IID_IDirectXFileData, (void **)&data);
if (FAILED(hr))
{
@ -1287,7 +1309,7 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3* iface, LPDIRECTXFILEDATA pData)
IDirectXFileObject_Release(child);
}
hr = Direct3DRMMaterial_create(&material);
hr = Direct3DRMMaterial_create(&This->materials[i].material);
if (FAILED(hr))
{
IDirectXFileData_Release(data);
@ -1306,20 +1328,20 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3* iface, LPDIRECTXFILEDATA pData)
values = (float*)ptr;
IDirect3DRMMeshBuilder3_SetColorRGB(iface, values[0], values [1], values[2]); /* Alpha ignored */
This->materials[i].color = D3DCOLOR_ARGB((BYTE)(values[3] * 255.0f), (BYTE)(values[0] * 255.0f),
(BYTE)(values[1] * 255.0f), (BYTE)(values[2] * 255.0f));
IDirect3DRMMaterial2_SetAmbient(material, values[0], values [1], values[2]); /* Alpha ignored */
IDirect3DRMMaterial2_SetPower(material, values[4]);
IDirect3DRMMaterial2_SetSpecular(material, values[5], values[6], values[7]);
IDirect3DRMMaterial2_SetEmissive(material, values[8], values[9], values[10]);
IDirect3DRMMaterial2_SetAmbient(This->materials[i].material, values[0], values [1], values[2]); /* Alpha ignored */
IDirect3DRMMaterial2_SetPower(This->materials[i].material, values[4]);
IDirect3DRMMaterial2_SetSpecular(This->materials[i].material, values[5], values[6], values[7]);
IDirect3DRMMaterial2_SetEmissive(This->materials[i].material, values[8], values[9], values[10]);
This->material = material;
This->materials[i].texture = NULL;
hr = IDirectXFileData_GetNextObject(data, &material_child);
if (hr == S_OK)
{
LPDIRECTXFILEDATA data;
LPDIRECT3DRMTEXTURE3 texture;
char** filename;
hr = IDirectXFileObject_QueryInterface(material_child, &IID_IDirectXFileData, (void **)&data);
@ -1352,16 +1374,18 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3* iface, LPDIRECTXFILEDATA pData)
{
HANDLE file;
/* If the texture file is not found, no texture is associated with the material */
file = CreateFileA(*filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (file != INVALID_HANDLE_VALUE)
{
hr = Direct3DRMTexture_create(&IID_IDirect3DRMTexture3, (LPUNKNOWN*)&texture);
CloseHandle(file);
hr = Direct3DRMTexture_create(&IID_IDirect3DRMTexture3, (LPUNKNOWN*)&This->materials[i].texture);
if (FAILED(hr))
{
IDirectXFileData_Release(data);
goto end;
}
This->texture = texture;
}
}
}
@ -2048,7 +2072,6 @@ static HRESULT WINAPI IDirect3DRMMeshBuilder3Impl_CreateMesh(IDirect3DRMMeshBuil
IDirect3DRMMeshBuilderImpl *This = impl_from_IDirect3DRMMeshBuilder3(iface);
HRESULT hr;
D3DRMGROUPINDEX group;
ULONG vertex_per_face = 0;
TRACE("(%p)->(%p)\n", This, mesh);
@ -2062,10 +2085,7 @@ static HRESULT WINAPI IDirect3DRMMeshBuilder3Impl_CreateMesh(IDirect3DRMMeshBuil
/* If there is mesh data, create a group and put data inside */
if (This->nb_vertices)
{
unsigned* face_data;
unsigned* out_ptr;
DWORD* in_ptr = This->pFaceData;
int i, j;
int i, j, k;
D3DRMVERTEX* vertices;
vertices = HeapAlloc(GetProcessHeap(), 0, This->nb_vertices * sizeof(D3DRMVERTEX));
@ -2079,63 +2099,103 @@ static HRESULT WINAPI IDirect3DRMMeshBuilder3Impl_CreateMesh(IDirect3DRMMeshBuil
hr = IDirect3DRMMesh_SetVertices(*mesh, 0, 0, This->nb_vertices, vertices);
HeapFree(GetProcessHeap(), 0, vertices);
face_data = HeapAlloc(GetProcessHeap(), 0, This->face_data_size * sizeof(DWORD));
if (!face_data)
/* Groups are in reverse order compared to materials list in X file */
for (k = This->nb_materials - 1; k >= 0; k--)
{
IDirect3DRMMesh_Release(*mesh);
return E_OUTOFMEMORY;
}
out_ptr = face_data;
unsigned* face_data;
unsigned* out_ptr;
DWORD* in_ptr = This->pFaceData;
ULONG vertex_per_face = 0;
BOOL* used_vertices;
unsigned nb_vertices = 0;
unsigned nb_faces = 0;
/* If all faces have the same number of vertex, set vertex_per_face */
for (i = 0; i < This->nb_faces; i++)
{
if (vertex_per_face && (vertex_per_face != *in_ptr))
break;
vertex_per_face = *in_ptr;
in_ptr += 1 + *in_ptr * 2;
}
if (i != This->nb_faces)
vertex_per_face = 0;
/* Put only vertex indices */
in_ptr = This->pFaceData;
for (i = 0; i < This->nb_faces; i++)
{
DWORD nb_indices = *in_ptr++;
/* Don't put nb indices when vertex_per_face is set */
if (vertex_per_face)
*out_ptr++ = nb_indices;
for (j = 0; j < nb_indices; j++)
used_vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->face_data_size * sizeof(*used_vertices));
if (!used_vertices)
{
*out_ptr++ = *in_ptr++;
/* Skip normal index */
in_ptr++;
IDirect3DRMMesh_Release(*mesh);
return E_OUTOFMEMORY;
}
face_data = HeapAlloc(GetProcessHeap(), 0, This->face_data_size * sizeof(*face_data));
if (!face_data)
{
IDirect3DRMMesh_Release(*mesh);
return E_OUTOFMEMORY;
}
out_ptr = face_data;
/* If all faces have the same number of vertex, set vertex_per_face */
for (i = 0; i < This->nb_faces; i++)
{
/* Process only faces belonging to the group */
if (This->material_indices[i] == k)
{
if (vertex_per_face && (vertex_per_face != *in_ptr))
break;
vertex_per_face = *in_ptr;
}
in_ptr += 1 + *in_ptr * 2;
}
if (i != This->nb_faces)
vertex_per_face = 0;
/* Put only vertex indices */
in_ptr = This->pFaceData;
for (i = 0; i < This->nb_faces; i++)
{
DWORD nb_indices = *in_ptr++;
/* Skip faces not belonging to the group */
if (This->material_indices[i] != k)
{
in_ptr += 2 * nb_indices;
continue;
}
/* Don't put nb indices when vertex_per_face is set */
if (vertex_per_face)
*out_ptr++ = nb_indices;
for (j = 0; j < nb_indices; j++)
{
*out_ptr = *in_ptr++;
used_vertices[*out_ptr++] = TRUE;
/* Skip normal index */
in_ptr++;
}
nb_faces++;
}
for (i = 0; i < This->nb_vertices; i++)
if (used_vertices[i])
nb_vertices++;
hr = IDirect3DRMMesh_AddGroup(*mesh, nb_vertices, nb_faces, vertex_per_face, face_data, &group);
HeapFree(GetProcessHeap(), 0, used_vertices);
HeapFree(GetProcessHeap(), 0, face_data);
if (SUCCEEDED(hr))
hr = IDirect3DRMMesh_SetGroupColor(*mesh, group, This->materials[k].color);
if (SUCCEEDED(hr))
hr = IDirect3DRMMesh_SetGroupMaterial(*mesh, group, (LPDIRECT3DRMMATERIAL)This->materials[k].material);
if (SUCCEEDED(hr) && This->materials[k].texture)
{
LPDIRECT3DRMTEXTURE texture;
IDirect3DRMTexture3_QueryInterface(This->materials[k].texture, &IID_IDirect3DRMTexture, (LPVOID*)&texture);
hr = IDirect3DRMMesh_SetGroupTexture(*mesh, group, texture);
IDirect3DRMTexture_Release(texture);
}
if (FAILED(hr))
{
IDirect3DRMMesh_Release(*mesh);
return hr;
}
}
hr = IDirect3DRMMesh_AddGroup(*mesh, This->nb_vertices, This->nb_faces, vertex_per_face, face_data, &group);
HeapFree(GetProcessHeap(), 0, face_data);
if (SUCCEEDED(hr))
hr = IDirect3DRMMesh_SetGroupColor(*mesh, 0, This->color);
if (SUCCEEDED(hr))
hr = IDirect3DRMMesh_SetGroupMaterial(*mesh, 0, (LPDIRECT3DRMMATERIAL)This->material);
if (SUCCEEDED(hr) && This->texture)
{
LPDIRECT3DRMTEXTURE texture;
IDirect3DRMTexture3_QueryInterface(This->texture, &IID_IDirect3DRMTexture, (LPVOID*)&texture);
hr = IDirect3DRMMesh_SetGroupTexture(*mesh, 0, texture);
IDirect3DRMTexture_Release(texture);
}
if (FAILED(hr))
IDirect3DRMMesh_Release(*mesh);
}
return hr;
return D3DRM_OK;
}
static HRESULT WINAPI IDirect3DRMMeshBuilder3Impl_GetFace(IDirect3DRMMeshBuilder3* iface,

View File

@ -180,6 +180,48 @@ static char data_d3drm_load[] =
" 0.9, 1.0, 1.1;;\n"
"}\n";
static char data_frame_mesh_materials[] =
"xof 0302txt 0064\n"
"Header { 1; 0; 1; }\n"
"Frame {\n"
" Mesh mesh1 {\n"
" 5;\n"
" 0.1; 0.2; 0.3;,\n"
" 0.4; 0.5; 0.6;,\n"
" 0.7; 0.8; 0.9;,\n"
" 1.1; 1.2; 1.3;,\n"
" 1.4; 1.5; 1.6;;\n"
" 6;\n"
" 3; 0, 1, 2;,\n"
" 3; 0, 2, 1;,\n"
" 3; 1, 2, 3;,\n"
" 3; 1, 3, 2;,\n"
" 3; 2, 3, 4;,\n"
" 3; 2, 4, 3;;\n"
" MeshMaterialList {\n"
" 3; 6; 0, 1, 1, 2, 2, 2;\n"
" Material mat1 {\n"
" 1.0; 0.0; 0.0; 0.1;;\n"
" 10.0;\n"
" 0.11; 0.12; 0.13;;\n"
" 0.14; 0.15; 0.16;;\n"
" }\n"
" Material mat2 {\n"
" 0.0; 1.0; 0.0; 0.2;;\n"
" 20.0;\n"
" 0.21; 0.22; 0.23;;\n"
" 0.24; 0.25; 0.26;;\n"
" }\n"
" Material mat3 {\n"
" 0.0; 0.0; 1.0; 0.3;;\n"
" 30.0;\n"
" 0.31; 0.32; 0.33;;\n"
" 0.34; 0.35; 0.36;;\n"
" }\n"
" }\n"
" }\n"
"}\n";
static void test_MeshBuilder(void)
{
HRESULT hr;
@ -1304,6 +1346,131 @@ static void test_d3drm_load(void)
IDirect3DRM_Release(pD3DRM);
}
IDirect3DRMMeshBuilder *mesh_builder = NULL;
static void __cdecl object_load_callback_frame(IDirect3DRMObject *object, REFIID object_guid, void *arg)
{
HRESULT hr;
IDirect3DRMFrame *frame;
IDirect3DRMVisualArray *array;
IDirect3DRMVisual *visual;
ULONG size;
char name[128];
hr = IDirect3DRMObject_QueryInterface(object, &IID_IDirect3DRMFrame, (void**)&frame);
ok(hr == D3DRM_OK, "IDirect3DRMObject_QueryInterface returned %x\n", hr);
hr = IDirect3DRMFrame_GetVisuals(frame, &array);
ok(hr == D3DRM_OK, "IDirect3DRMFrame_GetVisuals returned %x\n", hr);
size = IDirect3DRMVisualArray_GetSize(array);
ok(size == 1, "Wrong size %u returned, expected 1\n", size);
hr = IDirect3DRMVisualArray_GetElement(array, 0, &visual);
ok(hr == D3DRM_OK, "IDirect3DRMVisualArray_GetElement returned %x\n", hr);
hr = IDirect3DRMVisual_QueryInterface(visual, &IID_IDirect3DRMMeshBuilder, (void**)&mesh_builder);
ok(hr == D3DRM_OK, "IDirect3DRMVisualArray_GetSize returned %x\n", hr);
size = sizeof(name);
hr = IDirect3DRMMeshBuilder_GetName(mesh_builder, &size, name);
ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned %x\n", hr);
ok(!strcmp(name, "mesh1"), "Wrong name %s, expected mesh1\n", name);
IDirect3DRMVisual_Release(visual);
IDirect3DRMVisualArray_Release(array);
IDirect3DRMFrame_Release(frame);
}
struct {
int vertex_count;
int face_count;
int vertex_per_face;
int face_data_size;
DWORD color;
float power;
float specular[3];
float emissive[3];
} groups[3] = {
{ 4, 3, 3, 9, 0x4c0000ff, 30.0f, { 0.31f, 0.32f, 0.33f }, { 0.34f, 0.35f, 0.36f } },
{ 4, 2, 3, 6, 0x3300ff00, 20.0f, { 0.21f, 0.22f, 0.23f }, { 0.24f, 0.25f, 0.26f } },
{ 3, 1, 3, 3, 0x19ff0000, 10.0f, { 0.11f, 0.12f, 0.13f }, { 0.14f, 0.15f, 0.16f } }
};
static void test_frame_mesh_materials(void)
{
HRESULT hr;
IDirect3DRM *d3drm;
D3DRMLOADMEMORY info;
const GUID *req_refiids[] = { &IID_IDirect3DRMFrame };
IDirect3DRMMesh *mesh;
ULONG size;
IDirect3DRMMaterial *material;
IDirect3DRMTexture *texture;
int i;
hr = pDirect3DRMCreate(&d3drm);
ok(hr == D3DRM_OK, "Direct3DRMCreate returned %x\n", hr);
info.lpMemory = data_frame_mesh_materials;
info.dSize = strlen(data_frame_mesh_materials);
hr = IDirect3DRM_Load(d3drm, &info, NULL, (GUID**)req_refiids, 1, D3DRMLOAD_FROMMEMORY, object_load_callback_frame, (void*)0xdeadbeef, NULL, NULL, NULL);
ok(hr == D3DRM_OK, "Cannot load data (hr = %x)\n", hr);
hr = IDirect3DRMMeshBuilder_CreateMesh(mesh_builder, &mesh);
ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_CreateMesh returned %x\n", hr);
size = IDirect3DRMMesh_GetGroupCount(mesh);
ok(size == 3, "Wrong size %u returned, expected 3\n", size);
for (i = 0; i < size; i++)
{
D3DVALUE red, green, blue, power;
D3DCOLOR color;
unsigned vertex_count, face_count, vertex_per_face;
DWORD face_data_size;
hr = IDirect3DRMMesh_GetGroup(mesh, i, &vertex_count, &face_count, &vertex_per_face, &face_data_size, NULL);
ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroup returned %x\n", i, hr);
ok(vertex_count == groups[i].vertex_count, "Group %d: Wrong vertex count %d, expected %d\n", i, vertex_count, groups[i].vertex_count);
ok(face_count == groups[i].face_count, "Group %d: Wrong face count %d; expected %d\n", i, face_count, groups[i].face_count);
ok(vertex_per_face == groups[i].vertex_per_face, "Group %d: Wrong vertex per face %d, expected %d\n", i, vertex_per_face, groups[i].vertex_per_face);
ok(face_data_size == groups[i].face_data_size, "Group %d: Wrong face data size %d, expected %d\n", i, face_data_size, groups[i].face_data_size);
color = IDirect3DRMMesh_GetGroupColor(mesh, i);
ok(color == groups[i].color, "Group %d: Wrong color %x, expected %x\n", i, color, groups[i].color);
hr = IDirect3DRMMesh_GetGroupMaterial(mesh, i, &material);
ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroupMaterial returned %x\n", i, hr);
ok(material != NULL, "Group %d: No material\n", i);
power = IDirect3DRMMaterial_GetPower(material);
ok(power == groups[i].power, "Group %d: Wrong power %f, expected %f\n", i, power, groups[i].power);
hr = IDirect3DRMMaterial_GetSpecular(material, &red, &green, &blue);
ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMaterial_GetSpecular returned %x\n", i, hr);
ok(red == groups[i].specular[0], "Group %d: Wrong specular red %f, expected %f\n", i, red, groups[i].specular[0]);
ok(green == groups[i].specular[1], "Group %d: Wrong specular green %f, pD3DRMexpected %f\n", i, green, groups[i].specular[1]);
ok(blue == groups[i].specular[2], "Group %d: Wrong specular blue %f, expected %f\n", i, blue, groups[i].specular[2]);
hr = IDirect3DRMMaterial_GetEmissive(material, &red, &green, &blue);
ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMaterial_GetEmissive returned %x\n", i, hr);
ok(red == groups[i].emissive[0], "Group %d: Wrong emissive red %f, expected %f\n", i, red, groups[i].emissive[0]);
ok(green == groups[i].emissive[1], "Group %d: Wrong emissive green %f, expected %f\n", i, green, groups[i].emissive[1]);
ok(blue == groups[i].emissive[2], "Group %d: Wrong emissive blue %f, expected %f\n", i, blue, groups[i].emissive[2]);
hr = IDirect3DRMMesh_GetGroupTexture(mesh, i, &texture);
ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroupTexture returned %x\n", i, hr);
ok(!texture, "Group %d: Unexpected texture\n", i);
if (material)
IDirect3DRMMaterial_Release(material);
if (texture)
IDirect3DRMTexture_Release(texture);
}
IDirect3DRMMesh_Release(mesh);
IDirect3DRMMeshBuilder_Release(mesh_builder);
IDirect3DRM_Release(d3drm);
}
START_TEST(d3drm)
{
if (!InitFunctionPtrs())
@ -1320,6 +1487,7 @@ START_TEST(d3drm)
test_Texture();
test_frame_transform();
test_d3drm_load();
test_frame_mesh_materials();
FreeLibrary(d3drm_handle);
}