d3dx9_36: Implement D3DXCreateCylinder.

oldstable
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; 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; return stack*slices+slice+1;
} }
@ -1225,14 +1225,14 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli
else else
{ {
/* stacks in between top and bottom are quad strips */ /* stacks in between top and bottom are quad strips */
faces[face][0] = sphere_vertex(slices, slice-1, stack-1); faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = sphere_vertex(slices, slice, stack-1); faces[face][1] = vertex_index(slices, slice, stack-1);
faces[face][2] = sphere_vertex(slices, slice-1, stack); faces[face][2] = vertex_index(slices, slice-1, stack);
face++; face++;
faces[face][0] = sphere_vertex(slices, slice, stack-1); faces[face][0] = vertex_index(slices, slice, stack-1);
faces[face][1] = sphere_vertex(slices, slice, stack); faces[face][1] = vertex_index(slices, slice, stack);
faces[face][2] = sphere_vertex(slices, slice-1, stack); faces[face][2] = vertex_index(slices, slice-1, stack);
face++; face++;
} }
} }
@ -1249,14 +1249,14 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli
} }
else else
{ {
faces[face][0] = sphere_vertex(slices, slice-1, stack-1); faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = sphere_vertex(slices, 0, stack-1); faces[face][1] = vertex_index(slices, 0, stack-1);
faces[face][2] = sphere_vertex(slices, slice-1, stack); faces[face][2] = vertex_index(slices, slice-1, stack);
face++; face++;
faces[face][0] = sphere_vertex(slices, 0, stack-1); faces[face][0] = vertex_index(slices, 0, stack-1);
faces[face][1] = sphere_vertex(slices, 0, stack); faces[face][1] = vertex_index(slices, 0, stack);
faces[face][2] = sphere_vertex(slices, slice-1, stack); faces[face][2] = vertex_index(slices, slice-1, stack);
face++; face++;
} }
} }
@ -1271,14 +1271,14 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli
/* bottom stack is triangle fan */ /* bottom stack is triangle fan */
for (slice = 1; slice < slices; slice++) for (slice = 1; slice < slices; slice++)
{ {
faces[face][0] = sphere_vertex(slices, slice-1, stack-1); faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = sphere_vertex(slices, slice, stack-1); faces[face][1] = vertex_index(slices, slice, stack-1);
faces[face][2] = vertex; faces[face][2] = vertex;
face++; face++;
} }
faces[face][0] = sphere_vertex(slices, slice-1, stack-1); faces[face][0] = vertex_index(slices, slice-1, stack-1);
faces[face][1] = sphere_vertex(slices, 0, stack-1); faces[face][1] = vertex_index(slices, 0, stack-1);
faces[face][2] = vertex; faces[face][2] = vertex;
free_sincos_table(&phi); free_sincos_table(&phi);
@ -1292,11 +1292,190 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli
HRESULT WINAPI D3DXCreateCylinder(LPDIRECT3DDEVICE9 device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, HRESULT WINAPI D3DXCreateCylinder(LPDIRECT3DDEVICE9 device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices,
UINT stacks, LPD3DXMESH* mesh, LPD3DXBUFFER* adjacency) 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;
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; 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) HRESULT WINAPI D3DXCreateTeapot(LPDIRECT3DDEVICE9 device, LPD3DXMESH *mesh, LPD3DXBUFFER* adjacency)
{ {
FIXME("(%p, %p, %p): stub\n", device, mesh, adjacency); FIXME("(%p, %p, %p): stub\n", device, mesh, adjacency);

View File

@ -1788,7 +1788,7 @@ static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2
char name[256]; char name[256];
hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL); 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) if (hr != D3D_OK)
{ {
skip("Couldn't create cylinder\n"); skip("Couldn't create cylinder\n");
@ -1822,10 +1822,10 @@ static void D3DXCreateCylinderTest(void)
ID3DXMesh* cylinder = NULL; ID3DXMesh* cylinder = NULL;
hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, 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); 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); wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
d3d = Direct3DCreate9(D3D_SDK_VERSION); 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); 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); 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) 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); 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); 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) 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); 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 */ /* Test with length == 0.0f succeeds */
hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL); 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) 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); 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); 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); 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, 0.0f, 0.0f, 0.0f, 2, 1);
test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1); test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1);