d3dx9: Implement D3DXCreateTorus() + tests (try 2)
Gediminas Jakutis
gediminas at varciai.lt
Tue Jul 1 08:58:20 CDT 2014
Fixed problems outlined by Matteo Bruni.
Supersedes patch 105379.
---
dlls/d3dx9_36/d3dx9_36.spec | 2 +-
dlls/d3dx9_36/mesh.c | 119 ++++++++++++++++++++++++++++++
dlls/d3dx9_36/tests/mesh.c | 172 ++++++++++++++++++++++++++++++++++++++++++++
include/d3dx9shape.h | 2 +
4 files changed, 294 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 1a2b020..810b0e7 100644
--- a/dlls/d3dx9_36/mesh.c
+++ b/dlls/d3dx9_36/mesh.c
@@ -5056,6 +5056,125 @@ 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 rotation_step;
+ float rotation_curr;
+ float sin;
+ float cos;
+ unsigned int i, j, numvert, numfaces;
+
+ TRACE("device %p, innerradius %1.8f, outerradius %1.8f, 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;
+ }
+
+ rotation_step = D3DX_PI / sides * 2.0f;
+ rotation_curr = 0.0f;
+
+ for (i = 0; i < sides; ++i)
+ {
+ sin = sinf(rotation_curr);
+ cos = cosf(rotation_curr);
+ vertices[i].position.x = innerradius * cos + outerradius;
+ vertices[i].position.y = 0.0f;
+ vertices[i].position.z = innerradius * sin;
+ vertices[i].normal.x = cos;
+ vertices[i].normal.y = 0.0f;
+ vertices[i].normal.z = sin;
+
+ rotation_curr += rotation_step;
+ }
+
+ rotation_step = D3DX_PI / rings * -2.0f;
+ rotation_curr = rotation_step;
+
+ for (i = 1; i < rings; ++i)
+ {
+ cos = cosf(rotation_curr);
+ sin = sinf(rotation_curr);
+
+ for (j = 0; j < sides; ++j)
+ {
+ vertices[i * sides + j].position.x = vertices[j].position.x * cos;
+ vertices[i * sides + j].position.y = vertices[j].position.x * sin;
+ vertices[i * sides + j].position.z = vertices[j].position.z;
+ vertices[i * sides + j].normal.x = vertices[j].normal.x * cos;
+ vertices[i * sides + j].normal.y = vertices[j].normal.x * sin;
+ vertices[i * sides + j].normal.z = vertices[j].normal.z;
+ }
+
+ rotation_curr += rotation_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..ac21210 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -3157,6 +3157,177 @@ static void D3DXCreateCylinderTest(void)
DestroyWindow(wnd);
}
+static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings)
+{
+ float rotation_step;
+ float rotation_curr;
+ float sin;
+ float cos;
+ unsigned int numvert, numfaces, i, j;
+
+ numvert = sides * rings;
+ numfaces = numvert * 2;
+
+ if (!new_mesh(mesh, numvert, numfaces))
+ {
+ return FALSE;
+ }
+
+ rotation_step = D3DX_PI / sides * 2.0f;
+ rotation_curr = 0.0f;
+
+ for (i = 0; i < sides; ++i)
+ {
+ sin = sinf(rotation_curr);
+ cos = cosf(rotation_curr);
+ mesh->vertices[i].position.x = innerradius * cos + outerradius;
+ mesh->vertices[i].position.y = 0.0f;
+ mesh->vertices[i].position.z = innerradius * sin;
+ mesh->vertices[i].normal.x = cos;
+ mesh->vertices[i].normal.y = 0.0f;
+ mesh->vertices[i].normal.z = sin;
+
+ rotation_curr += rotation_step;
+ }
+
+ rotation_step = D3DX_PI / rings * -2.0f;
+ rotation_curr = rotation_step;
+
+ for (i = 1; i < rings; ++i)
+ {
+ cos = cosf(rotation_curr);
+ sin = sinf(rotation_curr);
+
+ for (j = 0; j < sides; ++j)
+ {
+ mesh->vertices[i * sides + j].position.x = mesh->vertices[j].position.x * cos;
+ mesh->vertices[i * sides + j].position.y = mesh->vertices[j].position.x * sin;
+ mesh->vertices[i * sides + j].position.z = mesh->vertices[j].position.z;
+ mesh->vertices[i * sides + j].normal.x = mesh->vertices[j].normal.x * cos;
+ mesh->vertices[i * sides + j].normal.y = mesh->vertices[j].normal.x * sin;
+ mesh->vertices[i * sides + j].normal.z = mesh->vertices[j].normal.z;
+ }
+
+ rotation_curr += rotation_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 +10473,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