d3dx9_36: Implement D3DXCreateCylinder.

This commit is contained in:
Misha Koshelev 2010-09-27 15:19:22 -05:00 committed by Alexandre Julliard
parent a7ded9a67d
commit 09af2a2bf9
2 changed files with 210 additions and 31 deletions

View File

@ -1112,7 +1112,7 @@ static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_
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;
}
@ -1225,14 +1225,14 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli
else
{
/* stacks in between top and bottom are quad strips */
faces[face][0] = sphere_vertex(slices, slice-1, stack-1);
faces[face][1] = sphere_vertex(slices, slice, stack-1);
faces[face][2] = sphere_vertex(slices, slice-1, stack);
faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = vertex_index(slices, slice, stack-1);
faces[face][2] = vertex_index(slices, slice-1, stack);
face++;
faces[face][0] = sphere_vertex(slices, slice, stack-1);
faces[face][1] = sphere_vertex(slices, slice, stack);
faces[face][2] = sphere_vertex(slices, slice-1, stack);
faces[face][0] = vertex_index(slices, slice, stack-1);
faces[face][1] = vertex_index(slices, slice, stack);
faces[face][2] = vertex_index(slices, slice-1, stack);
face++;
}
}
@ -1249,14 +1249,14 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli
}
else
{
faces[face][0] = sphere_vertex(slices, slice-1, stack-1);
faces[face][1] = sphere_vertex(slices, 0, stack-1);
faces[face][2] = sphere_vertex(slices, slice-1, stack);
faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = vertex_index(slices, 0, stack-1);
faces[face][2] = vertex_index(slices, slice-1, stack);
face++;
faces[face][0] = sphere_vertex(slices, 0, stack-1);
faces[face][1] = sphere_vertex(slices, 0, stack);
faces[face][2] = sphere_vertex(slices, slice-1, stack);
faces[face][0] = vertex_index(slices, 0, stack-1);
faces[face][1] = vertex_index(slices, 0, stack);
faces[face][2] = vertex_index(slices, slice-1, stack);
face++;
}
}
@ -1271,14 +1271,14 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli
/* bottom stack is triangle fan */
for (slice = 1; slice < slices; slice++)
{
faces[face][0] = sphere_vertex(slices, slice-1, stack-1);
faces[face][1] = sphere_vertex(slices, slice, stack-1);
faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = vertex_index(slices, slice, stack-1);
faces[face][2] = vertex;
face++;
}
faces[face][0] = sphere_vertex(slices, slice-1, stack-1);
faces[face][1] = sphere_vertex(slices, 0, stack-1);
faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = vertex_index(slices, 0, stack-1);
faces[face][2] = vertex;
free_sincos_table(&phi);
@ -1292,9 +1292,188 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli
HRESULT WINAPI D3DXCreateCylinder(LPDIRECT3DDEVICE9 device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices,
UINT stacks, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency)
{
FIXME("(%p, %f, %f, %f, %u, %u, %p, %p): stub\n", device, radius1, radius2, length, slices, stacks, mesh, adjacency);
DWORD number_of_vertices, number_of_faces;
HRESULT hr;
ID3DXMesh *cylinder;
struct vertex *vertices;
face *faces;
float theta_step, theta_start;
struct sincos_table theta;
float delta_radius, radius, radius_step;
float z, z_step, z_normal;
DWORD vertex, face;
int slice, stack;
return E_NOTIMPL;
TRACE("(%p, %f, %f, %f, %u, %u, %p, %p)\n", device, radius1, radius2, length, slices, stacks, mesh, adjacency);
if (device == NULL || radius1 < 0.0f || radius2 < 0.0f || length < 0.0f || slices < 2 || stacks < 1 || mesh == NULL)
{
return D3DERR_INVALIDCALL;
}
if (adjacency)
{
FIXME("Case of adjacency != NULL not implemented.\n");
return E_NOTIMPL;
}
number_of_vertices = 2 + (slices * (3 + stacks));
number_of_faces = 2 * slices + stacks * (2 * slices);
hr = D3DXCreateMeshFVF(number_of_faces, number_of_vertices, D3DXMESH_MANAGED,
D3DFVF_XYZ | D3DFVF_NORMAL, device, &cylinder);
if (FAILED(hr))
{
return hr;
}
hr = cylinder->lpVtbl->LockVertexBuffer(cylinder, D3DLOCK_DISCARD, (LPVOID *)&vertices);
if (FAILED(hr))
{
cylinder->lpVtbl->Release(cylinder);
return hr;
}
hr = cylinder->lpVtbl->LockIndexBuffer(cylinder, D3DLOCK_DISCARD, (LPVOID *)&faces);
if (FAILED(hr))
{
cylinder->lpVtbl->UnlockVertexBuffer(cylinder);
cylinder->lpVtbl->Release(cylinder);
return hr;
}
/* 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))
{
cylinder->lpVtbl->UnlockIndexBuffer(cylinder);
cylinder->lpVtbl->UnlockVertexBuffer(cylinder);
cylinder->lpVtbl->Release(cylinder);
return E_OUTOFMEMORY;
}
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;
}
vertices[vertex].normal.x = 0.0f;
vertices[vertex].normal.y = 0.0f;
vertices[vertex].normal.z = -1.0f;
vertices[vertex].position.x = 0.0f;
vertices[vertex].position.y = 0.0f;
vertices[vertex++].position.z = z;
for (slice = 0; slice < slices; slice++, vertex++)
{
vertices[vertex].normal.x = 0.0f;
vertices[vertex].normal.y = 0.0f;
vertices[vertex].normal.z = -1.0f;
vertices[vertex].position.x = radius * theta.cos[slice];
vertices[vertex].position.y = radius * theta.sin[slice];
vertices[vertex].position.z = z;
if (slice > 0)
{
faces[face][0] = 0;
faces[face][1] = slice;
faces[face++][2] = slice + 1;
}
}
faces[face][0] = 0;
faces[face][1] = slice;
faces[face++][2] = 1;
for (stack = 1; stack <= stacks+1; stack++)
{
for (slice = 0; slice < slices; slice++, vertex++)
{
vertices[vertex].normal.x = theta.cos[slice];
vertices[vertex].normal.y = theta.sin[slice];
vertices[vertex].normal.z = z_normal;
D3DXVec3Normalize(&vertices[vertex].normal, &vertices[vertex].normal);
vertices[vertex].position.x = radius * theta.cos[slice];
vertices[vertex].position.y = radius * theta.sin[slice];
vertices[vertex].position.z = z;
if (stack > 1 && slice > 0)
{
faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = vertex_index(slices, slice-1, stack);
faces[face++][2] = vertex_index(slices, slice, stack-1);
faces[face][0] = vertex_index(slices, slice, stack-1);
faces[face][1] = vertex_index(slices, slice-1, stack);
faces[face++][2] = vertex_index(slices, slice, stack);
}
}
if (stack > 1)
{
faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = vertex_index(slices, slice-1, stack);
faces[face++][2] = vertex_index(slices, 0, stack-1);
faces[face][0] = vertex_index(slices, 0, stack-1);
faces[face][1] = vertex_index(slices, slice-1, stack);
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++)
{
vertices[vertex].normal.x = 0.0f;
vertices[vertex].normal.y = 0.0f;
vertices[vertex].normal.z = 1.0f;
vertices[vertex].position.x = radius * theta.cos[slice];
vertices[vertex].position.y = radius * theta.sin[slice];
vertices[vertex].position.z = z;
if (slice > 0)
{
faces[face][0] = vertex_index(slices, slice-1, stack);
faces[face][1] = number_of_vertices - 1;
faces[face++][2] = vertex_index(slices, slice, stack);
}
}
vertices[vertex].position.x = 0.0f;
vertices[vertex].position.y = 0.0f;
vertices[vertex].position.z = z;
vertices[vertex].normal.x = 0.0f;
vertices[vertex].normal.y = 0.0f;
vertices[vertex].normal.z = 1.0f;
faces[face][0] = vertex_index(slices, slice-1, stack);
faces[face][1] = number_of_vertices - 1;
faces[face][2] = vertex_index(slices, 0, stack);
free_sincos_table(&theta);
cylinder->lpVtbl->UnlockIndexBuffer(cylinder);
cylinder->lpVtbl->UnlockVertexBuffer(cylinder);
*mesh = cylinder;
return D3D_OK;
}
HRESULT WINAPI D3DXCreateTeapot(LPDIRECT3DDEVICE9 device, LPD3DXMESH *mesh, LPD3DXBUFFER* adjacency)

View File

@ -1788,7 +1788,7 @@ static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2
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);
ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
if (hr != D3D_OK)
{
skip("Couldn't create cylinder\n");
@ -1822,10 +1822,10 @@ static void D3DXCreateCylinderTest(void)
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);
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);
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);
@ -1854,10 +1854,10 @@ static void D3DXCreateCylinderTest(void)
}
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);
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);
ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
if (SUCCEEDED(hr) && cylinder)
{
@ -1865,10 +1865,10 @@ static void D3DXCreateCylinderTest(void)
}
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);
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);
ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
if (SUCCEEDED(hr) && cylinder)
{
@ -1876,11 +1876,11 @@ static void D3DXCreateCylinderTest(void)
}
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);
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);
ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr);
if (SUCCEEDED(hr) && cylinder)
{
@ -1888,13 +1888,13 @@ static void D3DXCreateCylinderTest(void)
}
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);
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);
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);
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);