d3dx9: Implement D3DXCreateTorus() + tests (try 3)
Gediminas Jakutis
gediminas at varciai.lt
Wed Jul 9 12:05:03 CDT 2014
Supersedes patch 105390.
---
dlls/d3dx9_36/d3dx9_36.spec | 2 +-
dlls/d3dx9_36/mesh.c | 106 +++++++++++++++++++++++++++++
dlls/d3dx9_36/tests/mesh.c | 159 ++++++++++++++++++++++++++++++++++++++++++++
include/d3dx9shape.h | 2 +
4 files changed, 268 insertions(+), 1 deletion(-)
-------------- next part --------------
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index f2c229a..4c72dc2 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -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)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c
index 3b3784b..9901e3f 100644
--- a/dlls/d3dx9_36/mesh.c
+++ b/dlls/d3dx9_36/mesh.c
@@ -5068,6 +5068,112 @@ 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;
+ phi = 0.0f;
+
+ theta_step = D3DX_PI / rings * -2.0f;
+ theta = theta_step;
+
+ for (i = 0; i < rings; ++i)
+ {
+ cos_theta = cosf(theta);
+ sin_theta = sinf(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,
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index 24bcb82..ec07f28 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -3157,6 +3157,164 @@ 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;
+ phi = 0.0f;
+
+ theta_step = D3DX_PI / rings * -2.0f;
+ theta = theta_step;
+
+ for (i = 0; i < rings; ++i)
+ {
+ 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 +10460,7 @@ START_TEST(mesh)
D3DXCreateSphereTest();
D3DXCreateCylinderTest();
D3DXCreateTextTest();
+ D3DXCreateTorusTest();
test_get_decl_length();
test_get_decl_vertex_size();
test_fvf_decl_conversion();
diff --git a/include/d3dx9shape.h b/include/d3dx9shape.h
index 1d2667d..0d24032 100644
--- a/include/d3dx9shape.h
+++ b/include/d3dx9shape.h
@@ -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
--
1.9.1
More information about the wine-patches
mailing list