Commit fe802d92 authored by Gediminas Jakutis's avatar Gediminas Jakutis Committed by Alexandre Julliard

d3dx9: Implement D3DXCreateTorus() + tests.

parent 60f55887
......@@ -105,7 +105,7 @@
@ stdcall D3DXCreateTextureFromResourceW(ptr ptr wstr ptr)
@ stub D3DXCreateTextureGutterHelper(long long ptr long ptr)
@ stub D3DXCreateTextureShader(ptr ptr)
@ stub D3DXCreateTorus(ptr long long long long ptr ptr)
@ stdcall D3DXCreateTorus(ptr long long long long ptr ptr)
@ stdcall D3DXCreateVolumeTexture(ptr long long long long long long long ptr)
@ stdcall D3DXCreateVolumeTextureFromFileA(ptr ptr ptr)
@ stdcall D3DXCreateVolumeTextureFromFileExA(ptr ptr long long long long long long long long long long ptr ptr ptr)
......
......@@ -5068,6 +5068,113 @@ HRESULT WINAPI D3DXCreateTextA(struct IDirect3DDevice9 *device, HDC hdc, const c
return hr;
}
HRESULT WINAPI D3DXCreateTorus(struct IDirect3DDevice9 *device,
float innerradius, float outerradius, UINT sides, UINT rings, struct ID3DXMesh **mesh, ID3DXBuffer **adjacency)
{
HRESULT hr;
ID3DXMesh *torus;
WORD (*faces)[3];
struct vertex *vertices;
float phi, phi_step, sin_phi, cos_phi;
float theta, theta_step, sin_theta, cos_theta;
unsigned int i, j, numvert, numfaces;
TRACE("device %p, innerradius %.8e, outerradius %.8e, sides %u, rings %u, mesh %p, adjacency %p.\n",
device, innerradius, outerradius, sides, rings, mesh, adjacency);
numvert = sides * rings;
numfaces = numvert * 2;
if (!device || innerradius < 0.0f || outerradius < 0.0f || sides < 3 || rings < 3 || !mesh)
{
WARN("Invalid arguments.\n");
return D3DERR_INVALIDCALL;
}
if (FAILED(hr = D3DXCreateMeshFVF(numfaces, numvert, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &torus)))
return hr;
if (FAILED(hr = torus->lpVtbl->LockVertexBuffer(torus, 0, (void **)&vertices)))
{
torus->lpVtbl->Release(torus);
return hr;
}
if (FAILED(hr = torus->lpVtbl->LockIndexBuffer(torus, 0, (void **)&faces)))
{
torus->lpVtbl->UnlockVertexBuffer(torus);
torus->lpVtbl->Release(torus);
return hr;
}
phi_step = D3DX_PI / sides * 2.0f;
theta_step = D3DX_PI / rings * -2.0f;
theta = 0.0f;
for (i = 0; i < rings; ++i)
{
phi = 0.0f;
sin_theta = sinf(theta);
cos_theta = cosf(theta);
for (j = 0; j < sides; ++j)
{
sin_phi = sinf(phi);
cos_phi = cosf(phi);
vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
vertices[i * sides + j].position.z = innerradius * sin_phi;
vertices[i * sides + j].normal.x = cos_phi * cos_theta;
vertices[i * sides + j].normal.y = cos_phi * sin_theta;
vertices[i * sides + j].normal.z = sin_phi;
phi += phi_step;
}
theta += theta_step;
}
for (i = 0; i < numfaces - sides * 2; ++i)
{
faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
}
for (j = 0; i < numfaces; ++i, ++j)
{
faces[i][0] = i % 2 ? j / 2 : i / 2;
faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
}
torus->lpVtbl->UnlockIndexBuffer(torus);
torus->lpVtbl->UnlockVertexBuffer(torus);
if (adjacency)
{
if (FAILED(hr = D3DXCreateBuffer(numfaces * sizeof(DWORD) * 3, adjacency)))
{
torus->lpVtbl->Release(torus);
return hr;
}
if (FAILED(hr = torus->lpVtbl->GenerateAdjacency(torus, 0.0f, (*adjacency)->lpVtbl->GetBufferPointer(*adjacency))))
{
(*adjacency)->lpVtbl->Release(*adjacency);
torus->lpVtbl->Release(torus);
return hr;
}
}
*mesh = torus;
return D3D_OK;
}
enum pointtype {
POINTTYPE_CURVE = 0,
POINTTYPE_CORNER,
......
......@@ -3157,6 +3157,165 @@ static void D3DXCreateCylinderTest(void)
DestroyWindow(wnd);
}
static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
{
float phi, phi_step, sin_phi, cos_phi;
float theta, theta_step, sin_theta, cos_theta;
unsigned int numvert, numfaces, i, j;
numvert = sides * rings;
numfaces = numvert * 2;
if (!new_mesh(mesh, numvert, numfaces))
return FALSE;
phi_step = D3DX_PI / sides * 2.0f;
theta_step = D3DX_PI / rings * -2.0f;
theta = 0.0f;
for (i = 0; i < rings; ++i)
{
phi = 0.0f;
cos_theta = cosf(theta);
sin_theta = sinf(theta);
for (j = 0; j < sides; ++j)
{
sin_phi = sinf(phi);
cos_phi = cosf(phi);
mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta;
mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta;
mesh->vertices[i * sides + j].position.z = innerradius * sin_phi;
mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta;
mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta;
mesh->vertices[i * sides + j].normal.z = sin_phi;
phi += phi_step;
}
theta += theta_step;
}
for (i = 0; i < numfaces - sides * 2; ++i)
{
mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2;
mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2;
}
for (j = 0; i < numfaces; ++i, ++j)
{
mesh->faces[i][0] = i % 2 ? j / 2 : i / 2;
mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides;
mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2;
}
return TRUE;
}
static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings)
{
HRESULT hr;
ID3DXMesh *torus;
struct mesh mesh;
char name[256];
hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL);
ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr);
if (hr != D3D_OK)
{
skip("Couldn't create torus\n");
return;
}
if (!compute_torus(&mesh, innerradius, outerradius, sides, rings))
{
skip("Couldn't create mesh\n");
torus->lpVtbl->Release(torus);
return;
}
mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings);
compare_mesh(name, torus, &mesh);
free_mesh(&mesh);
torus->lpVtbl->Release(torus);
}
static void D3DXCreateTorusTest(void)
{
HRESULT hr;
HWND wnd;
IDirect3D9* d3d;
IDirect3DDevice9* device;
D3DPRESENT_PARAMETERS d3dpp;
ID3DXMesh* torus = NULL;
if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
640, 480, NULL, NULL, NULL, NULL)))
{
skip("Couldn't create application window\n");
return;
}
if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
{
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_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
if (FAILED(hr))
{
skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
IDirect3D9_Release(d3d);
DestroyWindow(wnd);
return;
}
hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL);
ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL);
ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL);
ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL);
ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL);
ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL);
ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
test_torus(device, 0.0f, 0.0f, 3, 3);
test_torus(device, 1.0f, 1.0f, 3, 3);
test_torus(device, 1.0f, 1.0f, 32, 64);
test_torus(device, 0.0f, 1.0f, 5, 5);
test_torus(device, 1.0f, 0.0f, 5, 5);
test_torus(device, 5.0f, 0.2f, 8, 8);
test_torus(device, 0.2f, 1.0f, 60, 3);
test_torus(device, 0.2f, 1.0f, 8, 70);
IDirect3DDevice9_Release(device);
IDirect3D9_Release(d3d);
DestroyWindow(wnd);
}
struct dynamic_array
{
int count, capacity;
......@@ -10302,6 +10461,7 @@ START_TEST(mesh)
D3DXCreateSphereTest();
D3DXCreateCylinderTest();
D3DXCreateTextTest();
D3DXCreateTorusTest();
test_get_decl_length();
test_get_decl_vertex_size();
test_fvf_decl_conversion();
......
......@@ -37,6 +37,8 @@ HRESULT WINAPI D3DXCreateTextA(struct IDirect3DDevice9 *device, HDC hdc, const c
float extrusion, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency, GLYPHMETRICSFLOAT *glyphmetrics);
HRESULT WINAPI D3DXCreateTextW(struct IDirect3DDevice9 *device, HDC hdc, const WCHAR *text, float deviation,
FLOAT extrusion, struct ID3DXMesh **mesh, struct ID3DXBuffer **adjacency, GLYPHMETRICSFLOAT *glyphmetrics);
HRESULT WINAPI D3DXCreateTorus(struct IDirect3DDevice9 *device,
float innerradius, float outerradius, UINT sides, UINT rings, struct ID3DXMesh **mesh, ID3DXBuffer **adjacency);
#define D3DXCreateText WINELIB_NAME_AW(D3DXCreateText)
#ifdef __cplusplus
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment