d3dx9: Implement D3DXCreateTorus() + tests.
This commit is contained in:
parent
60f558876e
commit
fe802d92bb
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue