Commit 09af2a2b authored by Misha Koshelev's avatar Misha Koshelev Committed by Alexandre Julliard

d3dx9_36: Implement D3DXCreateCylinder.

parent a7ded9a6
...@@ -1112,7 +1112,7 @@ static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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,9 +1292,188 @@ HRESULT WINAPI D3DXCreateSphere(LPDIRECT3DDEVICE9 device, FLOAT radius, UINT sli ...@@ -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, 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;
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) HRESULT WINAPI D3DXCreateTeapot(LPDIRECT3DDEVICE9 device, LPD3DXMESH *mesh, LPD3DXBUFFER* adjacency)
......
...@@ -1788,7 +1788,7 @@ static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment