d3dx9_36/tests: Add tests for D3DXCreateCylinder.
This commit is contained in:
parent
fe9db6faf7
commit
63dbf6ee3f
|
@ -1388,7 +1388,7 @@ static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WORD sphere_vertex(UINT slices, int slice, int stack)
|
static WORD vertex_index(UINT slices, int slice, int stack)
|
||||||
{
|
{
|
||||||
return stack*slices+slice+1;
|
return stack*slices+slice+1;
|
||||||
}
|
}
|
||||||
|
@ -1469,14 +1469,14 @@ static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT st
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* stacks in between top and bottom are quad strips */
|
/* stacks in between top and bottom are quad strips */
|
||||||
mesh->faces[face][0] = sphere_vertex(slices, slice-1, stack-1);
|
mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
|
||||||
mesh->faces[face][1] = sphere_vertex(slices, slice, stack-1);
|
mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
|
||||||
mesh->faces[face][2] = sphere_vertex(slices, slice-1, stack);
|
mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
|
||||||
face++;
|
face++;
|
||||||
|
|
||||||
mesh->faces[face][0] = sphere_vertex(slices, slice, stack-1);
|
mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
|
||||||
mesh->faces[face][1] = sphere_vertex(slices, slice, stack);
|
mesh->faces[face][1] = vertex_index(slices, slice, stack);
|
||||||
mesh->faces[face][2] = sphere_vertex(slices, slice-1, stack);
|
mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
|
||||||
face++;
|
face++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1491,14 +1491,14 @@ static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT st
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mesh->faces[face][0] = sphere_vertex(slices, slice-1, stack-1);
|
mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
|
||||||
mesh->faces[face][1] = sphere_vertex(slices, 0, stack-1);
|
mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
|
||||||
mesh->faces[face][2] = sphere_vertex(slices, slice-1, stack);
|
mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
|
||||||
face++;
|
face++;
|
||||||
|
|
||||||
mesh->faces[face][0] = sphere_vertex(slices, 0, stack-1);
|
mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
|
||||||
mesh->faces[face][1] = sphere_vertex(slices, 0, stack);
|
mesh->faces[face][1] = vertex_index(slices, 0, stack);
|
||||||
mesh->faces[face][2] = sphere_vertex(slices, slice-1, stack);
|
mesh->faces[face][2] = vertex_index(slices, slice-1, stack);
|
||||||
face++;
|
face++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1513,14 +1513,14 @@ static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT st
|
||||||
/* bottom stack is triangle fan */
|
/* bottom stack is triangle fan */
|
||||||
for (slice = 1; slice < slices; slice++)
|
for (slice = 1; slice < slices; slice++)
|
||||||
{
|
{
|
||||||
mesh->faces[face][0] = sphere_vertex(slices, slice-1, stack-1);
|
mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
|
||||||
mesh->faces[face][1] = sphere_vertex(slices, slice, stack-1);
|
mesh->faces[face][1] = vertex_index(slices, slice, stack-1);
|
||||||
mesh->faces[face][2] = vertex;
|
mesh->faces[face][2] = vertex;
|
||||||
face++;
|
face++;
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh->faces[face][0] = sphere_vertex(slices, slice-1, stack-1);
|
mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
|
||||||
mesh->faces[face][1] = sphere_vertex(slices, 0, stack-1);
|
mesh->faces[face][1] = vertex_index(slices, 0, stack-1);
|
||||||
mesh->faces[face][2] = vertex;
|
mesh->faces[face][2] = vertex;
|
||||||
|
|
||||||
free_sincos_table(&phi);
|
free_sincos_table(&phi);
|
||||||
|
@ -1633,6 +1633,281 @@ static void D3DXCreateSphereTest(void)
|
||||||
DestroyWindow(wnd);
|
DestroyWindow(wnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
|
||||||
|
{
|
||||||
|
float theta_step, theta_start;
|
||||||
|
struct sincos_table theta;
|
||||||
|
FLOAT delta_radius, radius, radius_step;
|
||||||
|
FLOAT z, z_step, z_normal;
|
||||||
|
DWORD number_of_vertices, number_of_faces;
|
||||||
|
DWORD vertex, face;
|
||||||
|
int slice, stack;
|
||||||
|
|
||||||
|
/* theta = angle on xy plane wrt x axis */
|
||||||
|
theta_step = -2 * M_PI / slices;
|
||||||
|
theta_start = M_PI / 2;
|
||||||
|
|
||||||
|
if (!compute_sincos_table(&theta, theta_start, theta_step, slices))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
number_of_vertices = 2 + (slices * (3 + stacks));
|
||||||
|
number_of_faces = 2 * slices + stacks * (2 * slices);
|
||||||
|
|
||||||
|
if (!new_mesh(mesh, number_of_vertices, number_of_faces))
|
||||||
|
{
|
||||||
|
free_sincos_table(&theta);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex = 0;
|
||||||
|
face = 0;
|
||||||
|
stack = 0;
|
||||||
|
|
||||||
|
delta_radius = radius1 - radius2;
|
||||||
|
radius = radius1;
|
||||||
|
radius_step = delta_radius / stacks;
|
||||||
|
|
||||||
|
z = -length / 2;
|
||||||
|
z_step = length / stacks;
|
||||||
|
z_normal = delta_radius / length;
|
||||||
|
if (isnan(z_normal))
|
||||||
|
{
|
||||||
|
z_normal = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh->vertices[vertex].normal.x = 0.0f;
|
||||||
|
mesh->vertices[vertex].normal.y = 0.0f;
|
||||||
|
mesh->vertices[vertex].normal.z = -1.0f;
|
||||||
|
mesh->vertices[vertex].position.x = 0.0f;
|
||||||
|
mesh->vertices[vertex].position.y = 0.0f;
|
||||||
|
mesh->vertices[vertex++].position.z = z;
|
||||||
|
|
||||||
|
for (slice = 0; slice < slices; slice++, vertex++)
|
||||||
|
{
|
||||||
|
mesh->vertices[vertex].normal.x = 0.0f;
|
||||||
|
mesh->vertices[vertex].normal.y = 0.0f;
|
||||||
|
mesh->vertices[vertex].normal.z = -1.0f;
|
||||||
|
mesh->vertices[vertex].position.x = radius * theta.cos[slice];
|
||||||
|
mesh->vertices[vertex].position.y = radius * theta.sin[slice];
|
||||||
|
mesh->vertices[vertex].position.z = z;
|
||||||
|
|
||||||
|
if (slice > 0)
|
||||||
|
{
|
||||||
|
mesh->faces[face][0] = 0;
|
||||||
|
mesh->faces[face][1] = slice;
|
||||||
|
mesh->faces[face++][2] = slice + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh->faces[face][0] = 0;
|
||||||
|
mesh->faces[face][1] = slice;
|
||||||
|
mesh->faces[face++][2] = 1;
|
||||||
|
|
||||||
|
for (stack = 1; stack <= stacks+1; stack++)
|
||||||
|
{
|
||||||
|
for (slice = 0; slice < slices; slice++, vertex++)
|
||||||
|
{
|
||||||
|
mesh->vertices[vertex].normal.x = theta.cos[slice];
|
||||||
|
mesh->vertices[vertex].normal.y = theta.sin[slice];
|
||||||
|
mesh->vertices[vertex].normal.z = z_normal;
|
||||||
|
D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal);
|
||||||
|
mesh->vertices[vertex].position.x = radius * theta.cos[slice];
|
||||||
|
mesh->vertices[vertex].position.y = radius * theta.sin[slice];
|
||||||
|
mesh->vertices[vertex].position.z = z;
|
||||||
|
|
||||||
|
if (stack > 1 && slice > 0)
|
||||||
|
{
|
||||||
|
mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
|
||||||
|
mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
|
||||||
|
mesh->faces[face++][2] = vertex_index(slices, slice, stack-1);
|
||||||
|
|
||||||
|
mesh->faces[face][0] = vertex_index(slices, slice, stack-1);
|
||||||
|
mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
|
||||||
|
mesh->faces[face++][2] = vertex_index(slices, slice, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack > 1)
|
||||||
|
{
|
||||||
|
mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1);
|
||||||
|
mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
|
||||||
|
mesh->faces[face++][2] = vertex_index(slices, 0, stack-1);
|
||||||
|
|
||||||
|
mesh->faces[face][0] = vertex_index(slices, 0, stack-1);
|
||||||
|
mesh->faces[face][1] = vertex_index(slices, slice-1, stack);
|
||||||
|
mesh->faces[face++][2] = vertex_index(slices, 0, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack < stacks + 1)
|
||||||
|
{
|
||||||
|
z += z_step;
|
||||||
|
radius -= radius_step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (slice = 0; slice < slices; slice++, vertex++)
|
||||||
|
{
|
||||||
|
mesh->vertices[vertex].normal.x = 0.0f;
|
||||||
|
mesh->vertices[vertex].normal.y = 0.0f;
|
||||||
|
mesh->vertices[vertex].normal.z = 1.0f;
|
||||||
|
mesh->vertices[vertex].position.x = radius * theta.cos[slice];
|
||||||
|
mesh->vertices[vertex].position.y = radius * theta.sin[slice];
|
||||||
|
mesh->vertices[vertex].position.z = z;
|
||||||
|
|
||||||
|
if (slice > 0)
|
||||||
|
{
|
||||||
|
mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
|
||||||
|
mesh->faces[face][1] = number_of_vertices - 1;
|
||||||
|
mesh->faces[face++][2] = vertex_index(slices, slice, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh->vertices[vertex].position.x = 0.0f;
|
||||||
|
mesh->vertices[vertex].position.y = 0.0f;
|
||||||
|
mesh->vertices[vertex].position.z = z;
|
||||||
|
mesh->vertices[vertex].normal.x = 0.0f;
|
||||||
|
mesh->vertices[vertex].normal.y = 0.0f;
|
||||||
|
mesh->vertices[vertex].normal.z = 1.0f;
|
||||||
|
|
||||||
|
mesh->faces[face][0] = vertex_index(slices, slice-1, stack);
|
||||||
|
mesh->faces[face][1] = number_of_vertices - 1;
|
||||||
|
mesh->faces[face][2] = vertex_index(slices, 0, stack);
|
||||||
|
|
||||||
|
free_sincos_table(&theta);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
ID3DXMesh *cylinder;
|
||||||
|
struct mesh mesh;
|
||||||
|
char name[256];
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
|
||||||
|
if (hr != D3D_OK)
|
||||||
|
{
|
||||||
|
skip("Couldn't create cylinder\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks))
|
||||||
|
{
|
||||||
|
skip("Couldn't create mesh\n");
|
||||||
|
cylinder->lpVtbl->Release(cylinder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
|
||||||
|
|
||||||
|
sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks);
|
||||||
|
compare_mesh(name, cylinder, &mesh);
|
||||||
|
|
||||||
|
free_mesh(&mesh);
|
||||||
|
|
||||||
|
cylinder->lpVtbl->Release(cylinder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void D3DXCreateCylinderTest(void)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
HWND wnd;
|
||||||
|
IDirect3D9* d3d;
|
||||||
|
IDirect3DDevice9* device;
|
||||||
|
D3DPRESENT_PARAMETERS d3dpp;
|
||||||
|
ID3DXMesh* cylinder = NULL;
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL);
|
||||||
|
todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
|
||||||
|
|
||||||
|
wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
|
||||||
|
d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||||
|
if (!wnd)
|
||||||
|
{
|
||||||
|
skip("Couldn't create application window\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!d3d)
|
||||||
|
{
|
||||||
|
skip("Couldn't create IDirect3D9 object\n");
|
||||||
|
DestroyWindow(wnd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
IDirect3D9_Release(d3d);
|
||||||
|
DestroyWindow(wnd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && cylinder)
|
||||||
|
{
|
||||||
|
cylinder->lpVtbl->Release(cylinder);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && cylinder)
|
||||||
|
{
|
||||||
|
cylinder->lpVtbl->Release(cylinder);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
|
||||||
|
|
||||||
|
/* Test with length == 0.0f succeeds */
|
||||||
|
hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && cylinder)
|
||||||
|
{
|
||||||
|
cylinder->lpVtbl->Release(cylinder);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL);
|
||||||
|
todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
|
||||||
|
|
||||||
|
hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL);
|
||||||
|
todo_wine ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL);
|
||||||
|
|
||||||
|
test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1);
|
||||||
|
test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);
|
||||||
|
test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4);
|
||||||
|
test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4);
|
||||||
|
test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4);
|
||||||
|
test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20);
|
||||||
|
|
||||||
|
IDirect3DDevice9_Release(device);
|
||||||
|
IDirect3D9_Release(d3d);
|
||||||
|
DestroyWindow(wnd);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_get_decl_length(void)
|
static void test_get_decl_length(void)
|
||||||
{
|
{
|
||||||
static const D3DVERTEXELEMENT9 declaration1[] =
|
static const D3DVERTEXELEMENT9 declaration1[] =
|
||||||
|
@ -1765,6 +2040,7 @@ START_TEST(mesh)
|
||||||
D3DXCreateMeshTest();
|
D3DXCreateMeshTest();
|
||||||
D3DXCreateMeshFVFTest();
|
D3DXCreateMeshFVFTest();
|
||||||
D3DXCreateSphereTest();
|
D3DXCreateSphereTest();
|
||||||
|
D3DXCreateCylinderTest();
|
||||||
test_get_decl_length();
|
test_get_decl_length();
|
||||||
test_get_decl_vertex_size();
|
test_get_decl_vertex_size();
|
||||||
test_fvf_decl_conversion();
|
test_fvf_decl_conversion();
|
||||||
|
|
Loading…
Reference in New Issue