d3dx9/tests: Add tests for D3DXLoadMeshHierarchyFromXInMemory.
This commit is contained in:
parent
39f94f3516
commit
420947c531
|
@ -18,11 +18,16 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define COBJMACROS
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
#include "wine/test.h"
|
||||
#include "d3dx9.h"
|
||||
|
||||
/* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
|
||||
* function call traces of ID3DXAllocateHierarchy callbacks. */
|
||||
#define TRACECALLBACK if(winetest_debug > 1) trace
|
||||
|
||||
#define admitted_error 0.0001f
|
||||
|
||||
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
|
||||
|
@ -48,6 +53,29 @@ static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
|
|||
return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
|
||||
}
|
||||
|
||||
#define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
|
||||
static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
|
||||
{
|
||||
int i;
|
||||
char exp_buffer[256] = "";
|
||||
char got_buffer[256] = "";
|
||||
char *exp_buffer_ptr = exp_buffer;
|
||||
char *got_buffer_ptr = got_buffer;
|
||||
BOOL equal = TRUE;
|
||||
|
||||
for (i = 0; i < dim; i++) {
|
||||
if (i) {
|
||||
exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
|
||||
got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
|
||||
}
|
||||
equal = equal && compare(*exp, *got);
|
||||
exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
|
||||
got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
|
||||
exp++, got++;
|
||||
}
|
||||
ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
|
||||
}
|
||||
|
||||
struct vertex
|
||||
{
|
||||
D3DXVECTOR3 position;
|
||||
|
@ -1370,6 +1398,539 @@ static void D3DXCreateMeshFVFTest(void)
|
|||
DestroyWindow(wnd);
|
||||
}
|
||||
|
||||
#define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
|
||||
check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
|
||||
static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
|
||||
{
|
||||
DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
|
||||
DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
|
||||
const void *mesh_vertices;
|
||||
HRESULT hr;
|
||||
|
||||
ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
|
||||
ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
|
||||
"Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
|
||||
|
||||
hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
|
||||
ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
if (mesh_fvf == fvf) {
|
||||
DWORD vertex_size = D3DXGetFVFVertexSize(fvf);
|
||||
int i;
|
||||
for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
|
||||
{
|
||||
const FLOAT *exp_float = vertices;
|
||||
const FLOAT *got_float = mesh_vertices;
|
||||
DWORD texcount;
|
||||
DWORD pos_dim = 0;
|
||||
int j;
|
||||
BOOL last_beta_dword = FALSE;
|
||||
char prefix[128];
|
||||
|
||||
switch (fvf & D3DFVF_POSITION_MASK) {
|
||||
case D3DFVF_XYZ: pos_dim = 3; break;
|
||||
case D3DFVF_XYZRHW: pos_dim = 4; break;
|
||||
case D3DFVF_XYZB1:
|
||||
case D3DFVF_XYZB2:
|
||||
case D3DFVF_XYZB3:
|
||||
case D3DFVF_XYZB4:
|
||||
case D3DFVF_XYZB5:
|
||||
pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
|
||||
if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
|
||||
{
|
||||
pos_dim--;
|
||||
last_beta_dword = TRUE;
|
||||
}
|
||||
break;
|
||||
case D3DFVF_XYZW: pos_dim = 4; break;
|
||||
}
|
||||
sprintf(prefix, "vertex[%u] position, ", i);
|
||||
check_floats_(line, prefix, got_float, exp_float, pos_dim);
|
||||
exp_float += pos_dim;
|
||||
got_float += pos_dim;
|
||||
|
||||
if (last_beta_dword) {
|
||||
ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
|
||||
"Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
|
||||
exp_float++;
|
||||
got_float++;
|
||||
}
|
||||
|
||||
if (fvf & D3DFVF_NORMAL) {
|
||||
sprintf(prefix, "vertex[%u] normal, ", i);
|
||||
check_floats_(line, prefix, got_float, exp_float, 3);
|
||||
exp_float += 3;
|
||||
got_float += 3;
|
||||
}
|
||||
if (fvf & D3DFVF_PSIZE) {
|
||||
ok_(__FILE__,line)(compare(*exp_float, *got_float),
|
||||
"Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
|
||||
exp_float++;
|
||||
got_float++;
|
||||
}
|
||||
if (fvf & D3DFVF_DIFFUSE) {
|
||||
ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
|
||||
"Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
|
||||
exp_float++;
|
||||
got_float++;
|
||||
}
|
||||
if (fvf & D3DFVF_SPECULAR) {
|
||||
ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
|
||||
"Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
|
||||
exp_float++;
|
||||
got_float++;
|
||||
}
|
||||
|
||||
texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
|
||||
for (j = 0; j < texcount; j++) {
|
||||
DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
|
||||
sprintf(prefix, "vertex[%u] texture, ", i);
|
||||
check_floats_(line, prefix, got_float, exp_float, dim);
|
||||
exp_float += dim;
|
||||
got_float += dim;
|
||||
}
|
||||
|
||||
vertices = (BYTE*)vertices + vertex_size;
|
||||
mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
|
||||
}
|
||||
}
|
||||
|
||||
mesh->lpVtbl->UnlockVertexBuffer(mesh);
|
||||
}
|
||||
|
||||
#define check_index_buffer(mesh, indices, num_indices, index_size) \
|
||||
check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
|
||||
static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
|
||||
{
|
||||
DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
|
||||
DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
|
||||
const void *mesh_indices;
|
||||
HRESULT hr;
|
||||
DWORD i;
|
||||
|
||||
ok_(__FILE__,line)(index_size == mesh_index_size,
|
||||
"Expected index size %u, got %u\n", index_size, mesh_index_size);
|
||||
ok_(__FILE__,line)(num_indices == mesh_num_indices,
|
||||
"Expected %u indices, got %u\n", num_indices, mesh_num_indices);
|
||||
|
||||
hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
|
||||
ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
if (mesh_index_size == index_size) {
|
||||
for (i = 0; i < min(num_indices, mesh_num_indices); i++)
|
||||
{
|
||||
if (index_size == 4)
|
||||
ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
|
||||
"Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
|
||||
else
|
||||
ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
|
||||
"Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
|
||||
indices = (BYTE*)indices + index_size;
|
||||
mesh_indices = (BYTE*)mesh_indices + index_size;
|
||||
}
|
||||
}
|
||||
mesh->lpVtbl->UnlockIndexBuffer(mesh);
|
||||
}
|
||||
|
||||
#define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
|
||||
static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
|
||||
"matrix[%u][%u]: expected %g, got %g\n",
|
||||
i, j, U(*expected).m[i][j], U(*got).m[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
|
||||
static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
|
||||
{
|
||||
DWORD *expected;
|
||||
DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
|
||||
HRESULT hr;
|
||||
|
||||
expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
|
||||
if (!expected) {
|
||||
skip_(__FILE__, line)("Out of memory\n");
|
||||
return;
|
||||
}
|
||||
hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
|
||||
ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_faces; i++)
|
||||
{
|
||||
ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
|
||||
expected[i * 3 + 1] == got[i * 3 + 1] &&
|
||||
expected[i * 3 + 2] == got[i * 3 + 2],
|
||||
"Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
|
||||
expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
|
||||
got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, expected);
|
||||
}
|
||||
|
||||
static LPSTR strdupA(LPCSTR p)
|
||||
{
|
||||
LPSTR ret;
|
||||
if (!p) return NULL;
|
||||
ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
|
||||
if (ret) strcpy(ret, p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
|
||||
{
|
||||
TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
|
||||
if (frame) {
|
||||
HeapFree(GetProcessHeap(), 0, frame->Name);
|
||||
HeapFree(GetProcessHeap(), 0, frame);
|
||||
}
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, LPCSTR name, LPD3DXFRAME *new_frame)
|
||||
{
|
||||
LPD3DXFRAME frame;
|
||||
|
||||
TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
|
||||
frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
|
||||
if (!frame)
|
||||
return E_OUTOFMEMORY;
|
||||
if (name) {
|
||||
frame->Name = strdupA(name);
|
||||
if (!frame->Name) {
|
||||
HeapFree(GetProcessHeap(), 0, frame);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
*new_frame = frame;
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mesh_container)
|
||||
return D3D_OK;
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->Name);
|
||||
if (U(mesh_container->MeshData).pMesh)
|
||||
IUnknown_Release(U(mesh_container->MeshData).pMesh);
|
||||
if (mesh_container->pMaterials) {
|
||||
for (i = 0; i < mesh_container->NumMaterials; i++)
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
|
||||
}
|
||||
if (mesh_container->pEffects) {
|
||||
for (i = 0; i < mesh_container->NumMaterials; i++) {
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
|
||||
if (mesh_container->pEffects[i].pDefaults) {
|
||||
int j;
|
||||
for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
|
||||
if (mesh_container->pSkinInfo)
|
||||
IUnknown_Release(mesh_container->pSkinInfo);
|
||||
HeapFree(GetProcessHeap(), 0, mesh_container);
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
|
||||
{
|
||||
TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
|
||||
return destroy_mesh_container(mesh_container);
|
||||
}
|
||||
|
||||
static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
|
||||
LPCSTR name, CONST D3DXMESHDATA *mesh_data, CONST D3DXMATERIAL *materials,
|
||||
CONST D3DXEFFECTINSTANCE *effects, DWORD num_materials, CONST DWORD *adjacency,
|
||||
LPD3DXSKININFO skin_info, LPD3DXMESHCONTAINER *new_mesh_container)
|
||||
{
|
||||
LPD3DXMESHCONTAINER mesh_container = NULL;
|
||||
int i;
|
||||
|
||||
TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
|
||||
iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
|
||||
num_materials, adjacency, skin_info, *new_mesh_container);
|
||||
|
||||
mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
|
||||
if (!mesh_container)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
if (name) {
|
||||
mesh_container->Name = strdupA(name);
|
||||
if (!mesh_container->Name)
|
||||
goto error;
|
||||
}
|
||||
|
||||
mesh_container->NumMaterials = num_materials;
|
||||
if (num_materials) {
|
||||
mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
|
||||
if (!mesh_container->pMaterials)
|
||||
goto error;
|
||||
|
||||
memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
|
||||
for (i = 0; i < num_materials; i++)
|
||||
mesh_container->pMaterials[i].pTextureFilename = NULL;
|
||||
for (i = 0; i < num_materials; i++) {
|
||||
if (materials[i].pTextureFilename) {
|
||||
mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
|
||||
if (!mesh_container->pMaterials[i].pTextureFilename)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
|
||||
if (!mesh_container->pEffects)
|
||||
goto error;
|
||||
for (i = 0; i < num_materials; i++) {
|
||||
int j;
|
||||
const D3DXEFFECTINSTANCE *effect_src = &effects[i];
|
||||
D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
|
||||
|
||||
if (effect_src->pEffectFilename) {
|
||||
effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
|
||||
if (!effect_dest->pEffectFilename)
|
||||
goto error;
|
||||
}
|
||||
effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
|
||||
if (!effect_dest->pDefaults)
|
||||
goto error;
|
||||
effect_dest->NumDefaults = effect_src->NumDefaults;
|
||||
for (j = 0; j < effect_src->NumDefaults; j++) {
|
||||
const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
|
||||
D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
|
||||
|
||||
if (default_src->pParamName) {
|
||||
default_dest->pParamName = strdupA(default_src->pParamName);
|
||||
if (!default_dest->pParamName)
|
||||
goto error;
|
||||
}
|
||||
default_dest->NumBytes = default_src->NumBytes;
|
||||
default_dest->Type = default_src->Type;
|
||||
default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
|
||||
memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
|
||||
if (adjacency) {
|
||||
if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
|
||||
ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
|
||||
DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
|
||||
size_t size = num_faces * sizeof(DWORD) * 3;
|
||||
mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (!mesh_container->pAdjacency)
|
||||
goto error;
|
||||
memcpy(mesh_container->pAdjacency, adjacency, size);
|
||||
} else {
|
||||
ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
|
||||
if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
|
||||
trace("FIXME: copying adjacency data for patch mesh not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
|
||||
if (U(*mesh_data).pMesh)
|
||||
IUnknown_AddRef(U(*mesh_data).pMesh);
|
||||
if (skin_info) {
|
||||
mesh_container->pSkinInfo = skin_info;
|
||||
skin_info->lpVtbl->AddRef(skin_info);
|
||||
}
|
||||
*new_mesh_container = mesh_container;
|
||||
|
||||
return S_OK;
|
||||
error:
|
||||
destroy_mesh_container(mesh_container);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
|
||||
ID3DXAllocateHierarchyImpl_CreateFrame,
|
||||
ID3DXAllocateHierarchyImpl_CreateMeshContainer,
|
||||
ID3DXAllocateHierarchyImpl_DestroyFrame,
|
||||
ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
|
||||
};
|
||||
static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
|
||||
|
||||
static void D3DXLoadMeshTest(void)
|
||||
{
|
||||
static const char empty_xfile[] = "xof 0303txt 0032";
|
||||
/*________________________*/
|
||||
static const char simple_xfile[] =
|
||||
"xof 0303txt 0032"
|
||||
"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;;"
|
||||
"}";
|
||||
static const WORD simple_index_buffer[] = {0, 1, 2};
|
||||
static const D3DXVECTOR3 simple_vertex_buffer[] = {
|
||||
{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
|
||||
};
|
||||
const DWORD simple_fvf = D3DFVF_XYZ;
|
||||
static const char framed_xfile[] =
|
||||
"xof 0303txt 0032"
|
||||
"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;; }"
|
||||
"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;;"
|
||||
"}"
|
||||
"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,"
|
||||
"0.0, 1.0, 0.0, 0.0,"
|
||||
"0.0, 0.0, 1.0, 0.0,"
|
||||
"0.0, 0.0, 3.0, 1.0;;"
|
||||
"}"
|
||||
"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;; }"
|
||||
"}";
|
||||
static const WORD framed_index_buffer[] = { 0, 1, 2 };
|
||||
static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
|
||||
{{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
|
||||
{{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
|
||||
{{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
|
||||
};
|
||||
const DWORD framed_fvf = D3DFVF_XYZ;
|
||||
/*________________________*/
|
||||
HRESULT hr;
|
||||
HWND wnd = NULL;
|
||||
IDirect3D9 *d3d = NULL;
|
||||
IDirect3DDevice9 *device = NULL;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
ID3DXMesh *mesh = NULL;
|
||||
D3DXFRAME *frame_hier = NULL;
|
||||
D3DXMATRIX transform;
|
||||
|
||||
wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
|
||||
if (!wnd)
|
||||
{
|
||||
skip("Couldn't create application window\n");
|
||||
return;
|
||||
}
|
||||
d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
if (!d3d)
|
||||
{
|
||||
skip("Couldn't create IDirect3D9 object\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ZeroMemory(&d3dpp, sizeof(d3dpp));
|
||||
d3dpp.Windowed = TRUE;
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
|
||||
D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
|
||||
ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
|
||||
|
||||
hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
|
||||
D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
|
||||
ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
|
||||
|
||||
hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
|
||||
D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
|
||||
ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
|
||||
|
||||
hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
|
||||
D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
|
||||
ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
|
||||
|
||||
hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
|
||||
D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
|
||||
ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
|
||||
|
||||
hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
|
||||
D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
|
||||
ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
|
||||
|
||||
hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
|
||||
D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
|
||||
ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
|
||||
if (SUCCEEDED(hr)) {
|
||||
D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
|
||||
|
||||
ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
|
||||
D3DXMatrixIdentity(&transform);
|
||||
check_matrix(&frame_hier->TransformationMatrix, &transform);
|
||||
|
||||
ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
|
||||
ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
|
||||
D3DXMESHTYPE_MESH, container->MeshData.Type);
|
||||
mesh = U(container->MeshData).pMesh;
|
||||
check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
|
||||
check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
|
||||
check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
|
||||
hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
|
||||
ok(hr == D3D_OK, "Expected D3D_OK, got %#x\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 %#x\n", hr);
|
||||
if (SUCCEEDED(hr)) {
|
||||
D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
|
||||
int i;
|
||||
|
||||
ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
|
||||
/* last frame transform replaces the first */
|
||||
D3DXMatrixIdentity(&transform);
|
||||
U(transform).m[3][2] = 3.0;
|
||||
check_matrix(&frame_hier->TransformationMatrix, &transform);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
|
||||
ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
|
||||
D3DXMESHTYPE_MESH, container->MeshData.Type);
|
||||
mesh = U(container->MeshData).pMesh;
|
||||
check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
|
||||
check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
|
||||
check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
|
||||
container = container->pNextMeshContainer;
|
||||
}
|
||||
ok(container == NULL, "Expected NULL, got %p\n", container);
|
||||
hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
|
||||
ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
|
||||
frame_hier = NULL;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (device) IDirect3DDevice9_Release(device);
|
||||
if (d3d) IDirect3D9_Release(d3d);
|
||||
if (wnd) DestroyWindow(wnd);
|
||||
}
|
||||
|
||||
static void D3DXCreateBoxTest(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -3314,6 +3875,7 @@ START_TEST(mesh)
|
|||
D3DXIntersectTriTest();
|
||||
D3DXCreateMeshTest();
|
||||
D3DXCreateMeshFVFTest();
|
||||
D3DXLoadMeshTest();
|
||||
D3DXCreateBoxTest();
|
||||
D3DXCreateSphereTest();
|
||||
D3DXCreateCylinderTest();
|
||||
|
|
Loading…
Reference in New Issue